Diver Dan
Diver Dan

Reputation: 9963

MVC main menu and selected submenu

I am creating a menu for the MVC music store application. Currently it looks like this As you can see I have the index view CSS selected not the About view

As you can see I have the Home sub level menu selected when in fact I am on the About View.

I used Darins example for the main menu and created a helper class which looks like this.

public static MvcHtmlString MenuLink(this HtmlHelper helper,
        string linkText, string actionName,
        string controllerName)
{
    string currentAction = helper.ViewContext.RouteData.GetRequiredString("action");
    string currentController = helper.ViewContext.RouteData.GetRequiredString("controller");

    //modified this to work whenever a view of the controller is selected
    //if (actionName == currentAction && controllerName == currentController)
    if (controllerName == currentController)
    {
        return helper.ActionLink(
            linkText,
            actionName,
            controllerName,
            null,
            new
            {
                @class = "active"
            });
    }
    return helper.ActionLink(linkText, actionName, controllerName);
}

Note I did slightly change the code as I wasn't interested in action name. I found this limited me and the main menu wouldn't add the active CSS state where I wanted.

So that works perfect for the top level menu however I am a little stuck with the sublevel menu. My html consists of 2 UL tags like

    <nav id="main-nav">
        <ul>
            <li>@Html.MenuLink("Home", "Index", "Home")</li>
            <li>@Html.MenuLink("Store", "Index", "Store")</li>
            <li>@Html.MenuLink("Cart", "Index", "ShoppingCart")</li>
           <li>@Html.MenuLink("Admin", "Index", "StoreManager")</li>

        </ul>
    </nav>
</div>
<div id="page-subheader">
    <div class="wrapper">
        <nav id="sub-nav">
            <ul>
             <li>@Html.SubMenuLink("Home", "Index", "Home")</li>
            <li>@Html.SubMenuLink("About", "Index", "Home/About")</li>
           @*     <li class="active"><a href="@Url.Content("~")">Index</a></li>
                <li><a href="@Url.Content("~/Home/About")">About</a></li>*@
            </ul>
        </nav>
        <input placeholder="Search..." type="text" name="q" value="" />
    </div>
</div>

Pretty standard HTML I have also tried to create another helper like:

public static MvcHtmlString SubMenuLink(this HtmlHelper helper, 
        string linkText, string actionName,
        string controllerName)
{
    string currentAction = helper.ViewContext.RouteData.GetRequiredString("action");
    string currentController = helper.ViewContext.RouteData.GetRequiredString("controller");

    if (controllerName == currentController)
    {
        return helper.ActionLink(
            linkText,
            actionName,
            controllerName,
            null,
            new
            {
                @class = "active"
            });
    }
    return helper.ActionLink(linkText, actionName, controllerName);
}

But I don't really know what to do next. If I put a break point on the code I can see currentAction is been returned as About and currentController is been returned as Home, I'm just a little unsure how to add the logic apply the active CSS class to the submenu.

Can some please help?

Upvotes: 1

Views: 12474

Answers (1)

Rob Stevenson-Leggett
Rob Stevenson-Leggett

Reputation: 35679

You can use the original method unchanged. I am doing exactly the same.

One note of caution. I've started using Areas and these methods no longer work so well.

public static MvcHtmlString SubMenuLink(this HtmlHelper helper, string linkText, string actionName,
                                       string controllerName)
{
    string currentAction = helper.ViewContext.RouteData.GetRequiredString("action");
    string currentController = helper.ViewContext.RouteData.GetRequiredString("controller");

    if (controllerName == currentController && actionName == currentAction)
    {
        return helper.ActionLink(
            linkText,
            actionName,
            controllerName,
            null,
            new
            {
                @class = "active"
            });
    }
    return helper.ActionLink(linkText, actionName, controllerName);
}

Upvotes: 2

Related Questions