Friday, October 15, 2010

How to Sort your Multilist Field


Greetings!

Just recently one of the Sitecore implementation partners asked me whether there is a way to have the list of available items on a Multilist field sorted by updated date.
To clarify, by default, the left side is sorted by item name, it is by design.

image

So I did some digging, and have found that it is a very frequent feature request. Another thing I’ve found is that since Sitecore 6 it is actually pretty easy to change this behavior.

First thing I need for that is subclass MultilistEx class which implements is UI part of the Multilist field. This class has a method called GetSelectedItems (introduced since Sitecore 6 release) where the list of unselected items is constructed. Since this method is marked as protected virtual, I can easily override it:

namespace Sitecore.SharedSource.CustomFields
{
   public class SortedMultilist : Sitecore.Shell.Applications.ContentEditor.MultilistEx
   {
      protected override void GetSelectedItems(Item[] sources, out ArrayList selected, out IDictionary unselected)
      {
         Assert.ArgumentNotNull(sources, "sources");
         ListString str = new ListString(this.Value);
         unselected = new SortedList(StringComparer.Ordinal);
         selected = new ArrayList(str.Count);
         int index = 0;
         while (index < str.Count)
         {
            selected.Add(str[index]);
            index++;
         }
         foreach (Item item in sources)
         {
            string str2 = item.ID.ToString();
            index = str.IndexOf(str2);
            if (index >= 0)
            {
               selected[index] = item;
            }
            else
            {
               unselected.Add(GetItemKey(item), item);
            }
         }
      }
      protected virtual string GetItemKey(Item item)
      {
         return MainUtil.GetSortKey(item[FieldIDs.Created]);
      }
   }
}

The only thing I change, actually, is the line where items are added to the “unselected” list. Since the key is used for sorting, I move this outside to a separate method “GetItemKey” where instead of constructing sort key by item.Name as in default implementation, I simply read the “created” date.

After this class is compiled, all I need to define the new “Sorted Multilist” field under core:/sitecore/system/Field types/List Types:

image

The easiest way to do it is to duplicate the existing Multilist item ;-)

I should mention that adding complex sorting rules will definitely slow down you multilist, so you have to be very careful.

Also, there is a very handy FilteredMultilist that is already on shared source. It gives you ability to refine the left side of Multilist, so you may never need it sorted at all.

no_filter[1]

Enjoy!