Лучший способ получить активную ссылку на страницу в MVC 3 Razor - PullRequest
54 голосов
/ 12 июня 2011

Когда я хочу, чтобы конкретная ссылка меню была активной на данной странице, я использую этот подход в 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";
}

Есть ли лучший способ разделения активных ссылок, чем тот, который я сейчас использую?

Ответы [ 6 ]

126 голосов
/ 12 июня 2011

Лучшим подходом является использование помощника 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>

Для того, чтобы вышеуказанное сработало, ваши представления должны распознавать ваше расширение: В Интернете.config в папке Views, добавьте <add namespace="yourNamespacehere.Helpers" /> в тег namespaces.Затем создайте свой проект, закройте и снова откройте представление, к которому вы добавляете это.

, затем, основываясь на текущем действии и контроллере, помощник добавит или нет класс active при создании привязки.

6 голосов
/ 30 июня 2013

Расширяя пример Дарина, вот полный класс, который добавляет дополнительные необязательные параметры для 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 голосов
/ 27 мая 2015

Обновлено для 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;


    }
}
2 голосов
/ 05 февраля 2013

Используйте этот InnerHtml, если вы хотите включить форматирование HTML в ваш текст;

li.InnerHtml = "<a href=\"" + new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(action, controller).ToString() + "\">" + text + "</a>";

текст может быть " Полужирный Обычный";

0 голосов
/ 20 апреля 2016

это расширение класса Дарина для вставки 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>
0 голосов
/ 13 ноября 2013

Этот код отлично работал для меня даже в новом проекте Visual Studio 2013 MVC5 / Bootstrap.Также обратите внимание, что вы можете изменить li.AddCssClass ("active");строка, указывающая на пользовательский класс, если вы хотите оставить Bootstrap «активный» класс в покое.Я добавил один файл с именем "activemenu" в файл Site.css проекта и внес в него все необходимые изменения стиля панели навигации.

Строка в приведенном выше коде была просто изменена на это, чтобы все заработало:

li.AddCssClass("activemenu");

В Site.css я добавил для своей цели простой класс:

.activemenu {
    text-decoration: underline;
}

В качестве альтернативы вы можете изменить цвет фона и / или границы и т. Д. ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...