You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 01:59:55