2

I'm trying to learn ASP.NET MVC, and I want to have menus highlighted on the item that is currently selected. I know I did this before in web forms (although I don't actually remember how at the moment, but somehow with the sitemap). But how can this be done in MVC?

It seems like such a basic thing it should be simple to do in MVC? Sure, I can do it by adding CSS rules that are coupled between a body id and an li id from the menu (#home #homeli [style as current]), but it seems that would quickly become unwieldy, especially if there are also a lot of sub menus besides the main navigation (in several of the sub pages I have a sub menu in a contentplaceholder. BTW, I guess that's the only way to do it in MVC? In web forms the sub menus too could be handled by the sitemap, but I haven't seen a way to do this in MVC...)

Any suggestions?

2 Answers 2

8

Here is a tutorial that provides a very clean way to achieve this kind of menu:

http://www.dev102.com/2009/04/14/creating-a-tabbed-menu-control-for-aspnet-mvc/

The magic bit figuring out whether or not a menu item is active happens in the helper method that renders the items:

public static class MyHtmlHelper
{
   public static string TabbedMenu(this HtmlHelper helper, IEnumerable<MenuTab> tabs)
   {
       var route = helper.ViewContext.RequestContext.RouteData;
       //This is the current controller
       var controller = route.GetRequiredString("controller");
       var action = route.GetRequiredString("action");
       var menu = "\n\n<ul id=\"menu\">";

       foreach (var tab in tabs)
       {
           //if the menu controller and action match current controller and action, mark it as selected
           if (controller == tab.Controller && action == tab.Action)
               menu += "\n\t<li>" + helper.ActionLink(tab.Text, tab.Action,
               tab.Controller, new { @class = "selected" }) + "</li>";
           else
               menu += "\n\t<li>" + helper.ActionLink(tab.Text,
               tab.Action, tab.Controller) + "</li>";
       }
       menu += "\n</ul>\n\n";
       return menu;
   }
}

MenuTab class:

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

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

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

Usage:

<%= Html.TabbedMenu(new List<MenuTab> {
    MenuTab.Create("Home", "Index", "Home"),
    MenuTab.Create("About", "About", "Home"),
    MenuTab.Create("Services", "Services", "Home"),
    MenuTab.Create("Pricing", "Pricing", "Home"),
    MenuTab.Create("Contact", "Contact", "Home")
}) %>
Sign up to request clarification or add additional context in comments.

Comments

0

Menu item per Controller

@{
    var currentController = (string)ViewContext.RouteData.Values["controller"];

    Func<string, object> htmlAttributesFactory =
        controller => currentController == controller ? new {@class = "selected"} : null;

    Func<string, string, MvcHtmlString> menuItemFactory =
        (title, controller) =>
        Html.RouteLink(
            title,
            new {controller},
            htmlAttributesFactory(controller)); 


}

@menuItemFactory("Home", "Home")
@menuItemFactory("Pending", "Pending")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.