Tab menus are a fairly common thing that I use in a lot of my applications. I like tabs because they help break up large chunks of, usually, related information.

 

At work we use RadControls for Telerik and they have a pretty nice tab menu control that is easy to use and looks good too. The only problem with these controls is that they only work in WebForms like even the default ASP.NET controls. So when I started playing with MVC I quickly realized I would need to spend some time building some of these controls myself.

Based on that realization, the idea for this post was formed and I set to work creating a fair simple control. This control is not meant to be compared with the control from Telerik. Mine is very basic and has very few features.

 

Again, I will be using the default MVC template project as my starting point. I did make a few minor changes to the MasterPage but I will include the finished Visual Studio project with this post so you can take a look for yourself.

The first step is to create the HtmlHelper extension method that will generate our control. This method will do most of the work we need.

   1: public static class MyHtmlHelper
   2: {
   3:     public static string TabbedMenu(this HtmlHelper helper, IEnumerable<MenuTab> tabs)
   4:     {
   5:         var route = helper.ViewContext.RequestContext.RouteData;
   6:         var controller = route.GetRequiredString("controller");
   7:         var action = route.GetRequiredString("action");
   8:         var menu = "\n\n<ul id=\"menu\">";
   9: 
  10:         foreach (var tab in tabs)
  11:         {
  12:             if (controller == tab.Controller && action == tab.Action)
  13:                 menu += "\n\t<li>" + helper.ActionLink(tab.Text, tab.Action,
  14:                 tab.Controller, new { @class = "selected" }) + "</li>";
  15:             else
  16:                 menu += "\n\t<li>" + helper.ActionLink(tab.Text,
  17:                 tab.Action, tab.Controller) + "</li>";
  18:         }
  19:         menu += "\n</ul>\n\n";
  20:         return menu;
  21:     }
  22: }

So what this method does is it accepts an IEnumberable collection of MenuTab. We’ll look at the MenuTab class in just a bit. Next the method gets the names of both the current controller and action. These will be used to determine which tab is currently selected. Then the method uses a foreach to loop through the collection and build out the HTML unordered list. Notice that during the loop we are checking to see if the MenuTab instance’s controller and action match the current controller and action. If they make we apply the selected CSS class to the anchor. Pretty simple stuff.

Note: All this method does is produce the required HTML markup. CSS is used to achieve the tab look.

Now let’s look at the MenuTab class.

   1: public class MenuTab
   2: {
   3:     private MenuTab(string text, string action, string controller)
   4:     {
   5:         Text = text;
   6:         Action = action;
   7:         Controller = controller;
   8:     }
   9: 
  10:     public static MenuTab Create(string text, string action, string controller)
  11:     {
  12:         return new MenuTab(text, action, controller);
  13:     }
  14: 
  15:     public string Text { get; private set; }
  16:     public string Action { get; private set; }
  17:     public string Controller { get; private set; }
  18: }

This class is very simple. It just stores the information we will need to build the links in our menu.

That covers off the extension method and any related code. As you can see I wasn’t kidding when I said it doesn’t have many features. This only meant to should how to get started.

In order to make the menu look like tabs a made a few minor tweaks to the existing Site.css file and added the below class definition to indicate which tab is selected.

   1: ul#menu li a.selected {
   2: background-color: #fff;
   3: color: #000;
   4: }

Now all that is left is to insert our menu into the Site.Master file of our application.

   1: <%= Html.TabbedMenu(new List<MenuTab> {
   2: MenuTab.Create("Home", "Index", "Home"),
   3: MenuTab.Create("About", "About", "Home"),
   4: MenuTab.Create("Services", "Services", "Home"),
   5: MenuTab.Create("Pricing", "Pricing", "Home"),
   6: MenuTab.Create("Contact", "Contact", "Home")
   7: }) %>

I replaced the menu code that was already in the demo with the above code that defines the links in our menu.

So as you can see it was pretty simple to build an extension method to add our own helper method for building a tab like menu. By encapsulating this into a helper method we can now easily reuse it in any application.

You can download a sample project from our Freebies Page

Stay tuned for more great posts from Dev102.com by grabbing the RSS feed. You can also see more posts I have written on my blog or grab my RSS feed.

Tags :

