Creating Hierarchical Menus with a CustomAction in SharePoint

It’s a fairly known technique to make use of CustomActions to add elements to the out-of-the-box user interface of SharePoint: you can add menu items to the Site Actions menu, you can add links on the Site Settings page, etc. The following piece of XML is the manifest of a feature that will add a new menu item to the Site Actions menu:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <CustomAction
        Id="{B0B5A0CB-7FBE-4dd6-9B2A-2B1E1321B8F9}"
        Location="Microsoft.SharePoint.StandardMenu"
        GroupId="SiteActions"
        Title="Dummy Menu Item"> 
    <UrlAction
        Url="/_layouts/dummy.aspx"/>   
    </CustomAction>
</Elements>

For a more detailed description of CustomActions, I recommend following articles:

Another variation on this technique is to provide a reference to a class, instead of having fixed UI element specified in the XML. The following piece of XML points to the class ListSettingsMenu in the DemoCustomAction assembly.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <CustomAction 
        Id="{42550415-FD08-4f1f-BAE6-93CCB2A2DE60}"
        Location="Microsoft.SharePoint.StandardMenu"
        GroupId="SiteActions"
        ControlAssembly="DemoCustomAction"
        ControlClass="DemoCustomAction.ListSettingsMenu">
    </CustomAction>
</Elements>

The cool thing is that you now can write code that will render the UI element; it’s even possible to create a hierarchical menu. The following implementation of the ListSettingsMenu class, in combination with the XML from above, is adding one extra menu item to the Site Actions menu (List Settings). This new menu item will contain a sub menu item for every list on the site, these sub menu items will point to the settings pages of the corresponding lists. The ListSettingsMenu class inherits from the WebControl class, by overriding the CreateChildControls method, you can instantiate SubMenuTemplate and MenuItemTemplate instances, and add them to the Controls collection. An instance of the SubMenuItemTemplate class corresponds with a menu item that contains sub menu items. These sub menu items are instances of the MenuItemTemplate class. By setting the Text, Description and ImageUrl properties of these classes, you can specify how the menu items will be rendered in the SharePoint UI. The ClientOnClickNavigateUrl of the MenuItemTemplate class specifies the URL for the menu item itself.

namespace DemoCustomAction
{
    public class ListSettingsMenu: System.Web.UI.WebControls.WebControl
    {
        protected override void CreateChildControls()
        {
            SubMenuTemplate listSettings = new SubMenuTemplate();
            listSettings.Text = "List Settings";
            listSettings.Description = "Manage settings for lists on this site";
            listSettings.ImageUrl = "/_layouts/images/lg_ICASCX.gif";

            foreach (SPList list in SPContext.Current.Web.Lists)
            {
                if (!list.Hidden)
                {
                    MenuItemTemplate listItem = new MenuItemTemplate();
                    listItem.Text = list.Title;
                    listItem.Description = string.Format(
                        "Manage settings for {0}", list.Title);
                    listItem.ImageUrl = list.ImageUrl;

                    string url = string.Format(
                        "{0}/_layouts/listedit.aspx?List={{{1}}}",
                        SPContext.Current.Web.Url, list.ID.ToString());
                    listItem.ClientOnClickNavigateUrl = url;

                    listSettings.Controls.Add(listItem);
                }
            }

            this.Controls.Add(listSettings);
        }
    }
}

To deploy all of this first of all the assembly (DLL) that contains the ListSettingsMenu should be built and copied either to the Global Assembly Cache or the BIN folder of the SharePoint site where you’d like to use it. Secondly the feature should be installed by copying the feature files and running STSADM -o installfeature -n featurename. Finally a SafeControl element must be added to the web.config, so the ListSettingsMenu control is marked as safe. If you forget the last step, you won’t get an error, but the extra menu item won’t be rendered. Here is a screenshot of the result:

The only caveat for this technique seems to be that you can’t use it to add a hierarchical menu in a EditControlBlock (ECB) CustomAction. The menu items of the ECB are rendered using Javascript. If you want to see a full blown example of what you can accomplish, check out the latest addition to the SmartTools project: the Enhanced Site Actions menu.

No Comments