ASP.NET MVC: Masterpage: как установить класс css в активном пункте меню

У меня есть следующее меню на моей главной странице:

<ul id="menu" class="lavaLampBottomStyle">
    <li>
        <%= Html.ActionLink("Employees", "Index", "Employees")%></li>
    <li>
        <%= Html.ActionLink("Customer", "Details", "Account")%></li>
</ul>

Мне нужен способ установить класс css текущего активного li в "current".

Сначала я предполагаю, что это делается с помощью javascript.

Я бы включил что-то подобное на главной странице:

  $("#menu li a").each(){
    if($(this).attr("href") == '<%= *GET CURRENT PAGE* %>'){
       $(this).parent("li").addClass("current");
    }
  }

Это хороший подход?

Если это так, как я могу получить текущую часть URL-адреса, как в href?

Если это не так, то что вы предлагаете?: -)

FYI, сгенерированный html я после:

<ul id="menu" class="lavaLampBottomStyle">
    <li>
        <a href="/KszEmployees/Index">Employees</a></li>
    <li>
        <a class="current" href="/">Customer</a></li>
</ul>

Ответы

Ответ 1

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

Request.Url - это объект, который вас интересует, чтобы получить текущую страницу на стороне сервера. Предложение использовать window.location.href tvanfosson неплохо, если вы хотите сохранить его полностью на стороне клиента.

Преимущество использования serveride заключается в том, что Request.Url имеет легкодоступные части URL-адреса, такие как Request.Url.Host и т.д., чтобы помочь вам в ваших потребностях в ссылках.

Ответ 2

Если вы хотите сделать это на всех серверах, я сделал это раньше. Создайте атрибут фильтра действий:

public class PageOptionsAttribute : ActionFilterAttribute
{
    public string Title { get; set; }
    public string Section { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var controller = filterContext.Controller as ControllerBase;
        if (controller != null)
        {
            controller.SetPageSection(this.Section);
            controller.SetPageTitle(this.Title);
        }

        base.OnActionExecuting(filterContext);
    }
}

Это вызывает два метода в моем классе ControllerBase, которые все мои контроллеры наследуют от:

public class ControllerBase : Controller
{
    public void SetPageSection(string section)
    {
                    // use the section defined or the controller name if none
        ViewData["PageSection"] = section != null ? 
                        section : this.RouteData.Values["controller"].ToString();
    }

    public void SetPageTitle(string title)
    {
        ViewData["PageTitle"] = title;
    }
}

Задайте раздел заголовка и страницы о методах контроллера:

public class HomeController : ControllerBase
{
    [PageOptions(Title="Home Page", Section="Home")]
    public ActionResult Index()
    { }
 }

Затем я вызываю значение ViewData на моей главной странице (это не будет мешать ViewData.Model):

<body class="<%=ViewData["PageSection"] %>">

Затем, чтобы ссылаться через CSS, вместо вызова .current, дайте каждому навигационному элементу идентификатор, а затем используйте класс body в сочетании с этим идентификатором, чтобы определить текущую страницу.

body.home #HomeNav { /* selected */  }
body.about #AboutNav { /* selected */  }

Ответ 3

Извлечь текущее местоположение из окна. Затем используйте селектор, который задает значение атрибута href, чтобы выбрать только те элементы, которые соответствуют (предположительно только одному).

 var currentLocation = window.location.href;
 // probably needs to be massaged to extract just the path so that it works in dev/prod

$("#menu li a[href$="+currentLocation+"]").addClass("current");

Ответ 4

У меня была та же проблема. Используя следующие ответы, мне удалось собрать решение ниже.

fooobar.com/questions/85990/...

fooobar.com/questions/389256/...

В HtmlHelpers.cs:

public static class HtmlHelpers
{
    public static HtmlString MenuLink(
        this HtmlHelper htmlHelper,
        string linkText,
        string actionName,
        string controllerName
    )
    {
        var currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
        var currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");
        var link = htmlHelper.ActionLink(linkText, actionName, controllerName);
        var prefix = (actionName == currentAction && controllerName == currentController) ? String.Format("<li class=\"current\">") : String.Format("<li>");
        const string suffix = "</li>";
        return new HtmlString(prefix + link + suffix);
    }
}

В макете:

<ul class="nav nav-list">
    <li class="nav-header">Statistics</li>
    @Html.MenuLink("Number of logins", "Logins", "Statistics")
</ul>

Обратите внимание, что помощник MenuLink создает как тег li, так и тег a.

Отзыв об этом решении очень приветствуется!

Ответ 5

Это НЕ должно быть сделано с Javascript! Определение того, на какой странице вы работаете, является заданием кода на стороне сервера, это не поведение пользовательского интерфейса.

Указать меню в качестве пользовательского элемента управления и передать ему значение, чтобы указать, какая часть меню должна быть выделена. Я сторонник, а не разработчик .NET, но что-то вроде этого:

<yourControl:menuControl runat="server" ID="menu" selectedPage="4" />