Добавление «активного» тега в список навигации на главной странице asp.net mvc - PullRequest
34 голосов
/ 18 октября 2008

В проекте MVC asp.net по умолчанию в файле Site.Master есть список навигации по меню:

<div id="menucontainer">
    <ul id="menu">              
        <li><%= Html.ActionLink("Home", "Index", "Home")%></li>
        <li><%= Html.ActionLink("About Us", "About", "Home")%></li>
    </ul>
</div>

В браузере отображается:

<div id="menucontainer"> 
    <ul id="menu">              
        <li><a href="/">Home</a></li> 
        <li><a href="/Home/About">About Us</a></li> 
    </ul> 
</div> 

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

<div id="menucontainer"> 
    <ul id="menu">              
        <li class="active"><a href="/">Home</a></li> 
        <li><a href="/Home/About">About Us</a></li> 
    </ul> 
</div> 

Я ожидаю, что способ сделать это будет что-то вроде:

<div id="menucontainer">
    <ul id="menu">              
        <li <% if(actionName == "Index"){%> class="active"<%}%>><%= Html.ActionLink("Home", "Index", "Home")%></li>
        <li <% if(actionName == "About"){%> class="active"<%}%>><%= Html.ActionLink("About Us", "About", "Home")%></li>
    </ul>
</div>

Ключевым битом здесь является строка <% if(actionName == "Index"){%> class="active"<%}%>. Я не знаю, как определить текущее имя actionName.

Есть предложения, как это сделать? Или, если я на неправильном пути, есть ли лучший способ сделать это?

Ответы [ 14 ]

0 голосов
/ 01 августа 2011

Используя MVC3 с Razor View, вы можете реализовать это следующим образом:

<ul id="menu">
 @if (ViewContext.RouteData.Values["action"].ToString() == "Index")
 {
 <li class="active">@Html.ActionLink("Home", "Index", "Home")</li>
 }
 else
 {
 <li>@Html.ActionLink("Home", "Index", "Home")</li>
 }
 @if (ViewContext.RouteData.Values["action"].ToString() == "About")
 {
 <li class="active">@Html.ActionLink("About", "About", "Home")</li>
 }
 else
 {
 <li>@Html.ActionLink("About", "About", "Home")</li>
 }
</ul>

А затем применить ваш стиль вашего класса ".active", например:

ul#menu li.active 
{
 text-decoration:underline;
}
0 голосов
/ 23 октября 2008

Основываясь на предыдущих ответах, вот мое текущее решение для той же проблемы:

На главной странице я даю каждому li идентификатор, соответствующий контроллеру и действию, так как это должно быть известно из ActionLink. Ранее я делал это с заголовком страницы, но это помогает с организацией.

Site.Master:

<ul id="menu">
    <li id="menuHomeIndex" runat="server"><%= Html.ActionLink("Home", "Index", "Home") %></li>
    <li id="menuHomeAbout" runat="server"><%= Html.ActionLink("About Us", "About", "Home") %></li>
</ul>

Site.Master.cs:

// This is called in Page_Load
private void SetActiveLink()
{
    string action = "" + ViewContext.RouteData.Values["controller"] + ViewContext.RouteData.Values["action"];
    var activeMenu = (HtmlGenericControl)Page.Master.FindControl("menu" + action);

    if (activeMenu != null)
    {
        activeMenu.Attributes.Add("class", "selected");
    }
}

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

Если кто-то видит проблемы с этим подходом, пожалуйста, дайте мне знать.

0 голосов
/ 19 октября 2008

Попробуйте

Должно работать нормально !!!

РЕДАКТИРОВАТЬ: УДАЛЕНО В BETA1

Удалено свойство ViewName из класса ViewContext.

0 голосов
/ 18 октября 2008

Тот факт, что ваш View должен знать о действиях вашего контроллера, нарушает паттерн MVC. Возможно, ваш контроллер мог бы передать некоторую «контрольную» информацию в представление, чтобы в конечном итоге позволить ему выполнить то же самое, единственное отличие состоит в том, кто отвечает.

Как и в действии вашего контроллера, вы могли бы:

public ActionResult Index(){
     ViewData["currentAction"] = "Index";
     //... other code
    return View();
}

Тогда, по вашему мнению, вы можете:

<% if( ((string)ViewData["currentAction"]) == "Index" {%> <!- some links --><% } %>
<% if( ((string)ViewData["currentAction"]) == "SomethingElse" {%> <!- some links --><% } %>

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

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

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