将"active"标记添加到asp.net mvc母版页的导航列表中

dp.*_*dp. 35 asp.net-mvc

在默认的asp.net mvc项目中,在Site.Master文件中,有一个菜单导航列表:

<div id="menucontainer">
    <ul id="menu">              
        <li><%= Html.ActionLink("Home", "Index", "Home")%></li>
        <li><%= Html.ActionLink("About Us", "About", "Home")%></li>
    </ul>
</div>
Run Code Online (Sandbox Code Playgroud)

这将在浏览器中呈现:

<div id="menucontainer"> 
    <ul id="menu">              
        <li><a href="/">Home</a></li> 
        <li><a href="/Home/About">About Us</a></li> 
    </ul> 
</div> 
Run Code Online (Sandbox Code Playgroud)

我希望能够根据被调用的视图动态设置活动列表项.也就是说,当用户查看主页时,我希望创建以下HTML:

<div id="menucontainer"> 
    <ul id="menu">              
        <li class="active"><a href="/">Home</a></li> 
        <li><a href="/Home/About">About Us</a></li> 
    </ul> 
</div> 
Run Code Online (Sandbox Code Playgroud)

我希望这样做的方式如下:

<div id="menucontainer">
    <ul id="menu">              
        <li <% if(actionName == "Index"){%> class="active"<%}%>><%= Html.ActionLink("Home", "Index", "Home")%></li>
        <li <% if(actionName == "About"){%> class="active"<%}%>><%= Html.ActionLink("About Us", "About", "Home")%></li>
    </ul>
</div>
Run Code Online (Sandbox Code Playgroud)

这里的关键位是<% if(actionName == "Index"){%> class="active"<%}%>线.我不知道如何确定当前actionName是什么.

有关如何做到这一点的任何建议?或者,如果我完全走错了轨道,有没有更好的方法呢?

Ada*_*arr 37

我自己做了一个帮助方法来处理这类事情.在我的母版页后面的代码中(可以推送到扩展方法......可能是更好的方法),我把下面的代码.

protected string ActiveActionLinkHelper(string linkText, string actionName, string controlName, string activeClassName)
{
    if (ViewContext.RouteData.Values["action"].ToString() == actionName && 
            ViewContext.RouteData.Values["controller"].ToString() == controlName)
        return Html.ActionLink(linkText, actionName, controlName, new { Class = activeClassName });

    return Html.ActionLink(linkText, actionName, controlName);
}
Run Code Online (Sandbox Code Playgroud)

然后,我只是在我的页面中调用它:

<%= ActiveActionLinkHelper("Home", "Index", "Home", "selected")%>
Run Code Online (Sandbox Code Playgroud)


Cra*_*ntz 10

在视图中,您可以使用以下命令获取当前操作名称:

ViewContext.RouteData.Values["action"].ToString()
Run Code Online (Sandbox Code Playgroud)


lab*_*lbe 10

您还可以尝试从其控制器名称和视图名称中检测当前所选选项卡,然后添加class属性.

public static string MenuActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName)
{
    var htmlAttributes = new RouteValueDictionary();

    if (helper.ViewContext.Controller.GetType().Name.Equals(controllerName + "Controller", StringComparison.OrdinalIgnoreCase))
    {
        htmlAttributes.Add("class", "current");
    }

    return helper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), htmlAttributes);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您在返回helper.ActionLink时收到错误,请将此添加到您的使用引用:using System.Web.Mvc.Html; (3认同)
  • 它应该返回一个MvcHtmlString而不是一个字符串 (2认同)

Tel*_*yen 10

在MVC 3 Razor View Engine中,您可以这样做:

@{string ctrName = ViewContext.RouteData.Values["controller"].ToString();}

<div id="menucontainer">
  <ul id="menu"> 
    <li @if(ctrName == "Home"){<text> class="active"</text>}>@ Html.ActionLink("Home",  "Index", "Home")</li>
    <li @if(ctrName == "About"){<text> class="active"</text>}>@ Html.ActionLink("About Us", "About", "Home")</li>
  </ul>
</div>
Run Code Online (Sandbox Code Playgroud)

当我有两个页面时我的样本工作:Home/About和它的控制器具有相同的名称索引,所以我得到控制器名称以区分操作.如果您想要采取行动,只需替换为以下内容:

