Monday, February 11, 2013

Get / Set field order for SharePoint 2010 list or library

When you build custom SharePoint solutions there are times when you need to create lists/libraries and fields (site columns or list fields) during run-time.

Using the SharePoint 2010 object model to programmatically create site columns, content types or list and library fields is really easy but you will find that the order in which the new fields appear on the item's view- and edit forms depends on the execution order of the code which provisioned the fields.

To illustrate this, imagine you have a document library called ‘Technology’ which contains 2 fields called ‘Name’ and ‘Title’.

An event triggers your code to add 2 new fields to the document library. First the code adds the field ‘Product’ to the library and then the code adds the field ‘Document Summary’ to the library. At this point your library will contain 4 fields in the following order: 1-Name, 2-Title, 3-Product, 4-Document Summary.

Later another event triggers your code to add a field called ‘Product Version’ to the same library. The result will be that the new field will be displayed in position 5 on the view and edit forms.  This is not ideal – as you can see from the image below, the position of the ‘Document Summary’ field should rather be below ‘Product Version’.

image

Fortunately there is an easy way to programmatically control the order in which fields appear on the list item view- and edit forms.

Many thanks to Rahul Sharma for his original post on this topic – I used the basics from his post http://www.directsharepoint.com/2011/11/change-column-order-in-new-and-edit.html and extended it to fit my needs.

The following code illustrates three functions:

  1. Get the display order of all visible fields for a specified list/library
  2. Get the display order of a specific list of fields for a specified list/library
  3. Set the display order of a specific list of fields on a list/library item’ view- and edit forms.

(The code is written in a simple console app. Remember to add a reference to Microsoft.SharePoint.dll and change your console app platform target to 64bit – and add proper exception management)

1-Get the display order of all visible fields for a specified list/library

Based on the scenario described above the result from the code below is:

image

static void Main(string[] args)
{
   using (SPSite site = new SPSite(args[0]))
   {
       Dictionary<string, int> actualfieldsorder = FetchFieldOrder(site.OpenWeb(), "Technology", "Document");
      
       foreach (KeyValuePair<string, int> pair in actualfieldsorder)
       {
          Console.WriteLine(pair.Key + " : " + pair.Value);
       }

       Console.WriteLine("");
       Console.WriteLine("Done");
       Console.ReadKey();
   }
}

private static Dictionary<string, int> FetchFieldOrder(SPWeb web, string listname, string contenttypename)
{
    Dictionary<string, int> fieldsorder = new Dictionary<string, int>();
    SPList list = web.Lists.TryGetList(listname);
    if (list != null)
    {
        SPContentType spct = list.ContentTypes[contenttypename];
            int positionindex = 0;
            foreach (SPField field in spct.Fields)
            {
                if (!field.Hidden && field.Reorderable)
                {
                        if (field.ShowInEditForm == null)
                        {
                                positionindex++;
                                fieldsorder.Add(field.InternalName, positionindex);
                        }
                        else
                        {
                            if ((bool)field.ShowInEditForm)
                            {
                                positionindex++;
                                fieldsorder.Add(field.InternalName, positionindex);
                            }
                        }
                }
            }
    }

    return fieldsorder;
}

2-Get the display order of a specific list of fields for a specified list/library

There might also be situations whereby you want to determine the display order for a specific list of fields in relation to each other. Example, I want to determine whether the ‘Product’ field will appear above the ‘Product Version’ field. I am not interested in any of the other fields.

The code below will return the following result:

image

static void Main(string[] args)
        {
            using (SPSite site = new SPSite(args[0]))
            {
                List<string> fields = new List<string>();
                fields.Add("Product");
                fields.Add("Product_x0020_Version");
                Dictionary<string, int> actualfieldsorder = FetchFieldOrder(site.OpenWeb(), "Technology", "Document",fields);

                foreach (KeyValuePair<string, int> pair in actualfieldsorder)
                {
                    Console.WriteLine(pair.Key + " : " + pair.Value);
                }

                Console.WriteLine("");
                Console.WriteLine("Done");
                Console.ReadKey();
            }
        }

