Лучший способ получить активную ссылку на страницу в 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;
}
etc.
меню 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";
}
есть ли лучший подход к разделению активных ссылок, чем тот, который я сейчас использую?
6 ответов:
лучше использовать 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, добавить
<add namespace="yourNamespacehere.Helpers" />
внутри тега, пространства имен. Затем создайте свой проект и закройте и снова откройте окно вы добавляете это.затем на основе текущего действия и контроллера помощник добавит или нет
active
класс при создании якоря.
расширяя пример Дарина, вот полный класс, который добавляет дополнительные необязательные параметры для 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()); } } }
и в веб-вид папок.config:
<system.web.webPages.razor> <host ... /> <pages ... > <namespaces> ... ... <add namespace="MYNAMESPACE.Helpers" /> </namespaces> </pages> </system.web.webPages.razor>
используйте этот InnerHtml, если вы хотите включить форматирование HTML в свой текст;
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 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; } }
этот код отлично работал для меня, даже на новом проекте Visual Studio 2013 MVC5 / Bootstrap. Обратите внимание также, что вы можете изменить li.AddCssClass("active"); линия, чтобы указать на пользовательский класс, если вы хотите оставить загрузочный "активный" класс в покое. Я добавил один под названием "activemenu" на сайте проекта.css-файл и сделал какие-либо конкретные изменения стиля navbar, которые я хотел там.
строка в коде выше была просто изменена на это, чтобы все это работало:
li.AddCssClass("activemenu");
In Сайт.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 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>