ASP.NET MVC Razor 动态菜单 <li class='current'>

ASP.NET MVC Razor Dynamic menu <li class='current'>

我有一个 HTML 菜单,在我的共享 Layout.cshtml 中呈现为 PartialView 并且具有以下结构:

我这样调用 Layout.cshtml 中的菜单:

 @Html.Action("LeftMenu", "Common", new { context = ViewContext})

这是左边的菜单结构:

<li class='current'>
   <a class='current' href="@Url.Action("Index","Home")">
   <span class="badge pull-right">17</span>
   <i class="icon-dashboard"></i> Dashboard
   </a>
</li>
<li>
   <a href="@Url.Action("Absence","Incident")" class="is-dropdown-menu">
   <span class="badge pull-right"></span>
   <i class="icon-bar-chart"></i> Absence List
   </a>
   <ul>
      <li>
         <a href="@Url.Action("AbsenceList","Incident")">
         <i class="icon-random"></i>
         Notice List
         </a>
      </li>
      <li>
         <a href="@Url.Action("NewAbsence","Incident")">
         <i class="icon-bullseye"></i>
         New Notice
         </a>
      </li>
   </ul>
</li>

我想根据当前视图使我的链接动态化 我可以通过分配 class='current'<a href> 元素来激活 <li> 元素。

我看到我可以使用 HTML 助手来做到这一点:

public static MvcHtmlString MenuItem(
        this HtmlHelper htmlHelper, 
        string text,
        string action, 
        string controller
    )
    {
        var li = new TagBuilder("li");
        var routeData = htmlHelper.ViewContext.RouteData;
        var currentAction = routeData.GetRequiredString("action");
        var currentController = routeData.GetRequiredString("controller");
        if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
            string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
        {
            li.AddCssClass("active");
        }
        li.InnerHtml = htmlHelper.ActionLink(text, action, controller).ToHtmlString();
        return MvcHtmlString.Create(li.ToString());
    }

但我认为上面的代码不会帮助我创建准确的 <li> 结构,我的菜单需要这样的结构才能看起来不错。

如果我检查 (google chrome) 我的活动菜单元素,我得到的是:

非常感谢任何帮助。

我通常会执行以下操作:

@{ string url; }
<ul>
    @{ url = Url.Action("SomeAction", "SomeController"); }
    <li>
        <a class="@(url == Request.Url.AbsolutePath ? "current" : string.Empty)" href="@url">
            Some Action
        </a>
    </li>

    @{ url = Url.Action("SomeOtherAction", "SomeOtherController"); }
    <li>
        <a class="@(url == Request.Url.AbsolutePath ? "current" : string.Empty)" href="@url">
            Some Other Action
        </a>
    </li>

    ...

换句话说,在每种情况下,您将 link 的 URL 与当前请求的 URL 进行比较,并在匹配时呈现 class。

可以修改帮助程序以生成您寻求的输出

public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, string text, string action, string controller, string num, string icon)
{
    var routeData = htmlHelper.ViewContext.RouteData;
    var currentAction = routeData.GetRequiredString("action");
    var currentController = routeData.GetRequiredString("controller");
    bool isCurrent = string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) && string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase);
    UrlHelper urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
    string url = urlHelper.Action(action, controller);
    StringBuilder html = new StringBuilder();
    TagBuilder span = new TagBuilder("span");
    span.AddCssClass("badge pull-right");
    span.InnerHtml = num;
    html.Append(span);
    TagBuilder i = new TagBuilder("i");
    i.AddCssClass(icon);
    html.Append(i);
    span = new TagBuilder("span");
    span.InnerHtml = text;
    html.Append(span);
    TagBuilder a = new TagBuilder("a");
    a.MergeAttribute("href", url);
    if (isCurrent)
    {
        a.AddCssClass("current");
    }
    a.InnerHtml = html.ToString();
    TagBuilder li = new TagBuilder("li");
    if (isCurrent)
    {
        li.AddCssClass("current");
    }
    li.InnerHtml = a.ToString();
    return MvcHtmlString.Create(li.ToString());
}

并在视图中使用它作为

@Html.MenuItem("Dashboard", "Index", "Home", "17", "icon-dashboard")