private static Dictionary<string, int> FetchFieldOrder(SPWeb web, string listname, string contenttypename, List<string> checkfields)
{
    Dictionary<string, int> fieldsorder = new Dictionary<string, int>();
    foreach (string fieldname in checkfields)
    {
        fieldsorder.Add(fieldname, 0);
    }
    SPList list = web.Lists.TryGetList(listname);
    if (list != null)
    {
        SPContentType spct = list.ContentTypes[contenttypename];
        int positionindex = 0;
        foreach (SPField field in spct.Fields)
        {
            if (!field.Hidden && field.Reorderable)
            {
                if (field.ShowInEditForm == null)
                {
                    if (fieldsorder.ContainsKey(field.InternalName))
                    {
                        positionindex++;
                        fieldsorder[field.InternalName] = positionindex;
                    }
                }
                else
                {
                    if ((bool)field.ShowInEditForm)
                    {
                        if (fieldsorder.ContainsKey(field.InternalName))
                        {
                            positionindex++;
                            fieldsorder[field.InternalName] = positionindex;
                        }
                    }
                }
            }
        }
    }

    return fieldsorder;
}

3-Set the display order of a specific list of fields on a list/library item’ view- and edit forms

The following code will set the display order of the specified fields. Please note that the parameter ‘CustomOrder’ contains the fields which you want to reorder. The order in which the fields will appear on the view and edit forms is determined by the order in which you programmatically add the fields to the List variable '(CustomOrder). If you want you can change to code to have even more granular control.

image

The code below will result in the following:

image

static void Main(string[] args)
       {
           using (SPSite site = new SPSite(args[0]))
           {
               List<string> CustomOrder = new List<string>();
               CustomOrder.Add("FileLeafRef");
               CustomOrder.Add("Title");
               CustomOrder.Add("Product");
               CustomOrder.Add("Product_x0020_Version");
               CustomOrder.Add("DocumentSummary");

               SetFieldOrder(site.OpenWeb(), "Technology", "Document", CustomOrder);

               Console.WriteLine("");
               Console.WriteLine("Done");
               Console.ReadKey();
           }
       
       }

private static void SetFieldOrder(SPWeb web, string listname, string contenttypename, List<String> CustomOrder)
{
    try
    {
        SPList list = web.Lists.TryGetList(listname);
        if(list!=null)
        {
            Dictionary<Int32, String> listColumnReorder = new Dictionary<Int32, String>();
            int iCounter = 0;
            foreach (string item in CustomOrder)
            {
                if (list.Fields.ContainsField(item))
                {
                    SPField field = list.Fields.GetFieldByInternalName(item);
                    if (field != null)
                    {
                        if (!field.Hidden && field.Reorderable)
                        {
                            if (field.ShowInEditForm == null || (bool)field.ShowInEditForm)
                                {
                                    listColumnReorder.Add(iCounter, field.InternalName);
                                    iCounter++;
                                }
                        }
                    }
                }
            }
            String[] sFields = new String[listColumnReorder.Count];
            foreach (Int32 order in listColumnReorder.Keys)
            {
                sFields[order] = listColumnReorder[order];
            }
            ReOrderColumn(sFields, list.ContentTypes[contenttypename]);
       }
    }
    catch (Exception ex)
    {
        // add your own exception management here...
    }
}

private static void ReOrderColumn(String[] fieldInternalNameArray, SPContentType objContentType)
{
     try
     {
         SPFieldLinkCollection fldLinks = objContentType.FieldLinks;
         fldLinks.Reorder(fieldInternalNameArray);

         objContentType.Update();
     }
     catch (Exception ex)
     {
         // add your own exception management here...
     }
}

1 comments:

vonz said...

Great article! How do you set the display position number of each field? Thanks.

Post a Comment