Wednesday, September 15, 2010

Keeping the Treelist organized


On a project I was working on recently all the banners were put into a common folder. In the common folder was a hierarchical structure, which would make it easier to find banners when I wanted to select them in my banners field. On the offside, if you have a lot of banners, it can become very difficult to find the one you want to change.

Current situation









In my case it would be sufficient if I could have the name of the parent item in front of the selected item.

To accomplish this, I needed to complete 3 tasks:
  1. Create a custom class that inherits the TreeList
  2. In the Core database, create the new field type
  3. Set our field type in the template
Create a custom class
This custom class needs to override the OnLoad method, since that calls the method we are actually interested in: RestoreState.
protected override void OnLoad(EventArgs args)
{
    base.OnLoad(args);
    Assert.ArgumentNotNull(args, "args");
    if (!Sitecore.Context.ClientPage.IsEvent)
    {
        this.RestoreState();
    }
}

Then we pretty much keep the original RestoreState the way it was as well, except for a few lines.
private void RestoreState()
{
    Listbox _listBox = (Listbox)FindControl(this.ID = "_selected");
    string[] strArray = this.Value.Split(new char[]{'|'});
    _listBox.Controls.Clear();
    if (strArray.Length > 0)
    {
        Database contentDatabase = Sitecore.Context.ContentDatabase;
        if (!string.IsNullOrEmpty(this.DatabaseName))
        {
            contentDatabase = Factory.GetDatabase(this.DatabaseName);
        }

        for (int i=0; i < strArray.Length; i++)
        {
            string str = strArray[i];
            if (!string.IsNullOrEmpty(str))
            {
                ListItem child = new ListItem();
                child.ID = Sitecore.Web.UI.HtmlControls.Control.GetUniqueID("I");
                _listBox.Controls.Add(child);
                child.Value = child.ID + "|"+ str;
                Item item = contentDatabase.GetItem(str);
                if (item != null)
                {
                    child.Header = item.Parent.DisplayName + ":" + item.DisplayName;
                }
                else
                {
                    child.Header = str + ' ' + Translate.Text("[Item not found]");
                }
            }
        }
        SheerResponse.Refresh(_listBox);
    }
}

Because the base.OnLoad() runs first, the listbox is already filled. To prevent it from containing double values, we need to clear it first. Then we run through the selected values again, putting the displayname of its parent in front.

Now, all we need to do is add the following to the web.config, in the <controlsources> node.
<source mode="on" namespace="CustomTreeList" assembly="CustomTreeList" prefix="MyProject" />

Create the field type
What I did here was duplicate the TreeList type in the Core database, and set the control field to what we just added in the web.config, followed by the classname.

Set the field type
In the template where we have the field, we can now select the Custom Treelist we just added.

If we then check the banner field again, we get the following:

Thank you for reading, I hope this blog helps you.

If you have any suggestions or a better way, please let me know.

1 comment:

  1. To cause links in this field type to appear in the links database, you may want to duplicate the existing treelist entry in the /App_Config/FieldTypes.config file, and change only the name attribute in the new line to match the name of your custom field type.

    ReplyDelete

Thank you for responding!