当用户选择页面时更改 _Layout.cshtml 中导航栏列表项文本的颜色

Change color of navbar list item text in _Layout.cshtml when page is selected by user

  1. 我在 _Layout.cshtml 中使用 bootstrap 导航栏。
  2. 在我的索引页面上,列表项 "Home" 显示为 color: rgba(255, 140, 0, 0.781),列表项 "Features" 显示为 color: green

期望的结果: 当我单击 "Features" link 并导航到 Features.cshtml 页面时,我想要 "Features" 列表项颜色更改为 color: rgba(255, 140, 0, 0.781),主页项更改为 color: green

如果我将导航栏标记放入每个 cshtml 页面,这很容易做到。但我只想在我的 _Layout.cshtml 页面中使用我的 bootstrap 导航栏。

_Layout.cshtml

<nav class="navbar navbar-expand-lg navbar-light">
    <div class="container">
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav mr-auto">
                <li class="nav-item active">
                    <a class="nav-link" style="color: rgba(255, 140, 0, 0.781)" asp-page="Index")>@_loc["Home"]</a>
                </li>
                <li class="nav-item active">
                    <a class="nav-link" style="color: green" asp-page="Features" localize-content>@_loc["Features"]</a>
                </li>
                <partial name="_LoginPartial" />
            </ul>
        </div>
    </div>
</nav>

通过在每个页面中为菜单栏放置 HTML,我可以很好地工作,但这不是一个好的解决方案,因为我将不得不单独维护我的菜单栏的多个实例。

我尝试了很多 Whosebug 项目,但没有找到适用于这种情况的项目。比如

我尝试按照 ForeColor 属性 的 MSDocs 进行操作,但也无法实现。

我也尝试过使用 Index.cshtml.cs 中设置的 [ViewData],但仍然无法弄清楚如何在页面加载时或导航到“功能”页面时更改颜色。

我也尝试过直接在我的_Layout页面添加@代码,比如@if(this.Page = "Index")@if(System.IO.Directory.GetCurrentDirectory = "Index"),但没有成功。

Desired Result: When I click the "Features" link and navigate to the Features.cshtml page, I want the "Features" list item to change color to color: rgba(255, 140, 0, 0.781) and the Home item to change to color: green.

如果您想为活动项目动态设置 color,您可以将活动页面名称存储在 localStorage 中,然后您可以检索存储的数据并动态设置自定义 class 在 _Layout 页面中为特定元素应用预期的颜色,如下所示。

Html

<div class="collapse navbar-collapse" id="navbarSupportedContent">
    <ul class="navbar-nav mr-auto">
        <li class="nav-item active" onclick="changeactive('Home')">
            <a class="nav-link" asp-page="Index" )>@_loc["Home"]</a>
        </li>
        <li class="nav-item active" onclick="changeactive('Features')">
            <a class="nav-link" asp-page="Features" localize-content>@_loc["Features"]</a>
        </li>
        <partial name="_LoginPartial" />
    </ul>
</div>

JS代码

<script>
    function changeactive(pname) {

        //console.log(pname);

        localStorage.setItem("activepage", pname);
    }

    $(function () {
        var pname = localStorage.getItem("activepage");

        if (pname == "Home" || pname == "" || pname == null) {
            $("ul.navbar-nav li.nav-item:nth-child(1) a").addClass("active-item");
            $("ul.navbar-nav li.nav-item:nth-child(2) a").addClass("normal-item");
        } else {
            $("ul.navbar-nav li.nav-item:nth-child(1) a").addClass("normal-item");
            $("ul.navbar-nav li.nav-item:nth-child(2) a").addClass("active-item");
        }
    })
</script>

CSS class

<style>
    .active-item {
        color: green !important;
    }

    .normal-item {
        color: rgba(255, 140, 0, 0.781) !important;
    }
</style>

测试结果

Change colour of the navbar element corresponding to the active page

我已经成功地为此使用了自定义标签助手,使用了一些受 here 启发的代码。

有关创建标签助手的 Microsoft 文档可用 here. Third party tutorial available here

标签助手会让我们指定对应于每个导航栏项目的操作,然后当页面在服务器上构建时我们将add the active class到相应的项目。

<ul class="navbar-nav flex-grow-1">
    <li navigation-active-for="/Index" class="nav-item">
        <a class="nav-link" asp-area="" asp-page="/Index">Home</a>
    </li>
    <li navigation-active-for="/Privacy" class="nav-item">
        <a class="nav-link" asp-area="" asp-page="/Privacy">Privacy</a>
    </li>
    <li navigation-active-for="/Movies/Index" class="nav-item">
        <a class="nav-link" asp-area="" asp-page="/Movies/Index">Movies</a>
    </li>
</ul>

在这种情况下,将使用 navigation-active-for 属性。

标签助手将如下所示 (在我的例子中,该项目称为 Emotify)

using System;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.AspNetCore.Routing;

namespace Emotify.TagHelpers
{
    [HtmlTargetElement("li", Attributes = _for)]
    public class ActiveItemTagHelper : TagHelper
    {
        private readonly IUrlHelper _urlHelper;
        private readonly IHttpContextAccessor _httpAccess;
        private readonly LinkGenerator _linkGenerator;
        private const string _for = "navigation-active-for";

        public ActiveItemTagHelper(
            IActionContextAccessor actionAccess,
            IUrlHelperFactory factory,
            IHttpContextAccessor httpAccess,
            LinkGenerator generator
        )
        {
            _urlHelper = factory.GetUrlHelper(actionAccess.ActionContext);
            _httpAccess = httpAccess;
            _linkGenerator = generator;
        }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            // grab attribute value
            var targetPage = output.Attributes[_for].Value.ToString();
            // remove from html so user doesn't see it
            output.Attributes.Remove(output.Attributes[_for]);
            
            // get the URI that corresponds to the attribute value
            var targetUri = _linkGenerator.GetUriByPage(_httpAccess.HttpContext, page: targetPage);
            // get the URI that corresponds to the current page's action
            var currentUri = _urlHelper.ActionLink();

            // if they match, then add the "active" CSS class
            if (targetUri == currentUri) {
                output.AddClass("active", HtmlEncoder.Default);
            }
        }
    }
}

依赖注入构造函数中使用的服务必须在Startup.cs::ConfigureServices中注册。 ref ref

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

重要:在中必须注册标签助手,就像在_ViewImports.cshtml.

中一样
@using Emotify
@addTagHelper *, Emotify

请注意,此 ISNT @addTagHelper *, Emotify.TagHelpers 因为这显然是错误的,所以不起作用。我不确定命名空间嵌套在 C# 中是如何工作的。

补充说明

  • 我对 C# 和 Razor 还很陌生,所以这可能不符合最佳实践