Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC Menu Selected Item

Tags:

OK new to MVC. I had asked this question earlier and got an answer but I am wondering if there is a simpler solution.

Say I have a master page with a menu laid out as an unordered list. How would I go about setting a css class on the currently selected menu item?

EDIT:

I am using the menu just as it comes setup out of the box when you start a new mvc app

<ul id="menu">              
   <li><%: Html.ActionLink("Home", "Index", "Home")%></li>
   <li><%: Html.ActionLink("About", "About", "Home")%></li>
</ul>
like image 665
stephen776 Avatar asked Jan 11 '11 01:01

stephen776


3 Answers

The answer from Jakub Konecki led me in the right direction... here is the controller action I ended up with:

    [ChildActionOnly]
    public ActionResult MainMenu()
    {
        var items = new List<MenuItem>
        {
            new MenuItem{ Text = "Home", Action = "Index", Controller = "Home", Selected=false },
            new MenuItem{ Text = "My Profile", Action = "Index", Controller = "Profile", Selected = false},
            new MenuItem{ Text = "About", Action = "About", Controller = "Home", Selected = false }
        };

        string action = ControllerContext.ParentActionViewContext.RouteData.Values["action"].ToString();
        string controller = ControllerContext.ParentActionViewContext.RouteData.Values["controller"].ToString();

        foreach (var item in items)
        {
            if (item.Controller == controller && item.Action == action)
            {
                item.Selected = true;
            }
        }

        return PartialView(items);
    }

Hope this helps someone.

like image 154
stephen776 Avatar answered Sep 27 '22 15:09

stephen776


You should pass all relevant information in the Model. Ideally your menu will be rendered as a Partial View by a separate controller method. I have a Navigation controller with actions like MainMenu, FooterMenu, Breadcrumbs, etc that render individual parts.

Your model will be a collection of menu items like:

    public class MenuItemModel
    {
        public MenuItemModel()
        {
            SubMenu = new List<MenuItemModel>();
        }

        public string Text { get; set; }
        public string Controller { get; set; }            
        public string Action { get; set; }
        public bool Selected { get; set; }

        public List<MenuItemModel> SubMenu { get; private set; }
    }

Your Controller will create a collection of menu items and pass them to the view with the appropriate item selected. Then the view can be as simple as:

<ul id="menu">     
    <% foreach(var menuItem in Model.MenuItems) { %> 
        <li><%: Html.ActionLink(menuItem.Text, menuItem.Action, menuItem.Controller, null, new { @class = menuItem.Selected ? "selected" : "" })%></li>
    <% } %>
</ul>
like image 18
Jakub Konecki Avatar answered Sep 24 '22 15:09

Jakub Konecki


stephen,

here's my contribution to the party. a recursive inline function to populate the <ul><li> for as many depths as is required (here's the entire ascx file):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<GBC_Art.Controllers.MenuItemModel>>" %>
<%@ Import Namespace="GBC_Art.Controllers" %>
<%
    Action<List<MenuItemModel>, int> printNodesRecursively = null;
    printNodesRecursively = (List<MenuItemModel> nodeList, int depth) =>
    {
        if (nodeList == null || nodeList.Count == 0) return;
%>
    <ul<%= depth == 0 ? " id='menu'" : ""%>>  
<%
    foreach (var menuItem in nodeList)
    {
    %>
    <li><%= Html.ActionLink(menuItem.Text, menuItem.Action, menuItem.Controller, null, new { @class = menuItem.Selected ? "selected" : "" })%>
        <%printNodesRecursively(menuItem.SubMenu, depth + 1);%>
    </li>
    <%
        }
%>
    </ul>
<%
    };
    List<MenuItemModel> nodes = Model; 
    printNodesRecursively(nodes, 0);
%>

usage -> called as a partialview via the controller as per your example above.

cheers

like image 4
jim tollan Avatar answered Sep 24 '22 15:09

jim tollan