MVC新手。我之前问了this问题并得到了答案,但我想知道是否有更简单的解决方案。
假设我有一个母版页,其菜单列为无序列表。我如何在当前选择的菜单项上设置css类?
编辑:
当您启动新的mvc应用程序时,我正在使用菜单,因为它是开箱即用的设置
<ul id="menu">
<li><%: Html.ActionLink("Home", "Index", "Home")%></li>
<li><%: Html.ActionLink("About", "About", "Home")%></li>
</ul>
答案 0 :(得分:27)
Jakub Konecki的回答让我朝着正确的方向前进......这是我最终得到的控制器动作:
[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);
}
希望这有助于某人。
答案 1 :(得分:18)
您应该传递模型中的所有相关信息。理想情况下,您的菜单将通过单独的控制器方法呈现为部分视图。我有一个导航控制器,其中包含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>
答案 2 :(得分:4)
斯蒂芬,
这是我对党的贡献。一个递归内联函数,用于填充<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);
%>
用法 - &gt;根据上面的例子,通过控制器调用部分视图。
欢呼声
答案 3 :(得分:4)
这是另一种可能性,我认为使用HTML Helper更简单:
CSS类
ul#menu li.selected a {
background-color: #034af3;
color: #e8eef4;
}
HTML Helper
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/
答案 4 :(得分:2)
现在只是学习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>
当然,您可以处理多个网址,显示通过OR
逻辑或列表选择的相同项目。但如果你正在制作一个清单,你当然希望在你的模型中。只需检查字符串的开头是否匹配,就可以为整个目录选择一个选项。
原样,这最适合更静态的网站。如果将其包含在LayoutPage中,则维护非常简单,因为您没有要维护的额外类或函数。显然,如果你在CMS工作,这不会削减它。
答案 5 :(得分:1)
除了所有其他解决方案之外,您还可以使用此方法从数据库动态加载菜单,并使所选菜单处于活动状态并保持网站状态。
布局页面中的:
<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>
要激活单击的菜单,您需要在局部视图中使用脚本。除了改变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');
}
});
答案 6 :(得分:0)
editOrderContainer = jasmine.createSpyObj('editOrderContainer', ['getEditOrderState', 'rebookOrder']);
editOrderContainer.getEditOrderState.and.callFake(() => {
var editOrderState = getOrderDetailsServiceResult();
return Observable.of(editOrderState);
});
function getOrderDetailsServiceResult() {
return {
data: {
shipAddressEdited: true,
shipInstructionEditted: true
}
};
}
时最简单的方法..感谢@HugoHilário的概念
you don't want to change your code much
布局页面
using Microsoft.Web.Mvc;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace Demo.Web.Mvc
{
public static class UIHelper
{
public static MvcHtmlString ActivePage(this HtmlHelper helper, string linkText, string action, string controller)
{
string currentController = helper.ViewContext.Controller.ValueProvider.GetValue("controller").RawValue.ToString();
string currentAction = helper.ViewContext.Controller.ValueProvider.GetValue("action").RawValue.ToString();
var actionLink = helper.ActionLink(linkText, action,controller);
var isCurrentRoute = currentController == controller;// && currentAction == action; uncomment if you want to segregate by action also
return MvcHtmlString.Create(string.Format("<li{0}>", isCurrentRoute ? " class=\"YourActiveCssClass\"" : string.Empty) + actionLink + "</li>");
}
}
}