How to Remove Up/Down Arrow Icons from a TreeList field in Sitecore

I was recently requested to update one of our client’s TreeList fields so that the Selected list was alphabetically sorted. Part of this change was to hide those blue up/down arrow buttons to the right of the selected list on the field. While it’s not as easy as I was hoping it would be, I found a solution for this. It involves rendering the field in a completely different way – through code.

2015-12-01 09_02_06-Sitecore

First, add a new class file for your field type. I put mine under a Fields folder in my project, but it can be anywhere technically. Make no changes to the class at this point.

Next, create a new field type in Sitecore. To do that, in the Core database, navigate to sitecore/system/Field types/List Types. Right click the List Type folder and create your list type – I believe it should be created from the System/Templates/Template field type. Once created, fill in the Assembly (Visual Studio Project name) and Class (Visual Studio path to your field type class) fields. Save and publish the list type.

 

2015-11-30 18_13_26-Sitecore

 

Next,we will implement the rendering change for our new field. I used Reflector to get the source from Treeist.cs. It’s actually in the OnLoad event, which I found interesting. Anyway, I have supplied a code sample – note it’s rather long; Sitecore is basically gathering all the info, and assembling the HTML dynamically:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using Sitecore;
using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Globalization;
using Sitecore.Resources;
using Sitecore.SecurityModel;
using Sitecore.Shell.Applications.ContentEditor;
using Sitecore.Web.UI.HtmlControls;
using Sitecore.Web.UI.Sheer;
using Sitecore.Web.UI.WebControls;

namespace Your.Namespace.Here
{
    public class AlphaTreeList : TreeList
    {
        private Listbox _listBox;

        protected override void OnLoad(EventArgs e)
        {
            RenderTreeListWithoutUpDownArrows(e);
        }

        private string FormTemplateFilterForDisplay()
        {
            // Taken from TreeList.cs using reflector

            if ((string.IsNullOrEmpty(this.IncludeTemplatesForDisplay) && string.IsNullOrEmpty(this.ExcludeTemplatesForDisplay)) && (string.IsNullOrEmpty(this.IncludeItemsForDisplay) && string.IsNullOrEmpty(this.ExcludeItemsForDisplay)))
            {
                return string.Empty;
            }
            string str = string.Empty;
            string str2 = ("," + this.IncludeTemplatesForDisplay + ",").ToLowerInvariant();
            string str3 = ("," + this.ExcludeTemplatesForDisplay + ",").ToLowerInvariant();
            string str4 = "," + this.IncludeItemsForDisplay + ",";
            string str5 = "," + this.ExcludeItemsForDisplay + ",";
            if (!string.IsNullOrEmpty(this.IncludeTemplatesForDisplay))
            {
                if (!string.IsNullOrEmpty(str))
                {
                    str = str + " and ";
                }
                str = str + string.Format("(contains('{0}', ',' + @@templateid + ',') or contains('{0}', ',' + @@templatekey + ','))", str2);
            }
            if (!string.IsNullOrEmpty(this.ExcludeTemplatesForDisplay))
            {
                if (!string.IsNullOrEmpty(str))
                {
                    str = str + " and ";
                }
                str = str + string.Format("not (contains('{0}', ',' + @@templateid + ',') or contains('{0}', ',' + @@templatekey + ','))", str3);
            }
            if (!string.IsNullOrEmpty(this.IncludeItemsForDisplay))
            {
                if (!string.IsNullOrEmpty(str))
                {
                    str = str + " and ";
                }
                str = str + string.Format("(contains('{0}', ',' + @@id + ',') or contains('{0}', ',' + @@key + ','))", str4);
            }
            if (string.IsNullOrEmpty(this.ExcludeItemsForDisplay))
            {
                return str;
            }
            if (!string.IsNullOrEmpty(str))
            {
                str = str + " and ";
            }
            return (str + string.Format("not (contains('{0}', ',' + @@id + ',') or contains('{0}', ',' + @@key + ','))", str5));
        }

