带有引导导航栏的 MVC - 将所选项目设置为活动
Posted
技术标签:
【中文标题】带有引导导航栏的 MVC - 将所选项目设置为活动【英文标题】:MVC with Bootstrap Navbar - Set Selected Item to Active 【发布时间】:2014-04-19 21:13:00 【问题描述】:我正在学习 Bootstrap,无法将所选项目置于“活动”状态。活动状态保持在默认项目上。新选择/单击的项目会短暂变为活动状态,但会恢复。我已阅读所有帖子,但仍然无法使此代码正常工作。我正在使用 MVC5 和 JQuery 2.1。
编辑: 如果我将 li 的 href 更改为 href="#",则活动类将正确应用。加载新视图时会发生什么?我认为塞巴斯蒂安的反应很接近,但对区域很混乱。
标记
<div class="navbar-wrapper">
<div class="container">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-header">
<a class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="navbar-brand" href="#">Test</a>
</div>
<div class="btn-group pull-right">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<i class="icon-user"></i>Login
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#">Profile</a></li>
<li class="divider"></li>
<li><a href="#">Sign Out</a></li>
</ul>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="~/Home">Home</a></li>
<li><a href="~/Home/About">About</a></li>
<li><a href="~/Student">Students Sample</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="~/Admin/Home/Index"">Admin</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<!-- /container -->
</div>
<!-- /navbar wrapper -->
脚本
<script type="text/javascript">
$(function ()
$('.navbar-nav li').click(function ()
$(this).addClass('active').siblings().removeClass('active');
);
);
</script>
编辑: 这是我在发布的答案和一些研究的帮助下最终完成的工作。
public static string MakeActive(this UrlHelper urlHelper,string action, string controller, string area = "")
string result = "active";
string requestContextRoute;
string passedInRoute;
// Get the route values from the request
var sb = new StringBuilder().Append(urlHelper.RequestContext.RouteData.DataTokens["area"]);
sb.Append("/");
sb.Append(urlHelper.RequestContext.RouteData.Values["controller"].ToString());
sb.Append("/");
sb.Append(urlHelper.RequestContext.RouteData.Values["action"].ToString());
requestContextRoute = sb.ToString();
if (string.IsNullOrWhiteSpace(area))
passedInRoute = "/" + controller + "/" + action;
else
passedInRoute = area + "/" + controller + "/" + action;
// Are the 2 routes the same?
if (!requestContextRoute.Equals(passedInRoute, StringComparison.OrdinalIgnoreCase))
result = null;
return result;
【问题讨论】:
您是否为这个 BigDaddy 找到了明确的解决方案?我一直想给某人打电话……特别是。汉斯·帕桑特! @Killercam...看看我的编辑。它显示了我的想法。这是公认答案的扩展。 【参考方案1】:使用代码from here 的简化版本,如果控制器和动作匹配(或者如果没有提供动作,则只标记控制器),您可以使用标签助手将锚标记为“活动”。
导航:
<li class="nav-item px-2">
<a class="nav-link" asp-active-route asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item px-2">
<a class="nav-link" asp-active-route asp-controller="Car" asp-action="Add">Add Car</a>
</li>
标签助手类
[htmlTargetElement(Attributes = "asp-active-route")]
public class ActiveRouteTagHelper : TagHelper
[HtmlAttributeName("asp-controller")] public string Controller get; set;
[HtmlAttributeName("asp-action")] public string Action get; set;
[HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext get; set;
public override void Process(TagHelperContext context, TagHelperOutput output)
if (IsActive())
output.AddClass("active", HtmlEncoder.Default);
output.Attributes.RemoveAll("asp-active-route");
base.Process(context, output);
private bool IsActive()
var currentController = ViewContext.RouteData.Values["Controller"].ToString();
var currentAction = ViewContext.RouteData.Values["Action"].ToString();
var active = false;
if (!string.IsNullOrWhiteSpace(Controller) && !string.IsNullOrWhiteSpace(currentController))
active = Controller.Equals(currentController, StringComparison.CurrentCultureIgnoreCase);
if (active && !string.IsNullOrWhiteSpace(Action) && !string.IsNullOrWhiteSpace(currentAction))
active = Action.Equals(currentAction, StringComparison.CurrentCultureIgnoreCase);
return active;
不要忘记将标签助手添加到您的 _ViewImports.cshtml
@addTagHelper *, My.Awesome.Web
未来的改进将是检查区域并可能将整个导航包裹在控件/助手中,这样您只需比较一次路线并标记项目
【讨论】:
【参考方案2】:只需添加这个 JQuery 编码:
<script>
$(document).ready(function ()
$('body').find('a[href="' + location.pathname + '"]')
.addClass('active');
);
</script>
【讨论】:
【参考方案3】:您可以在任何视图中执行此操作
<ul class="nav navbar-nav">
@Html.NavigationLink("Link1", "Index", "Home")
@Html.NavigationLink("Link2", "Index", "Home")
@Html.NavigationLink("Link3", "Index", "Home")
@Html.NavigationLink("Links with Parameter", "myAction", "MyController", new id=999, new @class= " icon-next" )
</ul>
将此方法添加到新类或现有 HtmlExtensions 类后
public static class HtmlExtensions
public static MvcHtmlString NavigationLink(this HtmlHelper html, string linkText, string action, string controller, object routeValues=null, object css=null)
TagBuilder aTag = new TagBuilder("a");
TagBuilder liTag = new TagBuilder("li");
var htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(css);
string url = (routeValues == null)?
(new UrlHelper(html.ViewContext.RequestContext)).Action(action, controller)
:(new UrlHelper(html.ViewContext.RequestContext)).Action(action, controller, routeValues);
aTag.MergeAttribute("href", url);
aTag.InnerHtml = linkText;
aTag.MergeAttributes(htmlAttributes);
if (action.ToLower() == html.ViewContext.RouteData.Values["action"].ToString().ToLower() && controller.ToLower() == html.ViewContext.RouteData.Values["controller"].ToString().ToLower())
liTag.MergeAttribute("class","active");
liTag.InnerHtml = aTag.ToString(TagRenderMode.Normal);
return new MvcHtmlString(liTag.ToString(TagRenderMode.Normal));
【讨论】:
记得把@using yourNamespace
放在你的视图中。就我而言,我把它放在我的视图布局_Layout.cshtml
如何使用此方法进行下拉?【参考方案4】:
最简单的做法是从您的控制器发送一个 ViewBag 参数,如下所示;
public ActionResult About()
ViewBag.Current = "About";
return View();
public ActionResult Contact()
ViewBag.Current = "Contact";
return View();
在cshtml页面中执行以下操作;
<ul class="nav navbar-nav">
<li class="@(ViewBag.Current == "About" ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
<li class="@(ViewBag.Current == "Contact" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
感谢@Damith here
【讨论】:
【参考方案5】:JavaScript 不工作,因为页面在运行后重新加载。所以它正确设置了活动项目,然后页面加载,因为浏览器正在跟踪链接。就个人而言,我会删除您拥有的 JavaScript,因为它没有任何用途。要执行此客户端(而不是您拥有的服务器端代码),您需要 JavaScript 在新页面加载时设置活动项。就像是:
$(document).ready(function()
$('ul.nav.navbar-nav').find('a[href="' + location.pathname + '"]')
.closest('li').addClass('active');
);
我建议您在导航栏中添加一个 id 或其他类,这样您就可以确定您选择了正确的。
【讨论】:
这就是我要找的! 谢谢!但是如何将上一个菜单项恢复为原始颜色(非活动) 对我来说很好用,也很简单。 JoshYates1980,不会有回发吗?如果不是,您可以在设置新课程之前删除所有活动课程。 谢谢!这就是我要找的。所有的程序员之神都会保佑你!【参考方案6】:您的 javascript 函数应该可以正常工作...问题是您的链接路由到控制器并重新加载整个页面。为了避免这种行为,您可以将正文内容呈现为部分视图,这样导航栏元素就不会重新加载。您不必编写函数来处理 dom 事件——这就是 javascript 的用途。
要明白我的意思,请更改您的代码:
<li><a href="~/Home/About">About</a></li>
<li><a href="~/Student">Students Sample</a></li>
到:
<li><a href="">About</a></li>
<li><a href="">Students Sample</a></li>
【讨论】:
【参考方案7】:您必须检查您的控制器或根据当前 url 查看哪个菜单项处于活动状态:
我有一个类似这样的扩展方法:
public static string MakeActiveClass(this UrlHelper urlHelper, string controller)
string result = "active";
string controllerName = urlHelper.RequestContext.RouteData.Values["controller"].ToString();
if (!controllerName.Equals(controller, StringComparison.OrdinalIgnoreCase))
result = null;
return result;
您可以像这样在视图中使用它:
<!-- Make the list item active when the current controller is equal to "blog" -->
<li class="@Url.MakeActive("blog")">
<a href="@Url.Action("index", "blog")">....</a>
</li>
【讨论】:
假设我有同名的控制器,因为它们位于区域中? 在这种情况下,您还必须检查该区域。很奇怪,但是你可以使用:object areaName = urlHelper.RequestContext.RouteData.DataTokens["area"] 谢谢,但应该有比这更干净的东西,对吧? 我并不喜欢这个解决方案,但它似乎是做这种事情的方式 - 根据我的研究。 只是一个小错字,扩展方法名应该是MakeActive而不是MakeActiveClass。【参考方案8】:我相信你的选择是倒退的。您正在添加课程,然后将其从兄弟姐妹中删除,我认为第二次删除会导致问题。您可以尝试将其反转为:
<script type="text/javascript">
$(function ()
$('.navbar-nav li').click(function ()
$(this).siblings().removeClass('active');
$(this).addClass('active');
);
);
</script>
【讨论】:
谢谢,但我得到了同样的行为 您还有其他对导航栏起作用的事件吗?您是否可以在 jsfiddle 中重现该问题? 没有其他事件。我从视图中发布所有代码。 因为方法链,他的脚本和你的一样。他的问题是他的链接请求一个新页面,当页面重新加载时活动项丢失了。以上是关于带有引导导航栏的 MVC - 将所选项目设置为活动的主要内容,如果未能解决你的问题,请参考以下文章
Silverlight Combobox 将所选项目设置为 datagrid 的所选项目