当我希望特定菜单链接在给定页面处于活动状态时,我在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";
}
有没有比我目前正在使用的更好的方法来分离活动链接?
答案 0 :(得分:126)
更好的方法是使用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, action, controller).ToHtmlString();
return MvcHtmlString.Create(li.ToString());
}
}
然后:
<ul>
@Html.MenuItem("Home", "Home", "Home")
@Html.MenuItem("Products", "Index", "Products")
</ul>
要完成上述工作,您需要使用视图来识别扩展名:在Views文件夹中的Web.config中,在名称空间标记内添加<add namespace="yourNamespacehere.Helpers" />
。然后构建项目并关闭并重新打开要添加到其中的视图。
然后基于当前操作和控制器,帮助器在生成锚点时将添加或不添加active
类。
答案 1 :(得分:6)
扩展Darin的例子,这里是完整的类,它为helper上的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 text, string action,
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,
action,
StringComparison.OrdinalIgnoreCase) &&
string.Equals(currentController,
controller,
StringComparison.OrdinalIgnoreCase)) {
li.AddCssClass("active");
}
if (routeValues != null) {
li.InnerHtml = (htmlAttributes != null)
? htmlHelper.ActionLink(text,
action,
controller,
routeValues,
htmlAttributes).ToHtmlString()
: htmlHelper.ActionLink(text,
action,
controller,
routeValues).ToHtmlString();
}
else {
li.InnerHtml = htmlHelper.ActionLink(text,
action,
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>
答案 2 :(得分:2)
如果您希望在文本中包含HTML格式,请使用此InnerHtml;
li.InnerHtml = "<a href=\"" + new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(action, controller).ToString() + "\">" + text + "</a>";
文字可以是“&lt; b&gt; Bold&lt; / b&gt;正常”;
答案 3 :(得分:2)
为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 text,
string action,
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, action, StringComparison.OrdinalIgnoreCase) &&
string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
{
li.AddCssClass("active");
}
li.InnerHtml.AppendHtml(htmlHelper.ActionLink(text, action, controller));
return li;
}
}
答案 4 :(得分:0)
即使在新的Visual Studio 2013 MVC5 / Bootstrap项目中,此代码也非常适合我。另请注意,您可以更改li.AddCssClass(“active”);如果要单独保留Bootstrap“活动”类,则指向自定义类的行。我在项目的Site.css文件中添加了一个名为“activemenu”的文件,并进行了我想要的任何特定导航样式更改。
上面代码中的行只是更改为此以使其全部正常工作:
li.AddCssClass("activemenu");
在Site.css中,我为自己的目的添加了一个简单的类:
.activemenu {
text-decoration: underline;
}
或者你可以改变背景颜色和/或边框等......
答案 5 :(得分:0)
这是对Darin的类的扩展,在链接文本中插入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 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");
}
//generate a unique id for the holder and convert it to string
string holder = Guid.NewGuid().ToString();
string anchor = htmlHelper.ActionLink(holder, action, 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", "Home")
</ul>