Blazor(.NET6)中NavMenu无法实时显示Counter计数的问题求助
方法一:使用状态容器服务(推荐,适合跨组件共享状态)
这种方式通过依赖注入共享状态,支持任意组件间同步数据,且能在属性变化时自动通知组件更新。
- 创建状态容器类
新建MenuState.cs,实现INotifyPropertyChanged接口,确保属性变更时触发通知:
using System.ComponentModel; using System.Runtime.CompilerServices; public class MenuState : INotifyPropertyChanged { private int _counterValue; public int CounterValue { get => _counterValue; set { if (_counterValue != value) { _counterValue = value; OnPropertyChanged(); } } } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
- 注册状态服务
在Program.cs中添加Scoped生命周期的服务注册:
builder.Services.AddScoped<MenuState>();
- 修改Counter.razor注入并更新状态
注入状态容器,点击按钮时同步更新容器内的计数值:
@page "/counter" @inject MenuState MenuState <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; MenuState.CounterValue = currentCount; } }
- 修改NavMenu.razor订阅状态变化并显示
注入状态容器,订阅属性变更事件以触发组件重新渲染:
@inject MenuState MenuState @implements IDisposable <div class="top-row ps-3 navbar navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="">BlazorApp</a> <button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu"> <span class="navbar-toggler-icon"></span> </button> </div> </div> <div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> <nav class="flex-column"> <div class="nav-item px-3"> <NavLink class="nav-link" href="" Match="NavLinkMatch.All"> <span class="oi oi-home" aria-hidden="true"></span> Home </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="counter"> <span class="oi oi-plus" aria-hidden="true"></span> Counter <span class="badge bg-primary ms-2">@MenuState.CounterValue</span> </NavLink> </div> </nav> </div> @code { private bool collapseNavMenu = true; private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; private void ToggleNavMenu() { collapseNavMenu = !collapseNavMenu; } protected override void OnInitialized() { MenuState.PropertyChanged += OnStateChanged; } private void OnStateChanged(object? sender, PropertyChangedEventArgs e) { StateHasChanged(); } public void Dispose() { MenuState.PropertyChanged -= OnStateChanged; } }
方法二:使用级联参数(适合层级较浅的组件结构)
若组件结构为MainLayout包含NavMenu和页面内容(Counter),可通过级联参数直接传递状态:
- 在MainLayout.razor中定义并传递级联值
@inherits LayoutComponentBase <div class="page"> <div class="sidebar"> <CascadingValue Value="this" Name="LayoutState"> <NavMenu /> </CascadingValue> </div> <main> <div class="top-row px-4"> <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> </div> <article class="content px-4"> <CascadingValue Value="this" Name="LayoutState"> @Body </CascadingValue> </article> </main> </div> @code { private int _counterValue; public int CounterValue { get => _counterValue; set { _counterValue = value; StateHasChanged(); } } }
- 修改Counter.razor接收级联参数并更新
@page "/counter" [CascadingParameter(Name = "LayoutState")] public MainLayout? LayoutState { get; set; } <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; LayoutState?.CounterValue = currentCount; } }
- 修改NavMenu.razor接收级联参数并显示
[CascadingParameter(Name = "LayoutState")] public MainLayout? LayoutState { get; set; } <div class="top-row ps-3 navbar navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="">BlazorApp</a> <button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu"> <span class="navbar-toggler-icon"></span> </button> </div> </div> <div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> <nav class="flex-column"> <div class="nav-item px-3"> <NavLink class="nav-link" href="" Match="NavLinkMatch.All"> <span class="oi oi-home" aria-hidden="true"></span> Home </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="counter"> <span class="oi oi-plus" aria-hidden="true"></span> Counter <span class="badge bg-primary ms-2">@LayoutState?.CounterValue</span> </NavLink> </div> </nav> </div> @code { private bool collapseNavMenu = true; private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; private void ToggleNavMenu() { collapseNavMenu = !collapseNavMenu; } }
原方案失效的可能原因
- 使用对象继承但未实现
INotifyPropertyChanged:属性变更时组件无法感知,不会触发重新渲染。 - EventCallback使用不当:NavMenu属于MainLayout的子组件,Counter是独立页面组件,两者无直接父子关系,EventCallback无法跨层级传递。
内容的提问来源于stack exchange,提问作者Zibix
相关产品推荐
相关产品推荐