18 Responses to “Creating A Tabbed Menu Control For ASP.NET MVC”


  1. Chris Pietschmann

    Said on April 14, 2009 :

    Looks like a good start, but where’s the rest of the code? CSS, JavaScript, etc?

  2. Chris Pietschmann

    Said on April 14, 2009 :

    oh, duh… I just skimmed the article, there’s the CSS. Maybe I should pay attention some times. :)

  3. Jon

    Said on April 22, 2009 :

    Could this work so that instead of a load of MenuTab.Create in the master page it somehow uses data from a database table and does a MenuTab.Create for each item in the database?

    This is a great example that I’ve been looking for, Thanks

  4. Jon

    Said on April 22, 2009 :

    There is a bug in the code, the HTML output is incorrect. This is a working version.

    foreach(var tab in tabs) {
    if(controller == tab.Controller && action == tab.Action)
    menu += “\n\t” + helper.ActionLink(tab.Text, tab.Action,
    tab.Controller, null, new { @class = “selected” }) + “”;
    else
    menu += “\n\t” + helper.ActionLink(tab.Text,
    tab.Action, tab.Controller) + “”;
    }

  5. Neeks

    Said on April 24, 2009 :

    Nice Article to start.

  6. Jon

    Said on April 24, 2009 :

    How would you do it for a nested menu eg/

    Item 1

    SubItem1

    Item 2

    SubItem1

  7. Mike Scott

    Said on May 21, 2009 :

    Hi Justin

    Nice article. Here are suggestions for improvements:

    1. Use a StringBuilder instead of concatenating strings to create the HTML.
    2. Lose the MenuTab.Create method, it’s redundant. You didn’t previously work with Delphi, did you? ;-)
    3. Add an overload to the MyHtmlHelper that takes a params MenuTab[] parameter so you can lose the new List( {…} ):

  8. Robert

    Said on December 5, 2009 :

    The following code is made available for use with MVC2 “Functional Areas”…
    http://msdn.microsoft.com/en-us/library/ee671793(VS.100).aspx

    download tutorial here…
    http://go.microsoft.com/fwlink/?LinkId=164755

    public class MenuTab
    {
    private MenuTab(string text, string action, string controller, object routevalues)
    {
    Text = text;
    Action = action;
    Controller = controller;
    RouteValues = routevalues;
    }

    public static MenuTab Create(string text, string action, string controller, object routevalues)
    {
    return new MenuTab(text, action, controller, routevalues);
    }

    public string Text { get; private set; }
    public string Action { get; private set; }
    public string Controller { get; private set; }
    public object RouteValues { get; private set; }
    }

    public static class MyHtmlHelper
    {
    public static string TabbedMenu(this HtmlHelper helper, IEnumerable tabs)
    {
    var route = helper.ViewContext.RequestContext.RouteData;
    var action = route.GetRequiredString(“action”);
    var controller = route.GetRequiredString(“controller”);

    var menu = “\n\n”;
    foreach (var tab in tabs)
    {
    if (action == tab.Action && controller == tab.Controller)
    menu += “\n\t” + helper.ActionLink(tab.Text, tab.Action,
    tab.Controller, new { area = tab.RouteValues }, new { @class = “selected” }) + “”;
    else
    menu += “\n\t” + helper.ActionLink(tab.Text, tab.Action,
    tab.Controller, new { area = tab.RouteValues }, null) + “”;
    }
    menu += “\n\n\n”;
    return menu;
    }
    }

    Site.Master page…

    <%= Html.TabbedMenu(new List {
    MenuTab.Create(“Home”, “Index”, “Home”, “”),
    MenuTab.Create(“Blog”, “ShowRecent”, “Blog”, “blog”),
    MenuTab.Create(“Dashboard”, “AddPost”, “Dashboard”, “dashboard”),
    MenuTab.Create(“About”, “About”, “Home”, “”)
    }) %>

  9. Robert

    Said on December 5, 2009 :

    I hope someone might find it useful; I modified the original code by Justin to work with MVC2 Areas.

    Thanks Justin!!

  10. Bart van der Vliet

    Said on March 23, 2010 :

    Thanks for this article, it helped me a lot. For other people who are using this control: Add the namespaces System.Web.Mvc and System.Web.Mvc.Html to access the ActionLink extension method on the HtmlHelper object.

  11. bala

    Said on April 21, 2011 :

    I want to know that how to give submenus to the main menu like
    Home>Item1
    Item2
    Servies>Item1
    Item2

    Please reply

  12. Shyam

    Said on June 10, 2011 :

    Hi
    I am doing as same way but want to add subtab on tab how i can do this?

  13. nadeekadn

    Said on April 6, 2012 :

    i want create 2 munus in one form. if u have any idea about it.

  14. http://internetpdfarticles.com/

    Said on March 28, 2014 :

    I do not write many remarks, but i did some searching and wound up here Creating A Tabbed Menu Control For ASP.NET
    MVC | Dev102.com. And I actually do have 2 questions for you if you don’t mind.
    Could it be only me or does it look like a few of the comments appear like they are left by brain dead individuals?
    :-P And, if you are posting on additional sites, I’d like to follow anything new you have to post.
    Could you make a list of the complete urls of all your social sites like your linkedin profile, Facebook page or twitter feed?

4 Trackback(s)

  1. Apr 14, 2009: DotNetBurner - ASP.net MVC
  2. Apr 15, 2009: 9eFish
  3. Apr 16, 2009: Links 2009-04-16 - Gunnar Peipman's ASP.NET blog
  4. Dec 6, 2011: Buy Facebook Fans

Post a Comment