Blazor中基于分支列同步过滤并展示两个关联数据集的方案问询
复用分支下拉框同时过滤多数据集的Blazor实现方案
方案1:封装独立的分支选择组件(推荐单页面复用)
把分支下拉框抽成独立组件,通过双向绑定传递选中值,父组件统一维护选中状态并过滤两个数据集。这样下拉框只实现一次,可在当前页面或其他页面复用。
分支选择组件(BranchSelector.razor)
<div class="mb-3"> <label class="form-label">选择分支</label> <select @bind="SelectedBranchId" class="form-select"> <option value="">全部分支</option> @foreach (var branch in Branches) { <option value="@branch.Id">@branch.Name</option> } </select> </div> @code { [Parameter] public int? SelectedBranchId { get; set; } [Parameter] public EventCallback<int?> SelectedBranchIdChanged { get; set; } [Parameter, Required] public IEnumerable<Branches> Branches { get; set; } = Enumerable.Empty<Branches>(); }
父页面使用示例
<!-- 复用分支选择组件 --> <BranchSelector @bind-SelectedBranchId="_selectedBranchId" Branches="_branches" /> <!-- 水果表数据展示 --> <h4>水果库存表</h4> <table class="table table-striped"> <thead> <tr> <th>水果名称</th> <th>所属分支</th> <th>库存数量</th> </tr> </thead> <tbody> @foreach (var fruit in _filteredFruits) { <tr> <td>@fruit.FruitName</td> <td>@fruit.Branch.Name</td> <td>@fruit.StockCount</td> </tr> } </tbody> </table> <!-- 新年价格数据展示 --> <h4>新年价格表</h4> <table class="table table-striped"> <thead> <tr> <th>商品名称</th> <th>所属分支</th> <th>新年售价</th> </tr> </thead> <tbody> @foreach (var price in _filteredPrices) { <tr> <td>@price.ProductName</td> <td>@price.Branch.Name</td> <td>@price.NewYearPrice.ToString("C")</td> </tr> } </tbody> </table> @code { private int? _selectedBranchId; private IEnumerable<Branches> _branches = Enumerable.Empty<Branches>(); private IEnumerable<FruitTable> _allFruits = Enumerable.Empty<FruitTable>(); private IEnumerable<NewYearPrices> _allPrices = Enumerable.Empty<NewYearPrices>(); // 实时过滤的数据集 private IEnumerable<FruitTable> _filteredFruits => _selectedBranchId.HasValue ? _allFruits.Where(f => f.BranchId == _selectedBranchId.Value) : _allFruits; private IEnumerable<NewYearPrices> _filteredPrices => _selectedBranchId.HasValue ? _allPrices.Where(p => p.BranchId == _selectedBranchId.Value) : _allPrices; [Inject] private IBranchService BranchService { get; set; } = null!; [Inject] private IFruitService FruitService { get; set; } = null!; [Inject] private INewYearPriceService PriceService { get; set; } = null!; protected override async Task OnInitializedAsync() { // 初始化加载所有基础数据 _branches = await BranchService.GetAllBranchesAsync(); _allFruits = await FruitService.GetAllFruitsAsync(); _allPrices = await PriceService.GetAllNewYearPricesAsync(); } }
方案2:页面内直接维护选中状态(简单场景)
如果不需要跨组件复用下拉框,直接在当前页面维护分支选中变量,两个数据集的过滤逻辑都依赖这个变量,无需额外封装组件。
<div class="mb-3"> <label class="form-label">选择分支</label> <select @bind="_selectedBranchId" class="form-select"> <option value="">全部分支</option> @foreach (var branch in _branches) { <option value="@branch.Id">@branch.Name</option> } </select> </div> <!-- 水果表和价格表的展示代码同方案1 --> @code { private int? _selectedBranchId; private IEnumerable<Branches> _branches = Enumerable.Empty<Branches>(); private IEnumerable<FruitTable> _allFruits = Enumerable.Empty<FruitTable>(); private IEnumerable<NewYearPrices> _allPrices = Enumerable.Empty<NewYearPrices>(); private IEnumerable<FruitTable> _filteredFruits => _selectedBranchId.HasValue ? _allFruits.Where(f => f.BranchId == _selectedBranchId.Value) : _allFruits; private IEnumerable<NewYearPrices> _filteredPrices => _selectedBranchId.HasValue ? _allPrices.Where(p => p.BranchId == _selectedBranchId.Value) : _allPrices; // 数据加载逻辑同方案1 }
方案3:全局状态管理(跨页面复用选中状态)
如果你的应用需要在多个页面共享分支选中状态,可创建一个注入式的状态服务,统一维护分支选择,所有需要过滤的组件监听状态变化。
分支状态服务(BranchStateService.cs)
public class BranchStateService { private int? _selectedBranchId; public int? SelectedBranchId { get => _selectedBranchId; set { if (_selectedBranchId != value) { _selectedBranchId = value; BranchSelected?.Invoke(this, EventArgs.Empty); } } } public event EventHandler? BranchSelected; public void UpdateSelectedBranch(int? branchId) { SelectedBranchId = branchId; } }
注册服务(Program.cs)
builder.Services.AddScoped<BranchStateService>();
分支选择组件绑定状态服务
<div class="mb-3"> <label class="form-label">选择分支</label> <select @bind="_branchState.SelectedBranchId" class="form-select"> <option value="">全部分支</option> @foreach (var branch in _branches) { <option value="@branch.Id">@branch.Name</option> } </select> </div> @code { [Inject] private BranchStateService _branchState { get; set; } = null!; [Inject] private IBranchService BranchService { get; set; } = null!; private IEnumerable<Branches> _branches = Enumerable.Empty<Branches>(); protected override async Task OnInitializedAsync() { _branches = await BranchService.GetAllBranchesAsync(); // 监听状态变化,触发组件刷新 _branchState.BranchSelected += (sender, e) => StateHasChanged(); } // 组件销毁时取消监听,避免内存泄漏 public void Dispose() { _branchState.BranchSelected -= (sender, e) => StateHasChanged(); } }
数据展示组件监听状态变化
<h4>水果库存表</h4> <table class="table table-striped"> <!-- 表格内容同方案1 --> </table> @code { [Inject] private BranchStateService _branchState { get; set; } = null!; [Inject] private IFruitService FruitService { get; set; } = null!; private IEnumerable<FruitTable> _allFruits = Enumerable.Empty<FruitTable>(); private IEnumerable<FruitTable> _filteredFruits => _branchState.SelectedBranchId.HasValue ? _allFruits.Where(f => f.BranchId == _branchState.SelectedBranchId.Value) : _allFruits; protected override async Task OnInitializedAsync() { _allFruits = await FruitService.GetAllFruitsAsync(); _branchState.BranchSelected += (sender, e) => StateHasChanged(); } public void Dispose() { _branchState.BranchSelected -= (sender, e) => StateHasChanged(); } }
内容的提问来源于stack exchange,提问作者Kibofigs
相关产品推荐
相关产品推荐

