SharePoint Menus in C#

There are a lot of great articles out there that talk about how you can leverage the SharePoint style of drop-down menus (you know that cool looking javascript menu) and creating your own. All of them require you to write some HTML and/or JavaScript and embed this into a CEWP on a page. This is fine, but when you’re building your own Web Parts, you might want something a little simpler.

In working on the SharePoint Forums Web Part, I wanted to create a drop-down menu populated by some of the links in the system and the categories and forums so someone could easily jump to a forum immediately. Most forums use a standard web drop-down list but since I had the SharePoint menu javascript already at my disposal I thought I would use it. So I put together this little class that creates me a menu, lets me add items to it, then just spits out the HTML that I can render to my page. Here’s the full class:

    1 /*

    2  * SharePointMenus.cs

    3  * Dynamic SharePoint-style menus in C#

    4  *

    5  * Copyright (c) 2006 by Bil Simser, bsimser@shaw.ca

    6  *

    7  * This work is licensed under the Creative Commons

    8  * Attribution-NonCommercial-ShareAlike 2.5 License.

    9  *

   10  * To view a copy of this license, visit

   11  * http://creativecommons.org/licenses/by-nc-sa/2.5/

   12  * or send a letter to Creative Commons, 559 Nathan

   13  * Abbott Way, Stanford, California 94305, USA.

   14 */

   15 

   16 using System;

   17 using System.Text;

   18 using System.Xml;

   19 

   20 namespace BilSimser.SharePoint.WebParts.Forums.Utility

   21 {

   22     /// <summary>

   23     /// Small helper class that will build out a menu in

   24     /// the SharePoint drop down style for adding to HTML output.

   25     /// </summary>

   26     public class SharePointMenu

   27     {

   28         #region Fields

   29 

   30         private string _header;

   31         private XmlElement _currentNode;

   32         private XmlElement _rootNode;

   33         private XmlDocument _xmlDocument;

   34 

   35         #endregion

   36 

   37         #region Constructors

   38 

   39         public SharePointMenu(string title)

   40         {

   41             createHeader(title);

   42             createXmlDocument();

   43         }

   44 

   45         #endregion

   46 

   47         #region Properties

   48 

   49         private string Header

   50         {

   51             set { _header = value; }

   52             get { return _header; }

   53         }

   54 

   55         #endregion

   56 

   57         #region Public Methods

   58 

   59         public void AddMenuItem(string title, string url)

   60         {

   61             AddMenuItem(title, url, string.Empty);

   62         }

   63 

   64         public void AddMenuItem(string title, string url, string imageUrl)

   65         {

   66             XmlElement childNode = _xmlDocument.CreateElement("ie:menuitem", "http://www.tempuri.com");

   67             childNode.SetAttribute("id", "MSO_MyMenu_Link1");

   68             childNode.SetAttribute("title", title);

   69             if(imageUrl != string.Empty)

   70                 childNode.SetAttribute("iconSrc", imageUrl);

   71             childNode.SetAttribute("onMenuClick", string.Format("javascript:window.location.href='{0}';", url));

   72             childNode.InnerText = title;

   73             _currentNode.AppendChild(childNode);

   74         }

   75 

   76         public void AddSeparator()

   77         {

   78             XmlElement childNode = _xmlDocument.CreateElement("ie:menuitem", "http://www.tempuri.com");

   79             childNode.SetAttribute("type", "separator");

   80             _currentNode.AppendChild(childNode);

   81         }

   82 

   83         public void AddSubMenu(string title)

   84         {

   85             AddSubMenu(title, string.Empty);

   86         }

   87 

   88         public void AddSubMenu(string title, string imageUrl)

   89         {

   90             XmlElement childNode = _xmlDocument.CreateElement("ie:menuitem", "http://www.tempuri.com");

   91             childNode.SetAttribute("type", "submenu");

   92             if(imageUrl != string.Empty)

   93                 childNode.SetAttribute("iconSrc", imageUrl);

   94             _currentNode.AppendChild(childNode);

   95             _currentNode = childNode;

   96             AddLabel(title);

   97         }

   98 

   99         public void CloseSubMenu()

  100         {

  101             _currentNode = _rootNode;

  102         }

  103 

  104         public void AddLabel(string title)

  105         {

  106             XmlElement childNode = _xmlDocument.CreateElement("ie:menuitem", "http://www.tempuri.com");

  107             childNode.SetAttribute("type", "label");

  108             childNode.InnerText = title;

  109             _currentNode.AppendChild(childNode);

  110         }

  111 

  112         public override string ToString()

  113         {

  114             StringBuilder sb = new StringBuilder();

  115             sb.Append(Header);

  116             sb.Append(_xmlDocument.InnerXml);

  117             return sb.ToString();

  118         }

  119 

  120         #endregion

  121 

  122         #region Private Methods

  123 

  124         private void createXmlDocument()

  125         {

  126             _xmlDocument = new XmlDocument();

  127             _rootNode = _xmlDocument.CreateElement("menu", "http://www.tempuri.com");

  128             _rootNode.SetAttribute("id", "MSO_MyMenu");

  129             _rootNode.SetAttribute("class", "ms-SrvMenuUI");

  130             _xmlDocument.AppendChild(_rootNode);

  131             _currentNode = _rootNode;

  132         }

  133 

  134         private void createHeader(string title)

  135         {

  136             Header = string.Format("<div class=\"ms-HoverCellInActive\" "+

  137                 "onmouseover=\"this.className='ms-HoverCellActive'\""+

  138                 "onmouseout=\"this.className='ms-HoverCellInActive'\">"+

  139                 "<a id=\"MSO_MyMenuLink\" title=\"{0}\" style=\'CURSOR: hand\''+

  140                 "onclick=\"MSOWebPartPage_OpenMenu(MSO_MyMenu, this);\""+

  141                 "tabindex=\"0\">{0}<img alt=\"{0}\" src=\"/_layouts/images/menudark.gif\""+

  142                 "align=\"absBottom\"></a></div>", title);

  143         }

  144         #endregion

  145     }

  146 }

