Blazor WASM如何将FilterMenu按钮点击事件绑定到@Body内Index页面方法
解决方案
Blazor WebAssembly 中实现Layout组件与@Body内页面的跨组件通信,有两种常用且稳定的实现方式:
方案1:扩展现有级联参数(适合小型项目)
无需新增服务,基于你现有代码结构修改即可:
步骤1:修改 FilterMenu.razor
修正EventCallback参数类型,触发回调传递筛选对象:
<div class="filterMenu"> <ul class="nav flex-column"> <li class="nav-item px-3"> <button class="btn-success" @onclick="ApplyFilters">Do Work</button> </li> </ul> </div> @code { // 泛型改为你的筛选对象类型 [Parameter] public EventCallback<FilterObject> OnClick_ApplyFilters { get; set; } private async Task ApplyFilters() { var filters = new FilterObject() { SomeFilter = "SomeValue"}; // 向上触发回调到MainLayout await OnClick_ApplyFilters.InvokeAsync(filters); } }
步骤2:修改 MainLayout.razor
新增通知事件,更新级联值后触发订阅通知:
<div class="container-fluid"> <div class="row"> <div class="col-md-2"> <FilterMenu OnClick_ApplyFilters="ApplyFilters"></FilterMenu> </div> <!-- 级联当前Layout实例供内部页面获取事件和筛选值 --> <CascadingValue Value="this"> <div class="content px-4"> @Body </div> </CascadingValue> </div> </div> @code { // 公开筛选值供页面读取 public Filters filters { get; set; } = new(); // 筛选更新通知事件 public event Action OnFilterUpdated; private async Task ApplyFilters(FilterObject filterObj) { // 更新筛选值 filters = new Filters { SomeFilter = filterObj.SomeFilter }; // 触发所有订阅该事件的页面方法 OnFilterUpdated?.Invoke(); } }
步骤3:修改 Index.razor
订阅Layout的筛选更新事件,页面销毁时取消订阅避免内存泄漏:
@page "/" @implements IDisposable <div class="mainContent"> <!-- 原有页面结构保留 --> </div> @code { // 接收级联的Layout实例 [CascadingParameter] public MainLayout Layout { get; set; } protected override void OnInitialized() { // 订阅筛选更新事件 Layout.OnFilterUpdated += GetGridData; } public async void GetGridData() { await LoadSampleData(Layout.filters); await LoadSampleData2(Layout.filters); // 手动触发UI刷新 StateHasChanged(); } // 页面销毁时取消订阅 public void Dispose() { Layout.OnFilterUpdated -= GetGridData; } // 原有LoadSampleData、LoadSampleData2方法保留 }
方案2:全局状态服务(适合中大型项目)
解耦性更强,支持多页面同时响应筛选变更:
步骤1:新建筛选状态服务
新增FilterService.cs类:
public class FilterService { // 当前全局筛选值 public Filters CurrentFilters { get; private set; } = new(); // 筛选更新通知事件 public event Action OnFilterChanged; /// <summary> /// 更新全局筛选值并触发通知 /// </summary> public void UpdateFilters(Filters newFilters) { CurrentFilters = newFilters; OnFilterChanged?.Invoke(); } }
步骤2:注册服务到依赖注入容器
修改Program.cs:
// 其他注册逻辑保留 builder.Services.AddScoped<FilterService>();
步骤3:修改 FilterMenu.razor
直接注入服务触发筛选更新:
@inject FilterService FilterService <div class="filterMenu"> <!-- 原有结构保留 --> </div> @code { private async Task ApplyFilters() { var filters = new Filters() { SomeFilter = "SomeValue"}; FilterService.UpdateFilters(filters); } }
该方案下MainLayout无需再绑定FilterMenu的回调参数
步骤4:修改 Index.razor
注入服务订阅事件:
@page "/" @implements IDisposable @inject FilterService FilterService <div class="mainContent"> <!-- 原有页面结构保留 --> </div> @code { protected override void OnInitialized() { FilterService.OnFilterChanged += GetGridData; } public async void GetGridData() { await LoadSampleData(FilterService.CurrentFilters); await LoadSampleData2(FilterService.CurrentFilters); StateHasChanged(); } public void Dispose() { FilterService.OnFilterChanged -= GetGridData; } // 原有LoadSampleData、LoadSampleData2方法保留 }
注意事项
两种方案都需要在页面实现IDisposable接口,销毁时取消事件订阅,否则会出现内存泄漏、方法重复触发的问题。
内容的提问来源于stack exchange,提问作者TonyStark
相关产品推荐
相关产品推荐

