Skip to content
March 23, 2013 / kiranpatils

Customize contexmenu for TreeViewEx

Challenge:

If you want to modify contextmenu options based on your logic then this post is for you!  For example, you have two options available to access media library one is from CE and one is from PE. Now, when user is accessing Media Library from CE it should show 10 options and from PE, you would like to show 5 options only! And as you know contextmenu comes from Core DB and TreeViewEx is responsible for generating contextmenu, and it  will not allow you to do so!

What, you really have similar challenge in front of you?! Wow, so as we, had similar challenge and we were also searching for solution same as you, and finally we’ve done it with the help of Sitecore support team! Sharing the steps with you!

Solution:

Create a custom TreeviewEx class that derives from standard one and extend it to show your custom menu.

Steps are as under:

1. Create a class based on TreeviewEx one i.e. MyTree

<pre>public class MyTree : TreeviewEx
    {
        protected override void GetContextMenu(string where)
        {
            Assert.ArgumentNotNullOrEmpty(where, "where");
            string source = Sitecore.Context.ClientPage.ClientRequest.Source;
            string control = Sitecore.Context.ClientPage.ClientRequest.Control;
            int num = source.LastIndexOf("_");
            Assert.IsTrue(num >= 0, "Invalid source ID");
            string id = ShortID.Decode(StringUtil.Mid(source, num + 1));
            Item item = Sitecore.Context.ContentDatabase.GetItem(id);
            if (item != null)
            {
                SheerResponse.DisableOutput();
                MyMenu menu = new MyMenu();
                CommandContext context = new CommandContext(item);
                context.Parameters.Add("menu", this.MenuId); // Main thing!
                Menu contextMenu = menu.Build(context);
                contextMenu.AddDivider();
                contextMenu.Add("__Refresh", "Refresh", "Applications/16x16/refresh.png", string.Empty, string.Concat(new object[] { "javascript:Sitecore.Treeview.refresh(\"", source, "\",\"", control, "\",\"", item.ID.ToShortID(), "\")" }), false, string.Empty, MenuItemType.Normal);
                SheerResponse.EnableOutput();
                SheerResponse.ShowContextMenu(control, where, contextMenu);
            }

        }
        public string MenuId
        {
            get;
            set;
        }
    }</pre>

2. Add a string property MenuId to it. As shown above.

3. Create a custom ContextMenu class that replicates logic of the Sitecore.Shell.Framework.ContextMenu one. I.E. MyMenu

4. Modify  public void Build(CommandContext context, Menu menu) method of MyMenu class.

<pre>public void Build(CommandContext context, Menu menu)
        {
            context.IsContextMenu = true;
            if (context.Items.Length == 1)
            {
                Item item = null;
                string id = context.Parameters["menu"]; // Our change!
                if (!string.IsNullOrEmpty(id))
                {
                    item = Context.Database.Items[id];
                }
                string contextMenu = context.Items[0].Appearance.ContextMenu;
                if (!string.IsNullOrEmpty(contextMenu))
                {
                    item = Context.ContentDatabase.Items[contextMenu];
                }
                if (item != null)
                {
                    Context.ClientPage.ClientResponse.DisableOutput();
                    if ((this.ID == null) || (this.ID.Length == 0))
                    {
                        this.ID = "AutoContextMenu";
                    }
                    this.Build(menu, item, context);
                    Context.ClientPage.ClientResponse.EnableOutput();
                }
            }
        }</pre>

5. Override void GetContextMenu(string where) method in MyTree class, full class is shown in Step1.

6.  In core database create a copy of the “/sitecore/content/Applications/Content Editor/Context Menues/Default” item
(MyMenuRoot) and remove unnecessary sub-items from it.

7. In you xml dialogue use the following definition for the TreeView control:


<MyTree ID="Treeview" DataContext="InternalLinkDataContext" Root="True" ContextMenu='Treeview.GetContextMenu
("contextmenu")' MenuId="<id of the MyMenuRoot from step 6>"  /

Just a note :  If you change ID attribute of  TreeView in your XML dialogue e.g. MyTreeView, then you might get this error “Control “Treeview” does not exist on form..” And to resolve that you need to modify the same in ContextMenu attribute as well with same name as your ID e.g. MyTreeView.GetContextMenu(“contextmenu”)

8. Add namespace of  MyTree control to the <controlSources> section in web.config

9. Add your assembly to the <references> section in web.config.

10. That’s it! Build your Sitecore solution and see your changes!

After doing all above steps, we were able to see ContextMenu (I’m sure you too!). But whenever contextmenu was firing a command attached to it. CommandContext was not passing selected command, and after discussion with Sitecore we resolved it as well!

You should override HandleMessage method in your dialogue class and dispatch the message in it. For example:


public override void HandleMessage(Message message)
{
Assert.ArgumentNotNull(message, "message");
string id = message["id"];
Item item;
if (!string.IsNullOrEmpty(id))
{
item=Sitecore.Context.ContentDatabase.GetItem(id);
}
else{
item=this.ImageDataContext.GetFolder();
}
Dispatcher.Dispatch(message, item );
base.HandleMessage(message);
}

Easy and Interesting, correct?! I just love Sitecore architecture! (One of my reason  Why I love Sitecore?!)

Happy Custom Context Menuing! 🙂

PS : Special thanks to  Yuriy Zakharov, Ivan Sheyenko(Sitecore Support) for providing this suggestion and Devashri who did all this investigation and worked on this challenge!

Advertisements

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

%d bloggers like this: