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(); }
核心实现说明
- 选中状态关联跟踪:用
_selectedFileNamesMap字典维护每个祖父行对应的父行选中集合,确保祖孙选中状态一一对应 - 选中事件联动:通过主表的
OnSelectedItemsChanged事件监听选中变化,自动将选中祖父行下的所有父行加入子表选中集合,取消选中时清空对应父行选中状态 - 渲染同步:在联动逻辑结束后调用
StateHasChanged()强制子表刷新,确保复选框状态实时同步
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

