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

MudTable多层级联动多选实现:祖孙表同步选中需求

MudBlazor祖孙层级表格多选联动实现方案

需求实现目标

  • 选中祖父行(JunkFiles)时,自动选中其下所有父行(FileNames)
  • 点击祖父行可展开父表,点击父行可展开子表
  • 祖父行选中状态同步到对应父行的复选框

修改后的完整代码

前端Razor代码

<MudTable @ref="_mudtable" T="JunkFiles" Items="@junkFiles" MultiSelection="true" Hover="true"
          @bind-SelectedItems="_selectedJunkFiles"
          OnSelectedItemsChanged="HandleJunkFilesSelectionChanged">
    <HeaderContent>
        <MudTh>Name</MudTh>
        <MudTh>Size</MudTh>
        <MudTh>Expand</MudTh>
    </HeaderContent>
    <RowTemplate>
        <MudTd DataLabel="Name">@context.Name</MudTd>
        <MudTd DataLabel="Size">@context.Size</MudTd>
        @if (@context.FileNames.Count > 0)
        {
            <MudTd>
                <MudLink @onclick="() => ToggleExpansion(context)">@(context.IsExpanded ? "v" : ">")</MudLink>
            </MudTd>
        }
    </RowTemplate>
    <ChildRowContent>
        @if (context.IsExpanded)
        {
            <MudTr>
                <td colspan="4">
                    <MudCard Elevation="0">
                        <MudCardContent Class="pa-0">
                            <MudTable Items="@context.FileNames" MultiSelection="true" Context="FileNameContext" Hover="true" Breakpoint="Breakpoint.Sm" Elevation="0"
                                      @bind-SelectedItems="_selectedFileNamesMap.GetValueOrDefault(context, new HashSet<FileNames>())">
                                <RowTemplate>
                                    <MudTd DataLabel="File Name">@FileNameContext.FileName</MudTd>
                                    <MudTd>
                                        @if (@FileNameContext.SubFileNames.Count > 0)
                                        {
                                            <MudLink @onclick="() => ToggleSubExpansion(FileNameContext)">@(FileNameContext.IsExpanded ? "v" : ">")</MudLink>
                                        }
                                    </MudTd>
                                </RowTemplate>
                                <ChildRowContent>
                                    @if (FileNameContext.IsExpanded)
                                    {
                                        <MudTr>
                                            <td colspan="4">
                                                <MudCard Elevation="0">
                                                    <MudTable Height="150px" Items="@FileNameContext.SubFileNames" Context="SubFileNameContext" Hover="true" Breakpoint="Breakpoint.Sm" Elevation="0">
                                                        <RowTemplate>
                                                            <MudTd DataLabel="SubFileName ">@SubFileNameContext.SubFileName</MudTd>
                                                        </RowTemplate>
                                                    </MudTable>
                                                </MudCard>
                                            </td>
                                        </MudTr>
                                    }
                                </ChildRowContent>
                            </MudTable>
                        </MudCardContent>
                    </MudCard>
                </td>
            </MudTr>
        }
    </ChildRowContent>
</MudTable>

后端C#代码

public class JunkFiles {
    public string Name { get; set; } = string.Empty;
    public string Size { get; set; } = string.Empty;
    public List<FileNames> FileNames { get; set; } = new();
    public bool IsExpanded { get; set; } = false;
    public JunkFiles(string name, string size , List<FileNames> filename)
    {
        Name = name;
        Size = size;
        FileNames = filename;
    }
}

public class FileNames
{
    public string FileName { get; set; } = string.Empty;
    public List<SubFileNames> SubFileNames { get; set; } = new();
    public bool IsExpanded { get; set; } = false;
    public FileNames (String fileName , List<SubFileNames> subFileName ) 
    {
        FileName = fileName;
        SubFileNames = subFileName;
    }
}

public class SubFileNames
{
    public string SubFileName { get; set; } = string.Empty;
    public SubFileNames (string subFileName)
    {
        SubFileName = subFileName;
    }
}

private List<JunkFiles> junkFiles = new();
private HashSet<JunkFiles> _selectedJunkFiles = new();
private Dictionary<JunkFiles, HashSet<FileNames>> _selectedFileNamesMap = new();
private MudTable<JunkFiles> _mudtable;
private bool _selectOnRowClick = true;

protected override void OnInitialized()
{
    junkFiles = new List<JunkFiles>
    {
        new JunkFiles("Temporary files","1.07GB",
         new List<FileNames>
         {
             new FileNames(@"c:\windows\temp\*",
             new List<SubFileNames>
             {
                 new SubFileNames(@"c:\windows\temp\file.log"),
                 new SubFileNames(@"c:\windows\temp\file.xml"),
                 new SubFileNames(@"c:\windows\temp\file.tmp")

             }),
             new FileNames(@"C:\Users\user\AppData\Local\Temp\*",
             new List<SubFileNames>
             {
                new SubFileNames(@"c:\windows\temp\file1.log"),
                 new SubFileNames(@"c:\windows\temp\file2.xml"),
                 new SubFileNames(@"c:\windows\temp\file3.tmp")
             })

         }),
        new JunkFiles("Empty Recycle Bin","6.39MB",
        new List<FileNames>
         {
             new FileNames(@"c:\tfs\temp\file1.cs",new (){}),                       
             new FileNames(@"c:\tfs\temp\file2.cs",new (){}),                       
             new FileNames(@"c:\tfs\temp\file3.cs",new (){}),
            
         }),
        new JunkFiles("Memory Dump Files","63.24MB",
        new List<FileNames>
         {
             new FileNames(@"c:\users\user1\AppData\Local\CrashDumps\*.dmp", new List<SubFileNames>
             {
                 new SubFileNames(@"c:\users\user1\AppData\Local\CrashDumps\file1.dmp"),
                 new SubFileNames(@"c:\users\user1\AppData\Local\CrashDumps\file2.dmp"),
                 new SubFileNames(@"c:\users\user1\AppData\Local\CrashDumps\file3.dmp"),

             })
         }),
        new JunkFiles("Test Files","63.24MB", new List<FileNames>())
         
    };
}

private void ToggleExpansion(JunkFiles junkFile)
{
    junkFile.IsExpanded = !junkFile.IsExpanded;
}

private void ToggleSubExpansion(FileNames fileName)
{
    fileName.IsExpanded = !fileName.IsExpanded;
}

private void HandleJunkFilesSelectionChanged(HashSet<JunkFiles> selectedItems)
{
    foreach (var junkFile in junkFiles)
    {
        if (!_selectedFileNamesMap.ContainsKey(junkFile))
        {
            _selectedFileNamesMap[junkFile] = new HashSet<FileNames>();
        }

        var fileSelectedSet = _selectedFileNamesMap[junkFile];
        fileSelectedSet.Clear();

        if (selectedItems.Contains(junkFile))
        {
            fileSelectedSet.UnionWith(junkFile.FileNames);
        }
    }
    StateHasChanged();
}

核心实现说明

  1. 选中状态关联跟踪:用_selectedFileNamesMap字典维护每个祖父行对应的父行选中集合,确保祖孙选中状态一一对应
  2. 选中事件联动:通过主表的OnSelectedItemsChanged事件监听选中变化,自动将选中祖父行下的所有父行加入子表选中集合,取消选中时清空对应父行选中状态
  3. 渲染同步:在联动逻辑结束后调用StateHasChanged()强制子表刷新,确保复选框状态实时同步

内容的提问来源于stack exchange,提问作者Dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 20:53:09