        private void RenderTreeListWithoutUpDownArrows(EventArgs args)
        {
            // Taken from TreeList.cs OnLoad() using reflector

            Assert.ArgumentNotNull(args, "args");

            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                this.SetProperties();
                GridPanel panel = new GridPanel();
                this.Controls.Add(panel);
                panel.Columns = 4;
                this.GetControlAttributes();
                foreach (string str in base.Attributes.Keys)
                {
                    panel.Attributes.Add(str, base.Attributes[str]);
                }
                panel.Attributes["id"] = this.ID;
                panel.Style["margin"] = "0px 0px 4px 0px";
                base.SetViewStateString("ID", this.ID);
                Literal literal = new Literal("All")
                {
                    Class = "scContentControlMultilistCaption"
                };
                panel.Controls.Add(literal);
                panel.SetExtensibleProperty(literal, "Width", "50%");
                panel.SetExtensibleProperty(literal, "Row.Height", "20px");
                LiteralControl control = new LiteralControl(Images.GetSpacer(0x18, 1));
                panel.Controls.Add(control);
                panel.SetExtensibleProperty(control, "Width", "24px");
                literal = new Literal("Selected")
                {
                    Class = "scContentControlMultilistCaption"
                };
                panel.Controls.Add(literal);
                panel.SetExtensibleProperty(literal, "Width", "50%");
                control = new LiteralControl(Images.GetSpacer(0x18, 1));
                panel.Controls.Add(control);
                panel.SetExtensibleProperty(control, "Width", "24px");
                Scrollbox scrollbox = new Scrollbox();
                scrollbox.ID = Sitecore.Web.UI.HtmlControls.Control.GetUniqueID("S");
                panel.Controls.Add(scrollbox);
                if (!UIUtil.IsIE())
                {
                    scrollbox.Padding = "0px";
                }
                scrollbox.Style["border"] = UIUtil.IsIE() ? ((string)"3px window-inset") : ((string)"2px inset silver");
                object obj2 = base.ServerProperties["SetMasters.FixBorder"];
                if (((UIUtil.IsFirefox() && (obj2 != null)) && (obj2.ToString() == "true")) || UIUtil.IsWebkit())
                {
                    scrollbox.Style["height"] = "100%";
                    scrollbox.Style["-moz-box-sizing"] = "border-box";
                }
                panel.SetExtensibleProperty(scrollbox, "rowspan", "2");
                panel.SetExtensibleProperty(scrollbox, "VAlign", "top");
                TreeviewEx ex = new TreeviewEx();
                ex.ID = this.ID + "_all";
                scrollbox.Controls.Add(ex);
                ex.DblClick = this.ID + ".Add";
                ex.AllowDragging = false;
                ImageBuilder builder = new ImageBuilder
                {
                    Src = "Applications/16x16/nav_right_blue.png",
                    ID = this.ID + "_right",
                    Width = 0x10,
                    Height = 0x10,
                    Margin = UIUtil.IsIE() ? ((string)"2px") : ((string)"2px 0px 2px 2px"),
                    OnClick = Sitecore.Context.ClientPage.GetClientEvent(this.ID + ".Add")
                };
                ImageBuilder builder2 = new ImageBuilder
                {
                    Src = "Applications/16x16/nav_left_blue.png",
                    ID = this.ID + "_left",
                    Width = 0x10,
                    Height = 0x10,
                    Margin = UIUtil.IsIE() ? ((string)"2px") : ((string)"2px 0px 2px 2px"),
                    OnClick = Sitecore.Context.ClientPage.GetClientEvent(this.ID + ".Remove")
                };
                LiteralControl control2 = new LiteralControl(builder + "<br/>" + builder2);
                panel.Controls.Add(control2);
                panel.SetExtensibleProperty(control2, "Width", "30");
                panel.SetExtensibleProperty(control2, "Align", "center");
                panel.SetExtensibleProperty(control2, "VAlign", "top");
                panel.SetExtensibleProperty(control2, "rowspan", "2");
                Listbox listbox = new Listbox();
                panel.Controls.Add(listbox);
                panel.SetExtensibleProperty(listbox, "VAlign", "top");
                panel.SetExtensibleProperty(listbox, "Height", "100%");
                this._listBox = listbox;
                listbox.ID = this.ID + "_selected";
                listbox.DblClick = this.ID + ".Remove";
                listbox.Style["width"] = "100%";
                listbox.Size = "10";
                listbox.Attributes["onchange"] = "javascript:document.getElementById('" + this.ID +
                                                 "_help').innerHTML=this.selectedIndex>=0?this.options[this.selectedIndex].innerHTML:''";
                listbox.Attributes["class"] = "scContentControlMultilistBox";
                this._listBox.TrackModified = false;
                ex.Enabled = !this.ReadOnly;
                listbox.Disabled = this.ReadOnly;
                panel.SetExtensibleProperty(control2, "Width", "30");
                panel.SetExtensibleProperty(control2, "Align", "center");
                panel.SetExtensibleProperty(control2, "VAlign", "top");
                panel.SetExtensibleProperty(control2, "rowspan", "2");
                panel.Controls.Add(new LiteralControl("
")); DataContext context = new DataContext(); panel.Controls.Add(context); context.ID = Sitecore.Web.UI.HtmlControls.Control.GetUniqueID("D"); context.Filter = this.FormTemplateFilterForDisplay(); ex.DataContext = context.ID; ex.DisplayFieldName = this.DisplayFieldName; context.DataViewName = "Master"; if (!string.IsNullOrEmpty(this.DatabaseName)) { context.Parameters = "databasename=" + this.DatabaseName; } context.Root = this.DataSource; context.Language = Language.Parse(this.ItemLanguage); panel.Fixed = true; ex.ShowRoot = true; panel.SetExtensibleProperty(scrollbox, "Height", "100%"); this.RestoreState(); } } private void RestoreState() { // Taken from TreeList.cs using reflector string[] strArray = this.Value.Split((char[])new char[] { '|' }); 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 = (int)(i + 1)) { string path = strArray[i]; if (!string.IsNullOrEmpty(path)) { ListItem item = new ListItem(); item.ID = Sitecore.Web.UI.HtmlControls.Control.GetUniqueID("I"); this._listBox.Controls.Add(item); item.Value = item.ID + "|" + path; Item item2 = contentDatabase.GetItem(path); if (item2 != null) { item.Header = this.GetHeaderValue(item2); } else { item.Header = path + ' ' + Translate.Text("[Item not found]"); } } } SheerResponse.Refresh(this._listBox); } } private void SetProperties() { // Taken from TreeList.cs using reflector string id = StringUtil.GetString((string[])new string[] { this.Source }); if (Sitecore.Data.ID.IsID(id)) { this.DataSource = this.Source; } else if ((this.Source != null) && !id.Trim().StartsWith("/", StringComparison.OrdinalIgnoreCase)) { this.ExcludeTemplatesForSelection = StringUtil.ExtractParameter("ExcludeTemplatesForSelection", this.Source).Trim(); this.IncludeTemplatesForSelection = StringUtil.ExtractParameter("IncludeTemplatesForSelection", this.Source).Trim(); this.IncludeTemplatesForDisplay = StringUtil.ExtractParameter("IncludeTemplatesForDisplay", this.Source).Trim(); this.ExcludeTemplatesForDisplay = StringUtil.ExtractParameter("ExcludeTemplatesForDisplay", this.Source).Trim(); this.ExcludeItemsForDisplay = StringUtil.ExtractParameter("ExcludeItemsForDisplay", this.Source).Trim(); this.IncludeItemsForDisplay = StringUtil.ExtractParameter("IncludeItemsForDisplay", this.Source).Trim(); string str2 = StringUtil.ExtractParameter("AllowMultipleSelection", this.Source).Trim().ToLowerInvariant(); this.AllowMultipleSelection = (bool)(string.Compare(str2, "yes", StringComparison.InvariantCultureIgnoreCase) == 0); this.DataSource = StringUtil.ExtractParameter("DataSource", this.Source).Trim().ToLowerInvariant(); this.DatabaseName = StringUtil.ExtractParameter("databasename", this.Source).Trim().ToLowerInvariant(); } else { this.DataSource = this.Source; } } } }

The above code is a bit different from the source I pulled with reflector. I had to change a number of unrecognizable method calls, like get_Item get_ID. For example,

panel.Attributes.set_Item("id", this.get_ID());

would become

panel.Attributes["id"] = this.ID;

Also, I did not call base.OnLoad() after the rendering code above. If you do, you may get errors in Sitecore. Looking at the logs you might get errors saying, “Multiple controls with the same ID ‘Field[SomeNumber]_all’ were found.”. Make sure not to render the field twice. 😉

Finally, notice that the RenderTrreeListWithoutUpDownArrows() submethod is missing the code that adds the up and down arrows – this was my objective:

ImageBuilder builder3 = new ImageBuilder
            {
                Src = "Applications/16x16/nav_up_blue.png",
                ID = this.ID + "_up",
                Width = 0x10,
                Height = 0x10,
                Margin = "2px",
                OnClick = Sitecore.Context.ClientPage.GetClientEvent(this.ID + ".Up")
            };
            ImageBuilder builder4 = new ImageBuilder
            {
                Src = "Applications/16x16/nav_down_blue.png",
                ID = this.ID + "_down",
                Width = 0x10,
                Height = 0x10,
                Margin = "2px",
                OnClick = Sitecore.Context.ClientPage.GetClientEvent(this.ID + ".Down")
            };
            control2 = new LiteralControl(builder3 + "<br/>" + builder4);
            panel.Controls.Add(control2);

You could also do this for left and right arrows, or another element of the field.

Finally, change the field type on your item’s template to your new custom field type, and publish.

The result is a custom TreeList field that simply does not have up/down arrows.

2015-12-01 09_05_42-Sitecore

I hope this helps you. I will write another blog about how I handled sorting my custom TreeList field’s selected section alphabetically, so look for that  to pop up soon. If you have any questions, feel free to comment.

 

Advertisements

One thought on “How to Remove Up/Down Arrow Icons from a TreeList field in Sitecore

  1. Hi All – WordPress wasn’t acting nicely when I edited this post. You will notice in the middle of the massive code block, there appears to be something missing.

    This:

    panel.Controls.Add(new LiteralControl(”
    “));

    Should be this (literally wouldn’t let me post the full text in a comment or render the image):
    https://onedrive.live.com/redir?resid=1BE5BB0A9B5612F!3441&authkey=!AHgdg308cZtl42Q&v=3&ithint=photo%2cpng

    Perhaps figuring what happened there will be covered in another blog post… Oh WordPress, you have issues.. Thanks!

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s