如何在 ASP.NET MVC 中将“活动”类添加到 Html.ActionLink

我试图在 MVC 中的引导导航栏中添加一个“活动”类,但是下面这样写的时候并没有显示活动类:

<ul class="nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home", null, new {@class="active"})</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

这就解决了一个看起来像是格式正确的类,但是不起作用的问题:

<a class="active" href="/">Home</a>

在 Bootstrap 文档中,它声明‘ a’标记不应该在导航栏中使用,但是我认为上面的内容是将类添加到 Html 的正确方法。行动连结。还有其他(整洁的)方法我可以这样做吗?

173900 次浏览

如果它根本没有显示出来,原因是你需要两个@符号:

@@class

但是,我相信您可能需要在“ li”标记上使用活动类,而不是在“ a”标记上使用活动类。根据 too bootstrap 文档(http://getbootstrap.com/components/#navbar-default) :

<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Messages</a></li>
</ul>

因此,你的代码将是:

<ul class="nav navbar-nav">
<li class="active">@Html.ActionLink("Home", "Index", "Home", null)</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

在 Bootstrap 中,需要将 active类应用于 <li>元素,而不是 <a>元素。请看这里的第一个例子: http://getbootstrap.com/components/#navbar

你处理 UI 样式的方法是基于什么是活动的或不活动的与 ASP.NET MVC 的 ActionLink助手没有任何关系。这是遵循如何构建 Bootstrap 框架的正确解决方案。

<ul class="nav navbar-nav">
<li class="active">@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

编辑:

由于您很可能在多个页面上重复使用菜单,因此有一种方法可以根据当前页面自动应用选定的类,而不是多次复制菜单并手动进行操作,这将是一种明智的做法。

最简单的方法是简单地使用 ViewContext.RouteData中包含的值,即 ActionController值。我们可以在你现有的基础上建立这样的东西:

<ul class="nav navbar-nav">
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Index" ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "About" ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Contact" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

它的代码并不漂亮,但它可以完成工作,并允许您提取您的菜单到一个部分视图,如果您愿意。有很多方法可以干净利落地解决这个问题,但既然你才刚刚开始,我就不多说了。祝你学习 ASP.NET MVC 好运!


后期编辑:

这个问题似乎得到了一点流量,所以我认为我扔在一个更优雅的解决方案使用 HtmlHelper扩展。

编辑03-24-2015: 必须重写这个方法,以允许多个操作和控制器触发选定的行为,以及处理方法是从一个子操作部分视图调用,认为我会共享更新!

public static string IsSelected(this HtmlHelper html, string controllers = "", string actions = "", string cssClass = "selected")
{
ViewContext viewContext = html.ViewContext;
bool isChildAction = viewContext.Controller.ControllerContext.IsChildAction;


if (isChildAction)
viewContext = html.ViewContext.ParentActionViewContext;


RouteValueDictionary routeValues = viewContext.RouteData.Values;
string currentAction = routeValues["action"].ToString();
string currentController = routeValues["controller"].ToString();


if (String.IsNullOrEmpty(actions))
actions = currentAction;


if (String.IsNullOrEmpty(controllers))
controllers = currentController;


string[] acceptedActions = actions.Trim().Split(',').Distinct().ToArray();
string[] acceptedControllers = controllers.Trim().Split(',').Distinct().ToArray();


return acceptedActions.Contains(currentAction) && acceptedControllers.Contains(currentController) ?
cssClass : String.Empty;
}

使用.NET 核心:

public static string IsSelected(this IHtmlHelper htmlHelper, string controllers, string actions, string cssClass = "selected")
{
string currentAction = htmlHelper.ViewContext.RouteData.Values["action"] as string;
string currentController = htmlHelper.ViewContext.RouteData.Values["controller"] as string;


IEnumerable<string> acceptedActions = (actions ?? currentAction).Split(',');
IEnumerable<string> acceptedControllers = (controllers ?? currentController).Split(',');


return acceptedActions.Contains(currentAction) && acceptedControllers.Contains(currentController) ?
cssClass : String.Empty;
}

使用方法:

<ul>
<li class="@Html.IsSelected(actions: "Home", controllers: "Default")">
<a href="@Url.Action("Home", "Default")">Home</a>
</li>
<li class="@Html.IsSelected(actions: "List,Detail", controllers: "Default")">
<a href="@Url.Action("List", "Default")">List</a>
</li>
</ul>

@ dombenoit 给出的答案是正确的。尽管它引入了一些需要维护的代码。请检查下面的语法:

using (var nav = Html.Bootstrap().Begin(new Nav().Style(NavType.NavBar).SetLinksActiveByControllerAndAction()))
{
@nav.ActionLink("Link 1", "action1")
@nav.ActionLink("Link 2", "action2")
@nav.Link("External Link", "#")
}

注意 .SetLinksActiveByControllerAndAction()方法的使用。

如果您想知道是什么使得这种语法成为可能,请查看 MVC

添加“ . ToString”以改进 ASP.NET MVC 上的比较

<ul class="nav navbar-nav">
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Index" ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "About" ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
<li class="@(ViewContext.RouteData.Values["Action"].ToString() == "Contact" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>

--

分机:

public static MvcHtmlString LiActionLink(this HtmlHelper html, string text, string action, string controller)
{
var context = html.ViewContext;
if (context.Controller.ControllerContext.IsChildAction)
context = html.ViewContext.ParentActionViewContext;
var routeValues = context.RouteData.Values;
var currentAction = routeValues["action"].ToString();
var currentController = routeValues["controller"].ToString();


var str = String.Format("<li role=\"presentation\"{0}>{1}</li>",
currentAction.Equals(action, StringComparison.InvariantCulture) &&
currentController.Equals(controller, StringComparison.InvariantCulture) ?
" class=\"active\"" :
String.Empty, html.ActionLink(text, action, controller).ToHtmlString()
);
return new MvcHtmlString(str);
}

用法:

<ul class="nav navbar-nav">
@Html.LiActionLink("About", "About", "Home")
@Html.LiActionLink("Contact", "Contact", "Home")
</ul>

我们还可以从 RequestContext 创建 UrlHelper,我们可以从 MvcHandler 本身获得它。因此,我相信对于那些希望在 Razor 模板中保持这种逻辑的人来说,以下方式会有所帮助:

  1. 在项目根目录中创建一个名为 AppCode的文件夹。
  2. 在那里创建一个名为 HtmlHelpers.cshtml的文件
  3. 在这里创建一个助手:

    @helper MenuItem(string action, string controller)
    {
    var mvcHandler = Context.CurrentHandler as MvcHandler;
    if (mvcHandler != null)
    {
    var url = new UrlHelper(mvcHandler.RequestContext);
    var routeData = mvcHandler.RequestContext.RouteData;
    var currentAction = routeData.Values["action"].ToString();
    var currentController = routeData.Values["controller"].ToString();
    var isCurrent = string.Equals(currentAction, action, StringComparison.InvariantCultureIgnoreCase) &&
    string.Equals(currentController, controller, StringComparison.InvariantCultureIgnoreCase);
    
    
    <div class="@(isCurrent ? "active" : "")">
    <div>@url.Action(action, controller)</div>
    </div>
    }
    }
    
  4. Then we can use on our views like this:

    @HtmlHelpers.MenuItem("Default", "Home")
    

Hope that it helps to someone.

我通过在 asp.net mvc 中添加一个 view bag 参数来实现这一点

在每个页面中添加了类似于 ViewBag.Current = "Scheduler";的参数

在布局页面

<ul class="nav navbar-nav">
<li class="@(ViewBag.Current == "Scheduler" ? "active" : "") "><a href="@Url.Action("Index","Scheduler")" target="_self">Scheduler</a></li>
</ul>

这解决了我的问题。

我也在寻找一个解决方案,而 jQuery 帮了我很大的忙。首先,需要为 <li>元素赋予 id。

<li id="listguides"><a href='/Guides/List'>List Guides</a></li>

在布局页面中执行此操作之后,可以告诉 jQuery 在视图中应该“选择”哪个 <li>元素。

@section Scripts{
<script type="text/javascript">
$('#listguides').addClass('selected');
</script>
}

注意: 您需要在布局页面中的 @RenderSection("scripts", required: false),就在 </body>标记之前添加该部分。

我修改了 Dom 的 "not pretty" answer,使它更难看。有时两个控制器的操作名称(即 Index)相互冲突,所以我这样做:

<ul class="nav navbar-nav">
<li class="@(ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString() == "HomeIndex" ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
<li class="@(ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString() == "AboutIndex" ? "active" : "")">@Html.ActionLink("About", "Index", "About")</li>
<li class="@(ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString() == "ContactHome" ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

我知道这个问题已经很老了,但是我想在这里加上我的声音。我相信将链接是否处于活动状态的知识留给视图的控制器是一个好主意。

我只是为控制器操作中的每个视图设置一个唯一的值。例如,如果我想激活主页链接,我会这样做:

public ActionResult Index()
{
ViewBag.Title = "Home";
ViewBag.Home = "class = active";
return View();
}

那么在我看来,我会这样写:

<li @ViewBag.Home>@Html.ActionLink("Home", "Index", "Home", null, new { title = "Go home" })</li>

当您导航到不同的页面时,例如“程序”、“视图包”。主页不存在(取而代之的是 ViewBag。因此,不呈现任何内容,甚至 class = “”也不呈现。我认为这对于可维护性和清洁性都更清洁。我总是倾向于尽可能地不去考虑逻辑问题。

我想根据唐的第一部分回答提出这个解决方案。

我们首先定义两个变量,“ action”和“ controller”,并使用它们来确定活动链接:

{ string controller = ViewContext.RouteData.Values["Controller"].ToString();
string action = ViewContext.RouteData.Values["Action"].ToString();}

然后:

<ul class="nav navbar-nav">
<li class="@((controller == "Home" && action == "Index") ? "active" : "")">@Html.ActionLink("Home", "Index", "Home")</li>
<li class="@((controller == "Home" && action == "About") ? "active" : "")">@Html.ActionLink("About", "About", "Home")</li>
<li class="@((controller == "Home" && action == "Contact") ? "active" : "")">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

现在它看起来更好,不需要更复杂的解决方案。

可能有点晚了,但希望这个能帮上忙。

public static class Utilities
{
public static string IsActive(this HtmlHelper html,
string control,
string action)
{
var routeData = html.ViewContext.RouteData;


var routeAction = (string)routeData.Values["action"];
var routeControl = (string)routeData.Values["controller"];


// both must match
var returnActive = control == routeControl &&
action == routeAction;


return returnActive ? "active" : "";
}
}

用法如下:

<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class='@Html.IsActive("Home", "Index")'>
@Html.ActionLink("Home", "Index", "Home")
</li>
<li class='@Html.IsActive("Home", "About")'>
@Html.ActionLink("About", "About", "Home")
</li>
<li class='@Html.IsActive("Home", "Contact")'>
@Html.ActionLink("Contact", "Contact", "Home")
</li>
</ul>
</div>

http://www.codingeverything.com/2014/05/mvcbootstrapactivenavbar.html得到的参考资料

你可以试试这个: 在我的情况下,我加载菜单从数据库基于角色的访问,写的代码在你的每一个视图哪一个菜单你想要活跃的基于你的视图。

<script type="text/javascript">
$(document).ready(function () {
$('li.active active-menu').removeClass('active active-menu');
$('a[href="/MgtCustomer/Index"]').closest('li').addClass('active active-menu');
});
</script>

我已经把上面的答案组合起来并做出了我的解决方案。

所以. 。

首先在剃须刀块创建一个字符串变量,它将包含控制器的名称值和用户调用的操作。

    @{
string controllerAction =  ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString();
}

然后使用 HTML 和 Razor 代码的组合:

    <ul class="nav navbar-nav">
<li class="@(controllerAction == "HomeIndex" ? "active" : "" )">@Html.ActionLink("Home", "Index", "Home")</li>
<li class="@(controllerAction == "AboutIndex" ? "active" : "" )">@Html.ActionLink("About", "Index", "About")</li>
<li class="@(controllerAction == "HomeContact" ? "active" : "" )">@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

我认为,这是好事,因为你不需要访问“ ViewContext。路由数据。值”,以获取控制器名称和操作名称。

用 lambda 函数是可能的

@{
string controllerAction = ViewContext.RouteData.Values["Controller"].ToString() + ViewContext.RouteData.Values["Action"].ToString();
Func<string, string> IsSelected= x => x==controllerAction ? "active" : "";
}

然后使用

 @Html.ActionLink("Inicio", "Index", "Home", new { area = "" }, new { @class = IsSelected("HomeIndex")})

我意识到这个问题对于我们中的一些人来说是一个普遍的问题,所以我用 nuget 包发布了我自己的解决方案。下面你可以看到它是如何工作的。我希望这会有用。

注意: 这是我的第一个包。所以如果你看到一个错误,请给予反馈。谢谢。

  1. 安装 Package 或下载源代码并添加项目

    -Install-Package Betalgo.MvcMenuNavigator
    
  2. Add your pages to an enum

    public enum HeaderTop
    {
    Dashboard,
    Product
    }
    public enum HeaderSub
    {
    Index
    }
    
  3. Put Filter to top of your Controllor or Action

    [MenuNavigator(HeaderTop.Product, HeaderSub.Index)]
    public class ProductsController : Controller
    {
    public async Task<ActionResult> Index()
    {
    return View();
    }
    
    
    [MenuNavigator(HeaderTop.Dashboard, HeaderSub.Index)]
    public async Task<ActionResult> Dashboard()
    {
    return View();
    }
    }
    
  4. And use it In your header layout like this

    @{
    var headerTop = (HeaderTop?)MenuNavigatorPageDataNavigatorPageData.HeaderTop;
    var headerSub = (HeaderSub?)MenuNavigatorPageDataNavigatorPageData.HeaderSub;
    }
    <div class="nav-collapse collapse navbar-collapse navbar-responsive-collapse">
    <ul class="nav navbar-nav">
    <li class="@(headerTop==HeaderTop.Dashboard?"active selected open":"")">
    <a href="@Url.Action("Index","Home")">Dashboard</a>
    </li>
    <li class="@(headerTop==HeaderTop.Product?"active selected open":"")">
    <a href="@Url.Action("Index", "Products")">Products</a>
    </li>
    </ul>
    

更多资讯: https://github.com/betalgo/MvcMenuNavigator

这个解决方案对 Asp.net MCV 5来说很简单。

  1. 创建一个静态类,例如 Utilitarios.cs

  2. 在 Class 中创建一个静态方法:

    public static string IsLinkActive(this UrlHelper url, string action, string controller)
    {
    if (url.RequestContext.RouteData.Values["controller"].ToString() == controller &&
    url.RequestContext.RouteData.Values["action"].ToString() == action)
    {
    return "active";
    }
    
    
    return "";
    }
    
  3. call like this

    <ul class="sidebar-menu" data-widget="tree">
    <li class="header">HEADER</li>
    <li class="@Url.IsLinkActive("Index", "Home")">
    <a href="@Url.Action("Index", "Home")"><i class="fa fa-link"></i> <span>Home</span></a>
    </li>
    <li class="@Url.IsLinkActive("About", "Home")">
    <a href="@Url.Action("About", "Home")"><i class="fa fa-link"></i><span>About</span></a>
    </li>
    </ul>
    

我对这个问题的解决办法是

<li class="@(Context.Request.Path.Value.ToLower().Contains("about") ? "active " : "" ) nav-item">
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="About">About</a>
</li>

更好的方法可能是添加一个 Html 扩展方法来返回要与 link 进行比较的当前路径

考虑到 Damith 发布的内容,我认为你可以通过 视图包,标题来限定活动(最佳实践是在你的内容页面中填充它,允许你的 _Layout.cshtml页面保持你的链接栏)。还要注意的是,如果你使用的是 子菜单项,它也可以很好地工作:

<li class="has-sub @(ViewBag.Title == "Dashboard 1" || ViewBag.Title == "Dashboard 2" ? "active" : "" )">
<a href="javascript:;">
<b class="caret"></b>
<i class="fa fa-th-large"></i>
<span>Dashboard</span>
</a>
<ul class="sub-menu">
<li class="@(ViewBag.Title == "Dashboard 1" ? "active" : "")"><a href="index.html">Dashboard v1</a></li>
<li class="@(ViewBag.Title == "Dashboard 2" ? "active" : "")"><a href="index_v2.html">Dashboard v2</a></li>
</ul>
</li>

我相信这里有一个更简洁、更小巧的代码,可以让选中的菜单处于“活动”状态:

 <ul class="navbar-nav mr-auto">
<li class="nav-item @Html.IfSelected("Index")">
<a class="nav-link" href="@Url.Action("Index", "Home")">Home</a>
</li>
<li class="nav-item @Html.IfSelected("Controls")">
<a class="nav-link" href="@Url.Action("Controls", "Home")">MVC Controls</a>
</li>
<li class="nav-item @Html.IfSelected("About")">
<a class="nav-link" href="@Url.Action("About", "Home")">About</a>
</li>
</ul>

 public static string IfSelected(this HtmlHelper html, string action)
{
return html
.ViewContext
.RouteData
.Values["action"]
.ToString() == action
? " active"
: "";
}

我创建了一个 HtmlHelper扩展,它为那些希望将“活动”类添加到链接本身而不是链接周围的 <li>的用户添加了一个 ActiveActionLink方法。


public static class LinkExtensions
{
public static MvcHtmlString ActiveActionLink(this HtmlHelper html, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
return ActiveActionLink(html, linkText, actionName, controllerName, new RouteValueDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}


public static MvcHtmlString ActiveActionLink(this HtmlHelper html, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
{
const string activeClassName = "active";


var routeData = html.ViewContext.RouteData;


var routeAction = (string)routeData.Values["action"];
var routeController = (string)routeData.Values["controller"];


var active = controllerName.Equals(routeController) && actionName.Equals(routeAction);


if (active)
{
var @class = (string)htmlAttributes["class"];


htmlAttributes["class"] = string.IsNullOrEmpty(@class)
? activeClassName
: @class + " active";
}


var link = html.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);


return link;
}
}


用法如下:

@Html.ActiveActionLink("Home", "Index", "Home", new { area = "" }, new { @class = "nav-item nav-link" })

我是这么做的:

在菜单部分视图中创建了一个助手

 @helper RouterLink(string action, string controller)
{
var IsActive = ViewContext.RouteData.Values["Controller"].ToString() == controller && ViewContext.RouteData.Values["Action"].ToString() == action;
<text>href="@Url.Action(action, controller)"</text>if (IsActive){ <text>class="active"</text>}
}

然后像这样在锚标签中使用它:

<li><a @RouterLink("Index","Home")>Home</a></li>

我的应用程序没有区域,但是它也可以作为另一个变量包含在 helper 函数中。我必须将活动类传递给视图中的锚标记。但是 li也可以这样配置。

NET 核心和引导程序4

最新的答案

我重新工作的 @ 暗恋的整洁的解决方案,为一个更新,ASP.NET 核心鞋带4兼容的方式来解决这个问题,基于 IHtmlHelper扩展方法:

public static class LinkExtensions
{
public static IHtmlContent ActiveActionLink(this IHtmlHelper html, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
return ActiveActionLink(html, linkText, actionName, controllerName, new RouteValueDictionary(routeValues), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}


public static IHtmlContent ActiveActionLink(this IHtmlHelper html, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
{
var routeData = html.ViewContext.RouteData;
var routeAction = (string)routeData.Values["action"];
var routeController = (string)routeData.Values["controller"];


var active = controllerName.Equals(routeController) && actionName.Equals(routeAction);


using (var writer = new StringWriter())
{
writer.WriteLine($"<li class='nav-item {(active ? "active" : "")}'>");
html.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes).WriteTo(writer, HtmlEncoder.Default);
writer.WriteLine("</li>");
return new HtmlString(writer.ToString());
}
}
}

用法

<nav class="navbar">
<div class="collapse navbar-collapse">
<ul class="navbar-nav">
@Html.ActiveActionLink("Home", "Index", "Home", null, new { @class = "nav-link" })
@Html.ActiveActionLink("About", "About", "Home", null, new { @class = "nav-link" })
@Html.ActiveActionLink("Contact", "Contact", "TimeTracking", null, new { @class = "nav-link" })
</ul>
</div>
</nav>

简单的 ASP.NET Core 3.0和 TagHelpers

[HtmlTargetElement("li", Attributes = "active-when")]
public class LiTagHelper : TagHelper
{
public string ActiveWhen { get; set; }


[ViewContext]
[HtmlAttributeNotBound]
public ViewContext ViewContextData { get; set; }


public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (ActiveWhen == null)
return;


var targetController = ActiveWhen.Split("/")[1];
var targetAction = ActiveWhen.Split("/")[2];


var currentController = ViewContextData.RouteData.Values["controller"].ToString();
var currentAction = ViewContextData.RouteData.Values["action"].ToString();


if (currentController.Equals(targetController) && currentAction.Equals(targetAction))
{
if (output.Attributes.ContainsName("class"))
{
output.Attributes.SetAttribute("class", $"{output.Attributes["class"].Value} active");
}
else
{
output.Attributes.SetAttribute("class", "active");
}
}
}
}

包含到你的视图中:

@addTagHelper *, YourAssemblyName

用法:

 <li active-when="/Home/Index">

关于这个问题的大多数解决方案都要求您在 li 还有a(通过 HtmlHelper)标记上指定“页面”。@ Wolles@ Crush的答案都消除了这种重复,这很好,但是他们使用的是 HtmlHelper 扩展方法而不是 TagHelpers。我想使用一个 TagHelper还有支持剃刀页面。

您可以阅读 我在这里的全职工作(并获得源代码) ,但它的要点是:

<bs-menu-link asp-page="/Events/Index" menu-text="Events"></bs-menu-link>

将呈现(如果链接显然是活动的) :

<li class="active"><a href="/Events">Events</a></li>

我的 TagHelper 在内部利用 AnchorTagHelper(因此支持 asp-page、 asp-controller、 asp-action 等属性)。“检查”是否激活与这篇文章的许多答案相似。

NET 内核 & Bootstrap 4 & AdminLte

[HtmlTargetElement("a", Attributes = "active-then")]
[HtmlTargetElement("a", Attributes = "asp-action")]
[HtmlTargetElement("a", Attributes = "asp-controller")]
public class AnchorActiveTagHelper : AnchorTagHelper
{
public AnchorActiveTagHelper(IHtmlGenerator generator) : base(generator)
{
}


[HtmlAttributeName("active-then")]
public string ActiveWhen { get; set; }


[ViewContext] [HtmlAttributeNotBound] public ViewContext ViewContextData { get; set; }


public override void Process(TagHelperContext context, TagHelperOutput output)
{
base.Process(context, output);
        

if (ActiveWhen == null)
return;


var currentController = ViewContextData.RouteData.Values["controller"].ToString();
var currentAction = ViewContextData.RouteData.Values["action"].ToString();


if (currentController.Equals(Controller) && currentAction.Equals(Action))
{
if (output.Attributes.ContainsName("class"))
{
output.Attributes.SetAttribute("class", $"{output.Attributes["class"].Value} active");
}
else
{
output.Attributes.SetAttribute("class", "active");
}
}
}
}

还有

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, YourProject.PlatformExtensions

用法

<li class="nav-item">
<a asp-controller="Home" asp-action="Index" class="nav-link" active-then="active">
<i class="nav-icon fas fa-home"></i>
<p>Home</p>
</a>
</li>

谢谢

我找到了多条路线的解决方案。 贴标助手:

[HtmlTargetElement("li", Attributes = "active-when")]
public class ActiveTagHelper : TagHelper
{
[HtmlAttributeName("active-when")]
public string ActiveWhen { get; set; }


[ViewContext]
[HtmlAttributeNotBound]
public ViewContext ViewContext { get; set; }


public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (ActiveWhen == null)
return;


var hrefs = ActiveWhen.Split(",");


var currentController = ViewContext.RouteData.Values["controller"].ToString();
var currentAction = ViewContext.RouteData.Values["action"].ToString();


foreach (var item in hrefs)
{
var targetController = item.Split("/")[1];
var targetAction = item.Split("/")[2];


if (currentController.Equals(targetController) && currentAction.Equals(targetAction))
{
if (output.Attributes.ContainsName("class"))
{
output.Attributes.SetAttribute("class", $"{output.Attributes["class"].Value} active");
}
else
{
output.Attributes.SetAttribute("class", "active");
}
}
}
}
}

进口:

@addTagHelper *, YourProjectName

用法:

   <li class="nav-item" active-when="/Product/Index,/Product/Add"></li>

在布局页面的顶部,

@{ var _path = Context.Request.Path.ToString();}

在你的导航栏里,

<a class="nav-link dropdown-toggle @(_path.Contains("UTBulkFlights") ? "active" : "")">abcLink</a>