The Requirement
Our clients have ’subject’ and ’function’ Metadata fields within their web page. They wanted to be able to content manage this subject and function list . They then wanted to be able to assign a subset of these function and subject keywords into each web page item (so all the subjects and functions are common to the whole site).
The Problem
The cleanest solution to this problem was to define a bunch of simple text items for each of the subjects and functions within specfic folder items. We would then create two multi lists in the Metadata base template (one for subject and one for function) and point them at these respective source directories.
Now think of the situation: We have 5 subjects and 3 functions on average per web page. In the background, we are going to have to pull out data from 8 related content items every time we load a given page. We did not want to do this so we devised a simple work-around that would let us retain the useability of the method discussed above but also ave all this related content available on the one item when it needs to be served up.
The Solution (I will be using a simple ‘Category’ multilist example as a demo here)
We added two hidden (not visible to author) text field within the Metadata base template to correspond with each multilist. These two text fields will contain the content (not the Id’s) of the ‘Description’ field of the referenced items seperating each with a ‘|’ delimeter as can be seen below.

The categories associate to a simple text field item which must have a field named ‘Description’ within it:

All the categories should lie within a common folder item so that we can point our multilist source at that folder:

In the template that holds the multilist, make sure that you create a text field with the name ‘chosen ‘ + <multilist name>. I.e. in our example, our multilist is named ‘Categories’, so our hidden text field will be called ‘Chosen Categories’

Now we create an OnSaving event which does the following:
1. Check if the item thats being saved contains any multilists
2. If 1 = true, then for each multilist named <name> in the current item
3. Check if there is a field named ‘Chosen ‘ + <name> (of the current multilist) from 2
4. If 3 = true, then clear the ‘Chosen ‘ + <name> field of its content; retrieve all the items referenced by the current multilist; For each of these items check if a ‘Description’ field exists; if ‘Description’ exists and there is content within it, add this content to ‘Chosen ‘ + <name>
I have pasted the code for the ItemOnSavingEvents.cs class here (sorry about the indentation, copy/paste into blog isnt the best):
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Sitecore;
using Sitecore.Data.Events;
using Sitecore.Data;
using System.Collections;
namespace SitecoreSCD1Labs
{
public class ItemOnSavingEvents
{
public void OnItemSavingPopulateHidenFields(object sender, EventArgs args)
{
Sitecore.Data.Items.Item item = Sitecore.Events.Event.ExtractParameter(args, 0) as Sitecore.Data.Items.Item;
Sitecore.Collections.FieldCollection fields = item.Fields;
foreach( Sitecore.Data.Fields.Field field in fields ) {
if (field.Type == “multilist”)
{
Sitecore.Data.Fields.MultilistField mlf = (Sitecore.Data.Fields.MultilistField)field;
String fieldname = field.Name;
if( item.Fields["chosen " + fieldname] != null ) { //Hidden field for corresponding multilist exists
Sitecore.Data.Fields.Field hiddenField = item.Fields["chosen " + fieldname];
hiddenField.SetValue(“”, false);
//Populate the hidden field with the descriptions from the related items (pipe delimitered)
String[] relatedItemGuids = mlf.Items;
foreach (String guid in relatedItemGuids)
{
Sitecore.Data.Database currentDB = Sitecore.Configuration.Factory.GetDatabase(“master”);
Sitecore.Data.Items.Item relatedItem = currentDB.Items.GetItem(guid); if (relatedItem != null)
{
if (relatedItem.Fields["description"] != null)
if (hiddenField.ToString() == “”)
hiddenField.SetValue(relatedItem.Fields["description"].ToString(), false);
else
hiddenField.SetValue(hiddenField.ToString() + “|” + relatedItem.Fields["description"].ToString(), false); }
}
}
}
}
}
}
}
Add a web.config entry in the Item onsave event to run your code:<event name=”item:saving”>
<handler type=”SitecoreSCD1Labs.ItemOnSavingEvents, SitecoreSCD1Labs” method=”OnItemSavingPopulateHidenFields” />
</event>Drawbacks of this solutionUnfortunately if the content author changes an existing subject or function then the current items will not automatically change to reflect the new update. The new change will only get reflected on existing items once those items get edited for any reason and re-saved (I have found that some edit needs to be made, i.e. even a smal re-sort of one of the metadata multilist fields, otherwise the item:onsave event does not fire even if save is clicked). In our case the user will most likely only add new subjects and functions and not change existing ones.