@{string ctrName = ViewContext.RouteData.Values["action"].ToString();}
Run Code Online (Sandbox Code Playgroud)


小智 7

一个老问题,但希望有人可能会发现这非常有帮助.

  1. ViewBag中放置一些可用于识别页面的东西,我使用了ViewgBag.PageName

例如,在index.cshtml中,添加类似的内容

@{
    ViewBag.PageName = "Index";
}
Run Code Online (Sandbox Code Playgroud)
  1. 使用条件语句向每个链接项添加一个类,以便在访问的页面具有所需值时返回活动状态,否则返回空字符串.查看以下详细信息:

<li class="@((ViewBag.PageName == "Index") ? "active" : "")"><a href="@Url.Action("Index","Home")">Home</a></li>
<li class="@((ViewBag.PageName == "About") ? "active" : "")"><a href="@Url.Action("About","Home")">About</a></li>
<li class="@((ViewBag.PageName == "Contact") ? "active" : "")"><a href="@Url.Action("Contact","Home")">Contact</a></li>
Run Code Online (Sandbox Code Playgroud)

我不只是测试它,我在我的项目中使用这种方法


Tim*_*les 6

为了贡献我自己的答案(在MVC4中测试),我采取了其他答案的几个最佳位,解决了一些问题,并添加了一个帮助程序来处理不一定通过Controller&Action解决的URL(例如,如果你有一个嵌入式CMS处理一些页面链接等)

该代码也可以在github上分叉:https://gist.github.com/2851684

/// 
/// adds the active class if the link's action & controller matches current request
/// 
public static MvcHtmlString MenuActionLink(this HtmlHelper htmlHelper,
    string linkText, string actionName, string controllerName,
    object routeValues = null, object htmlAttributes = null,
    string activeClassName = "active")
{
    IDictionary htmlAttributesDictionary =
        HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

    if (((string)htmlHelper.ViewContext.RouteData.Values["controller"])
            .Equals(controllerName, StringComparison.OrdinalIgnoreCase) &&
        ((string)htmlHelper.ViewContext.RouteData.Values["action"])
            .Equals(actionName, StringComparison.OrdinalIgnoreCase))
    {
        // careful in case class already exists
        htmlAttributesDictionary["class"] += " " + activeClassName;
    }

    return htmlHelper.ActionLink(linkText, actionName, controllerName,
                                    new RouteValueDictionary(routeValues),
                                    htmlAttributesDictionary);
}

/// 
/// adds the active class if the link's path matches current request
/// 
public static MvcHtmlString MenuActionLink(this HtmlHelper htmlHelper,
    string linkText, string path, object htmlAttributes = null,
    string activeClassName = "active")
{
    IDictionary htmlAttributesDictionary =
        HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
    if (HttpContext.Current.Request.Path
        .Equals(path, StringComparison.OrdinalIgnoreCase))
    {
        // careful in case class already exists
        htmlAttributesDictionary["class"] += " " + activeClassName;
    }
    var tagBuilder = new TagBuilder("a")
                            {
                                InnerHtml = !string.IsNullOrEmpty(linkText)
                                                ? HttpUtility.HtmlEncode(linkText)
                                                : string.Empty
                            };
    tagBuilder.MergeAttributes(htmlAttributesDictionary);
    tagBuilder.MergeAttribute("href", path);
    return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
}
Run Code Online (Sandbox Code Playgroud)


Jas*_*orn 0

您的视图必须了解控制器的操作这一事实打破了 MVC 模式。也许你的控制器可以将一些“控制”信息传递给视图,最终让它完成同样的事情,唯一的区别是谁负责。

就像在控制器的操作中一样,您可以:

public ActionResult Index(){
     ViewData["currentAction"] = "Index";
     //... other code
    return View();
}
Run Code Online (Sandbox Code Playgroud)

然后在你看来你可以:

<% if( ((string)ViewData["currentAction"]) == "Index" {%> <!- some links --><% } %>
<% if( ((string)ViewData["currentAction"]) == "SomethingElse" {%> <!- some links --><% } %>
Run Code Online (Sandbox Code Playgroud)

然而,我想得越多,我就越质疑为什么你要使用同一个视图来执行多个操作。观点有那么相似吗?

如果用例证明它是合理的,那么就遵循我上面的建议。但除此之外,也许您可​​以将事物分解为多个视图(每个控制器操作一个视图),问题就会自行解决。