It’s not beautiful and there are a lot of improvements you can make. For example, some of the names are hard coded and should be generated dynamically and keeping track of the submenu levels should be something managed outside of the class. However it works and is easy to use.

To use it, just drop this class into your project and you can create a menu with a few lines of code like this:

    7 public class TestMenu

    8 {

    9     public void CreateHtmlMenu()

   10     {

   11         SharePointMenu menu = new SharePointMenu("My Menu");

   12         menu.AddMenuItem("First Item", "http://www.microsoft.com");

   13         menu.AddMenuItem("Second Item", "http://www.slashdot.org");

   14         menu.AddSeparator();

   15         menu.AddMenuItem("Last Item", "http://www.example.com");

   16     }

   17 }

That will get you a simple menu with a few items. Then in your RenderWebPart, or wherever you’re writing out the Web Part contents just write it out:

   19 public override void RenderWebPart(HtmlTextWriter writer)

   20 {

   21     SharePointMenu menu = new SharePointMenu("My Menu");

   22     menu.AddMenuItem("First Item", "http://www.microsoft.com");

   23     menu.AddMenuItem("Second Item", "http://www.slashdot.org");

   24     menu.AddSeparator();

   25     menu.AddMenuItem("Last Item", "http://www.example.com");

   26     writer.WriteLine(menu.ToString());

   27 }

You can also create multiple level menus and submenus. Just call the AddSubMenu method(s) in the class (with or without an image). When you call AddSubMenu, any future calls to AddMenuItem will just add it to that submenu. When you want to back out of the menu, just call the CloseSubMenu method. Like I said, it’s not pretty as it really only supports 1 level of menus and will always back out to the root. However it can be modified and updated with a little work to support unlimited submenus, dynamic generation of IDs, etc. Use your imagination.

Here’s the menu for the SharePoint Forums Web Part which sparked creating this class. The categories and forums are dynamically generated based on what the user can see, etc. and the menu is built up based on options in the system and what the user can do. Looks pretty slick and only took a few lines of code:

sharepointmenus01

So have fun with it and feel free to modify it. If you do extend/enhance it let me know and I’ll update the resource. You can grab the class file here for use in your program. It’s released under the Creative Commons License.

3 Comments

  • Excellent! The only problem I found is that if you put more than one menus in the same webpart they don't work.

  • How can i increase the width of the Menu

  • Great!!! i need to increase the width of the Menu Items . I have applied a class for the menu item

    childNode.SetAttribute("class", "testingstyle")
    i am able to change the color and font . but no luck increasing the width !!! This is in SP2010
    Please help :(
    Thanks In Advance

Comments have been disabled for this content.