Archive | July 23, 2011

MVC Menu Generation Class

Menus can be complex or rather simple. Often if it is just a simple site with maybe one level of sub navigation and a handful of links it might be easiest to just throw in some divs, uls or whatever you choose and build up the menu manually in a partial view. When you start to add more items or they change frequently this is probably not the best solution. When the menu gets larger or every bit of speed counts you may want to cache it as well. So here is a class I put together this afternoon. It uses four things. A class, an Mvc helper method, some Css and a tiny bit of JQuery.

Quick Note

There are several other solutions out there for menus in MVC. You should check them out. The reason I did this is that I wanted to leverage the good ol’ SiteMapCollection and SiteMap built into .Net. Additionally something I think many don’t realize is in your Web.SiteMap you can add additional attributes to each node. For example in this article an additional attribute is used called “image”. This is used to add the dropdown arrow you see in the example below. So you could even change the whole structure with the exception of a few required attributes to do whatever you need. So rather than create a custom XML file that takes in controller = “home”, action = “index” and so on I chose to use the SiteMap for this one. Essentially “/Home/Index” is essentially the same thing. Obvious there are exceptions but for the most part this works just fine. The SiteMapCollection is rather easy to work with as you’ll see in this example. However you should as I mentioned check out some other examples. In fact this method in this article I’ve obviously used but have used several others also. Some links to checkout:

Alternate Menus To Checkout

MVC SiteMap Provider – This works great but may be more than you need. Used it many times.

Telerik MVC Menu – Telerik is great if you’re already using their controls.

Getting Started

Download Source

First thing you probably want to do is take a look at the class. All it is doing is building up some strings. You could create tags and so on but this was quick and does the job just fine for mvcmenu_screenshota simple solution to build out some unordered lists. Typically what you would use with JQuery. I won’t go over the whole class. It is heavily commented so you should have no trouble modifying or doing what you want. The biggest key to this class is the small method called “Process Child”. this is because it does some recursion which makes building out the menu possible when you don’t know exactly how many levels of sub menus we’d have in our SiteMap.

After you make reference (add using to your helper extensions class) to the MVCMenu.cs (see source) in your Helper Extensions class wherever that may be, you’ll need the following Helper to make it all wire up. Note may of the options here could be set statically in the method so that for example you don’t have to pass all those options. Maybe just enable security trimming. Most of these you’ll set once and forget anyway. It does help in development to have them all exposed to you in your view. If you need help creating a Helper or don’t understand what it is, please stop and go here first then come back.

Adding Helper Method

/// <summary>
/// Creates a menu by dynamically creating a string to be returned as MvcHtml.
/// </summary>
/// <param name="helper">The Html Helper.</param>
/// <param name="homeController">Your Home controller name, probably "Home" w/o quotes.</param>
/// <param name="useIcons">Indicates whether icon images should be used on parent menus.</param>
/// <param name="iconPosition">For icons on left 0, for right enter 1.</param>
/// <param name="enableDesc">Enables/Disables tooltips on anchors inside each menu. Use false in most cases.</param>
/// <param name="enableSecurityTrimming">Provides security trimming when enabled.</param>
/// <param name="enableCache">Adds caching to the MVCMenu, Selected CSS state will not work when enabled.</param>
/// <returns></returns>
public static MvcHtmlString MVCMenu(this HtmlHelper helper, string homeController, 
                                    bool useIcons, int iconPosition, bool enableDesc, 
                                    bool enableSecurityTrimming, bool enableCache)
    MVCMenu mu = new MVCMenu();
    string menu = mu.GetMenu(homeController, useIcons, iconPosition, 
                  enableDesc, enableSecurityTrimming, enableCache);
    return MvcHtmlString.Create(menu);

Reference Helper in View

So we have our Helper method in place, have referenced/resolved (Namespace = Origin1Technologies.MVC.Helpers)  MVCMenu.cs, now we’re ready to actually call the helper on our view. See syntax below. You’ll get intellisense as you specify the options. It will be self explanatory.

@Html.MVCMenu("Home", true, 1, false, false, false)

CSS Classes Built Into MVCMenu

There are few classes built into the MVCMenu.cs class. They are set as constants in the class. Feel free to change those to names/conventions that make more sense to you if you like but this is the defautl:

    • “menu-root” – This is the root of our menu. Not to be confused with the root of your SiteMap which is almost never used.
    • “menu-parent” – This is a ul that is nested in menu that has sub items regardless of nexted level.
    • “menuitem” – This is an item in the menu. Essentially an li, from root to the last child.
    • “menuitem-selected” – When a menuitem matches the current route (basically just the controller name) it is set as selected. See comments for a few exceptions and a better understanding.
    • “level{0}” – Where {0} is the level at which the “menu-parent” is at. Level 0 is the root of the menu. The next 1 and so on. This can be helpful in css styling. Often with a good JQuery design this is not needed but it can be handy.

There are several examples of using ul’s as menus. You can even grab some existing css from a menu plugin (JQuery) and use it or use the menu plugin. The majority use the very structure the Helper builds out. Just modify the CSS class names in the MVCMenu.cs class or your stylesheet to match up with the above described class names and bingo you have a menu.

Wrap Up

Now you have some todos. The Helper will build out an unordered list for you with nested unordered lists. You’ll need to wire up some css. That is up to you. The design of a menu is pretty specific to a site so that’ll be up to you. You can use CSS pseudo classes for hovering but probably better to use JQuery for better control. One HINT is to make sure the submenus are position: absolute in most cases for desired look.

    NOTE: this hasn’t been fully debugged. As with many of the things I post here that quick things thrown together for a need and I share them out. Often by the time you read this article the code will have been modified several times. Often I update the download links to the current source but may not always do so. So don’t get frustrated if something breaks just take a moment, do some proper debugging and you’ll be good. You can also comment and if I catch it in time I’ll gladly reply.