Sitecore Custom Field Type - Filtered MultiList

Posted Thursday, February 28, 2008 7:30 PM by Kevin

For a project I'm currently working on, the client wanted to have a multilist field on one of their templates but have the list of items displayed on the "All" side filtered according to some complex rules.  Normally, you can filter that list by assigning an XPath query to the Source property of the field.  In this case though, the filtering rules were going to be very difficult to implement with XPath and I felt some .NET code was in order.

The solution I chose was to build a custom field type, derive it from the existing MultiList field type, and place my filtering therein.  Turns out all I had to do was override the GetItems method on Sitecore.Shell.Applications.ContentEditor.MultilistEx, call the base implementation to get the initial list of items, then iterate through them - discarding the ones I don't want before returning the list.

Here is a full example using the workflow state code I posted a couple of weeks ago:

public class FilteredMultiList : Sitecore.Shell.Applications.ContentEditor.MultilistEx

{

    protected override Item[] GetItems(Item current)

    {

        List<Item> filteredItems = new List<Item>();

 

        // Call the base class to get the original list.

        Item[] items = base.GetItems(current);

 

        // Loop through the items and filter them.

        foreach (Item item in items)

        {

            // Get the master database.

            Database masterDatabase = Factory.GetDatabase("master");

 

            // We want to exclude items that are not in the final workflow state...

            IWorkflow workflow = masterDatabase.WorkflowProvider.GetWorkflow(item);

            WorkflowState state = workflow.GetState(item);

            if (state == null) continue;

            if (!state.FinalState) continue;

 

            // If we make it this far, add the item to the filtered list.

            filteredItems.Add(item);

        }

 

        // Return the filtered list.

        return filteredItems.ToArray();

    }

If you've never done a custom field type before, installation requires two steps...  First, edit web.config and search for the <controlSources> section.  Add an entry for the assembly and namespace containing your field types.  For example:

<source mode="on" namespace="Your.Namespace" assembly="Your.Assembly" prefix="Prefix" />

What this does is associates the prefix "Prefix" (you can use any name you want) with all field types in Your.Namespace inside Your.Assembly.dll.  You'll see in a second how this prefix is used.

Now, in content editor - expand the System node, right-click on Field Types, select New -> Add From Template.  Expand the System folder, Templates folder, and select the "Template field type" template.  Name the field type whatever you want it to show up when editing a template in template manager.

Fill in the Control field using Prefix:Class syntax where Prefix is the prefix used in web.config and Class is the name of your class that implements this field type.

Now you can go edit a template and add a field using your new field type.  Set the source as usual, but when the user edits an item based on your template, the new field will filter the source list using whatever code you placed in the overridden GetItems!

Filed under:

Comments

No Comments