Меню навигации с подсветкой в Asp.NET MVC?

Это простой вопрос. Как stackoverflow сделал свое меню в Asp.net MVC, с выделите, на какой странице мы находимся.

7 ответов


вероятно, нет специальной магии MVC,которая делает это.

Я уверен, что:

if( HttpContext.Current.Request.Path == "some some menu url" )

или

if( ViewContext_Or_ControllerContext.RouteData.Values["controller"] == "some value") 

используется где-то.

вы можете поместить этот код примерно в три разных места ( View ( .aspx), ViewModel, Custom HtmlHelper), и все они потребуют тот же бит кода.


для этого я написал некоторый код вниз, есть часть, которая использует мое пользовательское расширение, как язык, идти вперед и использовать его, просто игнорировать незначительную часть.

этот я помещаю поверх моего частичного, который содержит меню, чтобы получить действие и контроллер, чтобы я мог передать это в расширение.

<%  string currentAction = ViewContext.RouteData.Values["action"].ToString();
    string currentController = ViewContext.RouteData.Values["controller"].ToString(); %>

Это элемент боковой панели, в основном это создаст тег " li " со ссылкой и вашим пользовательским классом, чтобы указать, является ли ссылка в настоящее время используется на странице / highlight.

public static string SidebarItem(this System.Web.Mvc.HtmlHelper html, string currentAction, string currentController, string action, string controller, string languageKey, params object[] args)
{
    TagBuilder tb = new TagBuilder("li");
    if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) && string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
    {
        tb.GenerateId("activemenu");
    }
    string text = html.Language(languageKey, args);
    string link = html.ActionLink(text, action, controller).ToHtmlString();
    tb.SetInnerText("{0}");
    return String.Format(tb.ToString(), "<span>"+link+"</span>");
}

и вот фактическое использование кода выше

<%= Html.SidebarItem(currentAction, currentController, "index", "home", "index") %>

1.Сначала создайте расширение

public class Extention
{
    public static Dictionary<Menu, Menu> GetDictionary()
    {
        Dictionary<Menu, Menu> urls = new Dictionary<Menu, Menu>();
        urls.Add(new Menu { Controller = "AppHome", Action = "Index" }, new Menu { Controller = "AppHome", Action = "Index" });
        urls.Add(new Menu { Controller = "Home", Action = "Index" }, new Menu { Controller = "Home", Action = "Index" });

        return urls;
    }
}
public static class HtmlExtensions
{
    public static MvcHtmlString ActionMenu(this HtmlHelper helper,String linkText,string actionName,String controllerName)
    {
        var tag= new TagBuilder("li");
        if(helper.ViewContext.RequestContext.IsCurrentRoute(null,controllerName,actionName)||
            helper.ViewContext.RequestContext.IsParentRoute(controllerName,actionName))
        {
            tag.AddCssClass("active");
        }
        else
        {
            tag.AddCssClass("inactive");
        }
        tag.InnerHtml = helper.ActionLink(linkText, actionName, controllerName).ToString();
        return MvcHtmlString.Create(tag.ToString());
    }
}
public static class RequestExtentions
{
    public static bool IsCurrentRoute(this RequestContext context, String areaName)
    {
        return context.IsCurrentRoute(areaName, null, null);
    }
    public static bool IsCurrentRoute(this RequestContext context, String areaName, String controllerName)
    {
        return context.IsCurrentRoute(areaName, controllerName, null);
    }
    public static bool IsCurrentRoute(this RequestContext context, String areaName, String controllerName, params String[] actionNames)
    {
        var routeData = context.RouteData;
        var routeArea = routeData.DataTokens["area"] as String;
        var current = false;

        if (((String.IsNullOrEmpty(routeArea) && String.IsNullOrEmpty(areaName)) || (routeArea == areaName)) &&
             ((String.IsNullOrEmpty(controllerName)) || (routeData.GetRequiredString("controller") == controllerName)) &&
             ((actionNames == null) || actionNames.Contains(routeData.GetRequiredString("action"))))
        {
            current = true;
        }
        return current;
    }
    public static bool IsParentRoute(this RequestContext context, String controller, String action)
    {
        var routeData = context.RouteData;
        Menu returnUrl = null;
        Menu requestUrl = new Menu { Action = routeData.GetRequiredString("action"), Controller = routeData.GetRequiredString("controller") };
        Menu linkUrl = new Menu { Action = action, Controller = controller };

        var urls = Extention.GetDictionary();
        urls.TryGetValue(requestUrl, out returnUrl);

        if (returnUrl != null && returnUrl.Equals(linkUrl))
            return true;
        else
            return false; ;
    }
}

см. т. е. этот URL

http://stackoverflow.com/questions Это указывает на то, что, вероятно, вопросы контроллер обрабатывает эту страницу. Так это меняет посмотреть для отображения выделенного пункта меню.


Если вы посмотрите на источник страницы, они добавили класс css в <li> элемент для изменения цвета фона. Я предполагаю, что код смотрит на то, к какому контроллеру пользователь обращается (вопросы, пользователи и т. д.), и добавляет класс в этот раздел <li> тег.


вы можете использовать HTML-помощник для создания меню. Этак весь код находится в одном месте.

Карта сайта HtmlHelper ASP.NET MVC имеет некоторую информацию о компоненте, который доступен.


лучший способ-создать помощник MVC (см. предыдущие ответы) Но если вы не хотите этого делать и хотите сделать быстро-помните о новой функции в MVC 4.0 с установленными атрибутами html-тегов (атрибут будет избегать, если он установлен в null):

        @{
            string currentAction = ViewContext.RouteData.Values["action"].ToString().ToLower();

            string classUpcomingTime = null;
            string classArchive = null;
            string classReporting = null;

            switch (currentAction)
            {
                case "upcomingtime":
                    classUpcomingTime = "active";
                    break;
                case "archive":
                    classArchive = "active";
                    break;
                case "reporting":
                    classReporting = "active";
                    break;
            }

            <ul class="nav navbar-nav">
                <li class="@classUpcomingTime">
                    <a href="/Vacancy/UpcomingTime">Open Vacancies</a>
                </li>
                <li class="@classArchive">
                    <a href="/Vacancy/Archive">Archive</a>

                <li class="@classReporting">
                    @*<a href="#">Reporting</a>*@
                    <a href="/Vacancy/Reporting">Reporting</a>
                </li>
            </ul>
        }