Asp.net mvc 加入“;主动的;asp.net mvc母版页中导航列表的标记
在默认asp.net mvc项目的Site.Master文件中,有一个菜单导航列表:Asp.net mvc 加入“;主动的;asp.net mvc母版页中导航列表的标记,asp.net-mvc,Asp.net Mvc,在默认asp.net mvc项目的Site.Master文件中,有一个菜单导航列表: <div id="menucontainer"> <ul id="menu"> <li><%= Html.ActionLink("Home", "Index", "Home")%></li> <li><%= Html.ActionLink("About Us", "A
<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>
这里的关键位是class=“active”
行。我不知道如何确定当前actionName是什么
有什么建议吗?或者,如果我完全走错了方向,有没有更好的方法来实现这一点?您的视图必须了解控制器的操作,这一事实正在打破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 --><% } %>
在你看来,你可以:
public ActionResult Index(){
ViewData["currentAction"] = "Index";
//... other code
return View();
}
<% if( ((string)ViewData["currentAction"]) == "Index" {%> <!- some links --><% } %>
<% if( ((string)ViewData["currentAction"]) == "SomethingElse" {%> <!- some links --><% } %>
然而,我想得越多,我就越怀疑为什么要对多个操作使用相同的视图。的观点是否类似
如果用例证明它是正确的,那么就按照我上面的建议去做。但是,否则,您可能会将问题分解为多个视图(每个控制器操作一个视图),问题会自行解决。试试看
应该很好
编辑:在BETA1中删除
已从ViewContext类中删除ViewName属性。在视图中,您可以使用以下内容获取当前操作名称:
ViewContext.RouteData.Values["action"].ToString()
根据前面的回答,以下是我目前针对同一问题的解决方案: 在母版页中,我给每个li一个对应于控制器和操作的id,因为这应该从ActionLink中知道。我以前是这样做的网页标题,但这有助于组织 网站主:
<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>
它比内联代码要复杂得多,但我认为它更简洁,还允许在不同的控制器中使用相同名称的操作。因此,如果添加更多具有不同控制器的菜单项,则并非所有名为Index的操作都将在菜单中高亮显示
如果有人发现此方法存在问题,请告诉我。您还可以尝试从控制器名称和视图名称中检测当前选定的选项卡,然后添加class属性
public static string MenuActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName)
{
var htmlAttributes = new RouteValueDictionary();
if (helper.ViewContext.Controller.GetType().Name.Equals(controllerName + "Controller", StringComparison.OrdinalIgnoreCase))
{
htmlAttributes.Add("class", "current");
}
return helper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), htmlAttributes);
}
这应该可以在客户端使用jQuery,使用Google提供最新的jQuery库:
<script src="http://www.google.com/jsapi" type="text/javascript" language="javascript"></script>
<script type="text/javascript" language="javascript">google.load("jquery", "1");</script>
<script language="javascript" type="text/javascript">
$(document).ready(function(){
var str=location.href.toLowerCase();
$('#menucontainer ul#menu li a').each(function() {
if (str.indexOf(this.href.toLowerCase()) > -1) {
$(this).attr("class","current"); //hightlight parent tab
}
});
});
</script>
load(“jquery”,“1”);
$(文档).ready(函数(){
var str=location.href.toLowerCase();
$('menucontainer ul#menu li a')。每个(函数(){
if(str.indexOf(this.href.toLowerCase())>-1){
$(this.attr(“class”,“current”);//高亮父选项卡
}
});
});
我让自己成为处理这类事情的助手方法。在我的母版页后面的代码中(可以被推到一个扩展方法…可能是更好的方法),我放了以下代码
protected string ActiveActionLinkHelper(string linkText, string actionName, string controlName, string activeClassName)
{
if (ViewContext.RouteData.Values["action"].ToString() == actionName &&
ViewContext.RouteData.Values["controller"].ToString() == controlName)
return Html.ActionLink(linkText, actionName, controlName, new { Class = activeClassName });
return Html.ActionLink(linkText, actionName, controlName);
}
然后,我就这样在我的页面中调用它:
<%= ActiveActionLinkHelper("Home", "Index", "Home", "selected")%>
public class LayoutAttribute : ActionFilterAttribute
{
private CurrentPage _currentPage { get; set; }
public LayoutAttribute(
CurrentPage CurrentPage
){
_currentPage = CurrentPage;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var result = filterContext.Result as ViewResultBase;
if (result == null || result.Model == null || !(result.Model is LayoutModel)) return;
((LayoutModel)result.Model).CurrentPage = _currentPage;
}
}
使用MVC3和Razor视图,您可以实现如下功能:
<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>
在MVC 3 Razor视图引擎中,您可以按以下方式执行:
@{string ctrName = ViewContext.RouteData.Values["controller"].ToString();}
<div id="menucontainer">
<ul id="menu">
<li @if(ctrName == "Home"){<text> class="active"</text>}>@ Html.ActionLink("Home", "Index", "Home")</li>
<li @if(ctrName == "About"){<text> class="active"</text>}>@ Html.ActionLink("About Us", "About", "Home")</li>
</ul>
</div>
以下是与MVC4当前版本兼容的版本。
我重写了Adam Carr的代码作为扩展方法
using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
namespace MyApp.Web {
public static class HtmlHelpers {
/// <summary>
/// Returns an anchor element (a element) that contains the virtual path of the
/// specified action. If the controller name matches the active controller, the
/// css class 'current' will be applied.
/// </summary>
public static MvcHtmlString MenuActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName) {
var htmlAttributes = new RouteValueDictionary();
string name = helper.ViewContext.Controller.GetType().Name;
if (name.Equals(controllerName + "Controller", StringComparison.OrdinalIgnoreCase))
htmlAttributes.Add("class", "current");
return helper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), htmlAttributes);
}
}
}
使用系统;
使用System.Web.Mvc;
使用System.Web.Mvc.Html;
使用System.Web.Routing;
名称空间MyApp.Web{
公共静态类HtmlHelpers{
///
///返回一个锚元素(元素),该元素包含
///指定的操作。如果控制器名称与活动控制器匹配,则
///将应用css类“当前”。
///
公共静态MvcHtmlString MenuActionLink(此HtmlHelper帮助程序、字符串链接文本、字符串操作名、字符串控制器名){
var htmlAttributes=新的RouteValueDictionary();
字符串名称=helper.ViewContext.Controller.GetType().name;
if(name.Equals(controllerName+“Controller”,StringComparison.OrdinalIgnoreCase))
HtmlatAttributes.Add(“类”、“当前”);
返回helper.ActionLink(linkText、actionName、controllerName、new RouteValueDictionary()、htmlAttributes);
}
}
}
为了给出我自己的答案(在MVC4中测试),我从其他答案中选取了一些最好的答案,修复了一些问题,并添加了一个帮助器来处理不一定通过控制器和操作解决的URL(例如,如果您有一个处理某些页面链接的嵌入式CMS,等等)
代码也可以在github上分叉:
我想对我的布局有更多的控制,这就是我所做的 创建其他模型继承的布局模型:
public abstract class LayoutModel
{
public CurrentPage CurrentPage { get; set; }
}
创建从ActionFilterAttribute继承的LayoutAttribute,如下所示:
<%= ActiveActionLinkHelper("Home", "Index", "Home", "selected")%>
public class LayoutAttribute : ActionFilterAttribute
{
private CurrentPage _currentPage { get; set; }
public LayoutAttribute(
CurrentPage CurrentPage
){
_currentPage = CurrentPage;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var result = filterContext.Result as ViewResultBase;
if (result == null || result.Model == null || !(result.Model is LayoutModel)) return;
((LayoutModel)result.Model).CurrentPage = _currentPage;
}
}
现在,在操作或控制器级别,我可以如下设置当前页面(如果需要,还可以设置其他内容):
[Layout(CurrentPage.Account)]
public class MyController : Controller
{
}
在我的布局视图中,我现在可以访问当前页面,以及我添加到布局模型中的任何其他内容。使用MVC3和Razor视图提供了另一个选项: _Layout.cshtml:
<li class="@ViewBag.NavClassHome">@Html.ActionLink("Home", "Index", "Home")</li>
<li class="@ViewBag.NavClassAbout">@Html.ActionLink("Disclaimer", "About", "Home")</li>
如果还希望为回发保留此值,则还必须在此处指定ViewBag值:
[HttpPost]
public ActionResult Index() {
ViewBag.NavClassHome = "active";
return View();
}
[HttpPost]
public ActionResult About() {
ViewBag.NavClassAbout = "active";
return View();
}
对我来说,测试和工作都很好,
[HttpPost]
public ActionResult Index() {
ViewBag.NavClassHome = "active";
return View();
}
[HttpPost]
public ActionResult About() {
ViewBag.NavClassAbout = "active";
return View();
}
@{
ViewBag.PageName = "Index";
}
<ul>
<li class="@(ViewContext.RouteData.Values["Controller"].ToString() == "Home" ? "active" : "")">
<a asp-area="" asp-controller="Home" asp-action="Index"><i class="icon fa fa-home"></i><span>Home</span>
</a>
</li>
</ul>