MudBlazor带多选与搜索的表格搜索时选中项丢失求助
解决MudBlazor表格搜索时选中项SessionStorage被清空的问题
问题根源
搜索触发表格重新渲染时,MudBlazor会重置SelectedItems集合,多次调用SelectedItemsChanged并传入空列表,直接覆盖了SessionStorage中保存的选中工单。同时原代码使用async void可能导致异步操作不可控,加剧问题。
解决方案
1. 替换async void为async Task(基础修复)
Blazor中async void会导致异常无法捕获,所有异步方法必须返回Task:
// 修改UpdateSearch async public Task UpdateSearch(string searchStringField) { searchString = searchStringField; await sessionStorage.SetItemAsync("SessionSearch", searchString); StateHasChanged(); } // 修改UpdateSelection async public Task UpdateSelection(HashSet<Ticket> selectedRows) { selectedTickets = selectedRows; await sessionStorage.SetItemAsync("SelectedTickets", selectedTickets); StateHasChanged(); }
同时更新MudTextField的绑定,无需手动创建EventCallback:
<MudTextField @ref="mudSearchRef" Value="@searchString" ValueChanged="@UpdateSearch" Placeholder="Search" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0" Clearable></MudTextField>
2. 改用双向绑定SelectedItems(推荐方案)
放弃SelectedItemsChanged事件,改用双向绑定直接控制选中集合,避免组件自动触发的无效更新:
<!-- 修改MudTable的绑定 --> <MudTable @ref="mudTableRef" Items="@TicketList" @bind-SelectedItems="selectedTickets" RowsPerPage="@rowCount" RowsPerPageChanged="@UpdateRowCount" Filter="new Func<Ticket,bool>(FilterFunc1)" T="Ticket" OnRowClick="@RowClicked" SelectOnRowClick="false" Hover Bordered Striped MultiSelection>
然后将selectedTickets改为带setter的属性,在setter中处理SessionStorage保存:
private HashSet<Ticket> _selectedTickets = new HashSet<Ticket>(); private HashSet<Ticket> selectedTickets { get => _selectedTickets; set { if (_selectedTickets != value) { _selectedTickets = value; // Blazor属性setter不能异步,用InvokeAsync包装 _ = InvokeAsync(async () => { await sessionStorage.SetItemAsync("SelectedTickets", _selectedTickets); }); } } }
这样只有当选中项真正发生变化时才会保存到SessionStorage,组件重置空集合的操作不会触发保存。
3. 搜索后恢复可见的选中项(补充优化)
如果需要保留搜索前的选中项(只要它们在搜索结果中),可以在搜索时临时保存选中状态,渲染完成后恢复:
private bool _isSearching; async public Task UpdateSearch(string searchStringField) { _isSearching = true; searchString = searchStringField; await sessionStorage.SetItemAsync("SessionSearch", searchString); StateHasChanged(); } protected override async Task OnAfterRenderAsync(bool firstRender) { if (!firstRender && _isSearching) { // 从SessionStorage获取之前的选中项 var savedSelected = await sessionStorage.GetItemAsync<HashSet<Ticket>>("SelectedTickets") ?? new HashSet<Ticket>(); // 过滤出当前搜索结果中存在的项 var visibleSelected = new HashSet<Ticket>(TicketList.Where(t => savedSelected.Any(s => s.TicketId == t.TicketId))); // 更新表格选中状态 selectedTickets = visibleSelected; mudTableRef.SelectedItems = visibleSelected; _isSearching = false; StateHasChanged(); } else if (firstRender) { // 原有初始化逻辑保持不变... } }
4. 避免空集合覆盖(应急方案)
如果暂时不想改绑定方式,可以在UpdateSelection中添加判断,拒绝空集合覆盖已有选中项:
async public Task UpdateSelection(HashSet<Ticket> selectedRows) { // 只有当传入的集合非空,或者本地原本就没有选中项时才更新 if (selectedRows.Count > 0 || selectedTickets.Count == 0) { selectedTickets = selectedRows; await sessionStorage.SetItemAsync("SelectedTickets", selectedTickets); } else { // 把本地选中项同步回表格,避免UI显示错误 mudTableRef.SelectedItems = new HashSet<Ticket>(selectedTickets); } StateHasChanged(); }
内容的提问来源于stack exchange,提问作者luca.04
相关产品推荐
相关产品推荐

