在MVC 3 Razor中获得活动页面链接的更好方法

问题描述

| 当我希望特定菜单链接在给定页面上处于活动状态时,我在Razor中使用以下方法: 在主版式上,我有以下检查:
var active = ViewBag.Active;
const string ACTIVE_CLASS = \"current\";

if (active == \"home\")
{
    ViewBag.ActiveHome = ACTIVE_CLASS;
}
if (active == \"products\")
{
    ViewBag.ActiveProducts = ACTIVE_CLASS;
}
等等 主版式上的html菜单
<ul>
<li class=\"@ViewBag.ActiveHome\"><a href=\"/\">Home</a></li>
<li class=\"@ViewBag.ActiveProducts\"><a href=\"@Url.Action(\"index\",\"products\")\">Products</a></li>
</ul>
指定在其他视图上使用哪个布局页面时:
@{
    ViewBag.Active = \"home\";
    Layout = \"~/Views/Shared/_Layout.cshtml\";
}
与我当前使用的链接相比,有没有一种更好的方法来分隔活动链接?     

解决方法

        更好的方法是使用HTML帮助器:
using System.Web.Mvc; 
using System.Web.Mvc.Html;

public static class MenuExtensions
{
    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,controller).ToHtmlString();
        return MvcHtmlString.Create(li.ToString());
    }
}
接着:
<ul>
    @Html.MenuItem(\"Home\",\"Home\",\"Home\")
    @Html.MenuItem(\"Products\",\"Index\",\"Products\")
</ul>
要完成上述工作,您需要您的视图才能识别您的扩展名:在Webs.config的“视图”文件夹中,在名称空间标记内添加“ 5”。然后构建您的项目并关闭并重新打开要添加该视图的视图。 然后根据当前动作和控制器,辅助对象在生成锚点时将添加或不添加“ 6”类。     ,        在Darin的示例上进行扩展,这里是完整类,该类在辅助程序上为RouteValues和HtmlAttributes添加了其他可选参数。实际上,它的行为就像基本的ActionLink。
using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MYNAMESPACE.Helpers {
    public static class MenuExtensions {
        public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper,string controller,object routeValues = null,object htmlAttributes = null) {
            var li = new TagBuilder(\"li\");
            var routeData = htmlHelper.ViewContext.RouteData;
            var currentAction = routeData.GetRequiredString(\"action\");
            var currentController = routeData.GetRequiredString(\"controller\");
            if (string.Equals(currentAction,StringComparison.OrdinalIgnoreCase) &&
                string.Equals(currentController,StringComparison.OrdinalIgnoreCase)) {
                li.AddCssClass(\"active\");
            }
            if (routeValues != null) {
                li.InnerHtml = (htmlAttributes != null)
                    ? htmlHelper.ActionLink(text,routeValues,htmlAttributes).ToHtmlString()
                    : htmlHelper.ActionLink(text,routeValues).ToHtmlString();
            }
            else {
                li.InnerHtml = htmlHelper.ActionLink(text,controller).ToHtmlString();
            }
            return MvcHtmlString.Create(li.ToString());
        }
    }
}
并在View文件夹的web.config中:
<system.web.webPages.razor>
  <host ... />
  <pages ... >
    <namespaces>
      ...

      ...
      <add namespace=\"MYNAMESPACE.Helpers\" />
    </namespaces>
  </pages>
</system.web.webPages.razor>
    ,        如果您想在文本中包含HTML格式,请使用此InnerHtml;
li.InnerHtml = \"<a href=\\\"\" + new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(action,controller).ToString() + \"\\\">\" + text + \"</a>\";
文字可能是\“ 粗体普通\”;     ,        已为RC2更新-对于那些想知道如何在MVC6 / Asp.Net 5中执行此操作的用户-相似但略有不同。现在没有
MvcHtmlString
,而
RouteData
的工作方式则完全不同。而且,上下文对象现在应该是
IHtmlContent
而不是
HtmlHelper
using System;
using Microsoft.AspNet.Mvc.Rendering;

public static class MenuExtensions
{
    public static IHtmlContent MenuItem(
        this IHtmlHelper htmlHelper,string controller
    )
    {

        var li = new TagBuilder(\"li\") { TagRenderMode = TagRenderMode.Normal };
        var routeData = htmlHelper.ViewContext.RouteData;
        var currentAction = routeData.Values[\"action\"].ToString();
        var currentController = routeData.Values[\"controller\"].ToString();

        if (string.Equals(currentAction,StringComparison.OrdinalIgnoreCase))
        {
            li.AddCssClass(\"active\");
        }


        li.InnerHtml.AppendHtml(htmlHelper.ActionLink(text,controller));

        return li;


    }
}
    ,        即使在新的Visual Studio 2013 MVC5 / Bootstrap项目上,此代码也对我非常有用。还要注意,您可以更改li.AddCssClass(\“ active \”);如果要单独保留Bootstrap \“ active \\”类,则该行指向一个自定义类。我在项目的Site.css文件中添加了一个名为“ activemenu”的文件,并在此进行了任何想要的特定导航栏样式更改。 上面代码中的行仅更改为此代码,以使其全部正常工作:
li.AddCssClass(\"activemenu\");
在Site.css中,出于我的目的添加了一个简单的类:
.activemenu {
    text-decoration: underline;
}
或者,您可以更改背景颜色和/或边框等。     ,        这是达林类的扩展,可以在链接文本中插入html而不是简单的文本
using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace YourNameSpaceHere
{
    public static class MenuExtensions
    {
        public static MvcHtmlString MenuItem(
            this HtmlHelper htmlHelper,string html,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,StringComparison.OrdinalIgnoreCase))
            {
                li.AddCssClass(\"active\");
            }
            //generate a unique id for the holder and convert it to string
            string holder = Guid.NewGuid().ToString();
            string anchor = htmlHelper.ActionLink(holder,controller).ToHtmlString();
            //replace the holder string with the html
            li.InnerHtml = anchor.Replace(holder,html);
            return MvcHtmlString.Create(li.ToString());
        }
    }
}
并像这样使用它:
<ul>
    @Html.MenuItem(\"<span class\'ClassName\'>Home</span>\",\"Home\")
</ul>