Подтвердить что ты не робот

Выбранный элемент меню ASP.NET MVC

OK для MVC. Я ранее задавал этот вопрос и получил ответ, но мне интересно, есть ли более простое решение.

Скажем, у меня есть главная страница с меню, выложенным как неупорядоченный список. Как я могу настроить класс css в текущем выбранном пункте?

EDIT:

Я использую меню так же, как оно приходит из окна, когда вы запускаете новое приложение mvc

<ul id="menu">              
   <li><%: Html.ActionLink("Home", "Index", "Home")%></li>
   <li><%: Html.ActionLink("About", "About", "Home")%></li>
</ul>
4b9b3361

Ответ 1

Ответ от Якуба Конецки привел меня в правильном направлении... вот действие контроллера, в котором я закончил:

    [ChildActionOnly]
    public ActionResult MainMenu()
    {
        var items = new List<MenuItem>
        {
            new MenuItem{ Text = "Home", Action = "Index", Controller = "Home", Selected=false },
            new MenuItem{ Text = "My Profile", Action = "Index", Controller = "Profile", Selected = false},
            new MenuItem{ Text = "About", Action = "About", Controller = "Home", Selected = false }
        };

        string action = ControllerContext.ParentActionViewContext.RouteData.Values["action"].ToString();
        string controller = ControllerContext.ParentActionViewContext.RouteData.Values["controller"].ToString();

        foreach (var item in items)
        {
            if (item.Controller == controller && item.Action == action)
            {
                item.Selected = true;
            }
        }

        return PartialView(items);
    }

Надеюсь, это поможет кому-то.

Ответ 2

Вы должны передать всю соответствующую информацию в Модели. В идеале ваше меню будет отображаться как частичный вид с помощью отдельного метода контроллера. У меня есть контроллер навигации с такими действиями, как MainMenu, FooterMenu, Breadcrumbs и т.д., Которые отображают отдельные части.

Ваша модель будет представлять собой набор элементов меню, например:

    public class MenuItemModel
    {
        public MenuItemModel()
        {
            SubMenu = new List<MenuItemModel>();
        }

        public string Text { get; set; }
        public string Controller { get; set; }            
        public string Action { get; set; }
        public bool Selected { get; set; }

        public List<MenuItemModel> SubMenu { get; private set; }
    }

Ваш контроллер создаст коллекцию элементов меню и передаст их в представление с выбранным соответствующим элементом. Тогда представление может быть простым:

<ul id="menu">     
    <% foreach(var menuItem in Model.MenuItems) { %> 
        <li><%: Html.ActionLink(menuItem.Text, menuItem.Action, menuItem.Controller, null, new { @class = menuItem.Selected ? "selected" : "" })%></li>
    <% } %>
</ul>

Ответ 3

стивен,

вот мой вклад в партию. рекурсивную встроенную функцию для заполнения <ul><li> для такого количества глубин, сколько требуется (здесь весь файл ascx):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<GBC_Art.Controllers.MenuItemModel>>" %>
<%@ Import Namespace="GBC_Art.Controllers" %>
<%
    Action<List<MenuItemModel>, int> printNodesRecursively = null;
    printNodesRecursively = (List<MenuItemModel> nodeList, int depth) =>
    {
        if (nodeList == null || nodeList.Count == 0) return;
%>
    <ul<%= depth == 0 ? " id='menu'" : ""%>>  
<%
    foreach (var menuItem in nodeList)
    {
    %>
    <li><%= Html.ActionLink(menuItem.Text, menuItem.Action, menuItem.Controller, null, new { @class = menuItem.Selected ? "selected" : "" })%>
        <%printNodesRecursively(menuItem.SubMenu, depth + 1);%>
    </li>
    <%
        }
%>
    </ul>
<%
    };
    List<MenuItemModel> nodes = Model; 
    printNodesRecursively(nodes, 0);
%>

use → вызывается как частичное представление через контроллер в соответствии с вашим примером выше.

веселит

Ответ 4

Вот еще одна возможность, более простая, на мой взгляд, с помощью HTML-помощника:

Класс CSS

ul#menu li.selected a {
  background-color: #034af3;
  color: #e8eef4;
}

HTML-помощник

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;

namespace MyWebApp.WebUI.HtmlHelpers
{
  public static class HtmlHelperExtensions
  {
    public static string ActivePage(this HtmlHelper helper, string controller, string action)
    {
      string classValue = "";

      string currentController = helper.ViewContext.Controller.ValueProvider.GetValue("controller").RawValue.ToString();
      string currentAction = helper.ViewContext.Controller.ValueProvider.GetValue("action").RawValue.ToString();

      if (currentController == controller && currentAction == action)
      {
        classValue = "selected";
      }

      return classValue;
    }
  }
}

Меню на макете:

<nav>
  <ul id="menu">
    <li class="@Html.ActivePage("Home", "Index")">@Html.ActionLink("Home", "Index", "Home")</li>
    <li class="@Html.ActivePage("Home", "About")">@Html.ActionLink("About", "About", "Home")</li>
  </ul>
</nav>

Дополнительная информация здесь: http://bubblogging.wordpress.com/2012/02/12/mvc-add-selected-class-to-menu/

Ответ 5

Просто изучая MVC сейчас, но я столкнулся с этой проблемой, и я понял гораздо более быстрый способ достижения этого. Он полагается на согласованные URL-адреса и не зависит от строк запроса.

<ul id="menu">              
  <li @(Request.Path.Equals("/") ? Html.Raw("class=\"selected\"") : Html.Raw(""))>
    @Html.ActionLink("Home", "Index", "Home")</li>
  <li @(Request.Path.Equals("/about") ? Html.Raw("class=\"selected\"") : Html.Raw(""))>
    @Html.ActionLink("About", "About", "Home")%></li>
</ul>

Конечно, вы можете обрабатывать несколько URL-адресов, отображающих один и тот же элемент, выбранный с помощью логики OR или составляющий список. Но если вы составляете список, вы, конечно, хотите этого в своей модели. Вы можете выделить опцию для всего каталога, просто проверив, что начало строки соответствует.

Как это было бы, это было бы наиболее подходящим для более статического веб-сайта. Если вы включите это в LayoutPage, обслуживание будет довольно простым, так как у вас нет дополнительных классов или функций для поддержки. Очевидно, это не сократилось бы, если бы вы работали над CMS.

Ответ 6

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

на странице "Макет":

<body>
<header>
   @{Html.RenderPartial("_MenuPartial"); }
</header>
@RenderBody()
</body>

Затем ваш частичный вид содержит:

<nav class="navMain">
<ul>
   foreach (var menu in menuList)
   {
    <li id="@menu.Id"><a href="@menu.Url">@menu.Name</a></li>
   }
</ul>
</nav>

Чтобы активировать выбранное меню, вам нужно script в частичном представлении. Также "активный" класс ничем не отличается от изменения цвета фона в CSS.

<script>
var selector = '.navMain li';
$(selector).on('click', function () {
    $(this).addClass('active').siblings().removeClass('active');
    var menuId = $(this).prop("id");
    localStorage.setItem('SelectedMenu', menuId);
});

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

<script>
$(document).ready(function () {
    var activeMenuLocalStorage = localStorage.getItem('SelectedMenu');
    if (!isNaN(activeMenuLocalStorage)) {
    {
     $("#" + activeMenuLocalStorage).addClass('active');
    }
});