MudBlazor DataGrid服务端分页切换后选中行无法高亮(RowClassFunc失效)
问题描述
使用带服务端分页和过滤功能的MudBlazor DataGrid时,选中行后数据保存正常,但切换页面时无法让之前选中的行重新显示选中状态。尝试通过RowClassFunc为选中行添加"selected"类,但该方案未生效。
相关代码如下:
<MudDataGrid T="ObservationListModel" MultiSelection="@true" @ref="_dataGrid" @bind-SelectedItems="selectedItems" ServerData="LoadGridData" SortMode="SortMode.Multiple" Filterable="true" RowClassFunc="SelectedRowClassFunc" Hideable="false" Elevation="5" Dense="@true"> <ToolBarContent> <MudSpacer /> <MudTextField T="string" Value="@_requestDto.Search" Placeholder="Search" Adornment="Adornment.Start" Immediate="false" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0" ValueChanged="OnSearchChange"></MudTextField> </ToolBarContent> <Columns> <SelectColumn T="ObservationListModel" /> <TemplateColumn Sortable="@false" Filterable="@false" Title="Detail" > <CellTemplate> <MudStack Row> <MudButton Size="@Size.Small" Variant="@Variant.Filled" Href="@($"obsdetail/{context.Item.ReferenceID}/{context.Item.OriginalDataID}")" Color="@Color.Primary">View</MudButton> </MudStack> </CellTemplate> </TemplateColumn> <PropertyColumn Property="x => x.ScientificName" Title="Scientific Name" Sortable="true" /> <PropertyColumn Property="x => x.ObservationDate" Title="Observation Date" Sortable="true" Filterable="false" /> <PropertyColumn Property="x => x.Class" Title="Class" Sortable="true"/> <PropertyColumn Property="x => x.CountyName" Title="County" Sortable="true" /> <PropertyColumn Property="x => x.Observer" Title="Observer" Sortable="true" /> <PropertyColumn Property="x => x.ReviewStatus" Title="Review Status" Sortable="true" /> </Columns> <PagerContent> <MudText>@($"{selectedItems.Count} items selected")</MudText> <MudDataGridPager T="ObservationListModel"/> </PagerContent> </MudDataGrid>
@code { private MudDataGrid<ObservationListModel>? _dataGrid; private ObsRequestModel _requestDto = new(); private HashSet<ObservationListModel> selectedItems { get; set; } = new HashSet<ObservationListModel>(); private async Task Search() { if (_dataGrid is not null) { await _dataGrid!.ReloadServerData(); } } private async Task OnSearchChange(string newValue) { _requestDto.Search = newValue; await Search(); } private async Task<GridData<ObservationListModel>> LoadGridData(GridState<ObservationListModel> state) { _requestDto.Filters.Clear(); _requestDto.Page = state.Page + 1; _requestDto.PageSize = state.PageSize; // Extract sorting information var sorting = state.SortDefinitions.FirstOrDefault(); // Assuming single column sorting if (sorting != null) { _requestDto.SortColumn = sorting.SortBy; _requestDto.SortDirection = sorting.Descending == false ? "asc" : "desc"; // Convert Enum to string or appropriate format } // Extract filtering information foreach (var filter in state.FilterDefinitions) { if (filter.Value != null) { var colString = filter.Title.ToString(); var valString = colString == "County" ? await ReferenceService.GetCountyFips(filter.Value.ToString()) : filter.Value.ToString(); _requestDto.Filters.Add(new FilterDefinition { Column = colString, Operator = filter.Operator.ToString(), Value = valString }); } else if (filter.Operator.ToLower() == "is empty" || filter.Operator.ToLower() == "is not empty") { _requestDto.Filters.Add(new FilterDefinition { Column = filter.Title.ToString(), Operator = filter.Operator.ToString(), Value = "0", // Assuming the value is a string, adjust as necessary }); } } ObListDTO Response = await ReferenceService.GetAllObs(_requestDto); GridData<ObservationListModel> data = new() { Items = Response.Items, TotalItems = Response.ItemTotalCount }; return data; } private async Task OnStartDateChanged(DateTime? newDate) { _requestDto.StartDate = newDate; await DateChange(); } private async Task OnEndDateChanged(DateTime? newDate) { _requestDto.EndDate = newDate; await DateChange(); } private async Task DateChange() { if (_dataGrid is not null) { await _dataGrid!.ReloadServerData(); } } public void Dispose() { } private string SelectedRowClassFunc(ObservationListModel element, int rowNumber) { return selectedItems.Contains(element) ? "selected" : string.Empty; } }
解决方案
问题核心:HashSet<ObservationListModel>默认用对象引用判断相等性,服务端分页返回的是新创建的ObservationListModel实例,即使数据内容和之前选中的行一致,引用不同导致selectedItems.Contains(element)返回false,选中样式不生效。
方案1:重写模型的相等性判断
在ObservationListModel类中重写Equals和GetHashCode方法,基于唯一标识(比如ReferenceID和OriginalDataID)判断对象相等:
public class ObservationListModel { // 你的现有属性 public int ReferenceID { get; set; } public int OriginalDataID { get; set; } // ...其他属性 public override bool Equals(object obj) { if (obj is not ObservationListModel other) return false; return ReferenceID == other.ReferenceID && OriginalDataID == other.OriginalDataID; } public override int GetHashCode() { return HashCode.Combine(ReferenceID, OriginalDataID); } }
修改后HashSet能正确识别内容相同的不同实例,RowClassFunc的判断会自动生效。
方案2:用唯一ID集合跟踪选中项
如果不想修改模型类,可改用存储选中项的唯一标识,而非整个对象:
步骤1:修改选中项存储
// 替换原有的HashSet<ObservationListModel> private HashSet<Tuple<int, int>> selectedItemIds { get; set; } = new(); // 保留用于DataGrid绑定的临时集合 private HashSet<ObservationListModel> selectedItems { get; set; } = new();
步骤2:同步选中项到ID集合
给MudDataGrid添加SelectedItemsChanged事件:
<MudDataGrid ... @bind-SelectedItems="selectedItems" SelectedItemsChanged="OnSelectedItemsChanged" ...>
实现事件处理逻辑:
private void OnSelectedItemsChanged(HashSet<ObservationListModel> items) { selectedItemIds.Clear(); foreach (var item in items) { selectedItemIds.Add(Tuple.Create(item.ReferenceID, item.OriginalDataID)); } }
步骤3:修改RowClassFunc判断逻辑
private string SelectedRowClassFunc(ObservationListModel element, int rowNumber) { return selectedItemIds.Contains(Tuple.Create(element.ReferenceID, element.OriginalDataID)) ? "selected" : string.Empty; }
步骤4:切换页面后恢复选中状态
在LoadGridData方法返回数据后,手动匹配当前页的选中项:
private async Task<GridData<ObservationListModel>> LoadGridData(GridState<ObservationListModel> state) { // ...原有逻辑 ObListDTO Response = await ReferenceService.GetAllObs(_requestDto); GridData<ObservationListModel> data = new() { Items = Response.Items, TotalItems = Response.ItemTotalCount }; // 恢复当前页的选中状态 selectedItems.Clear(); foreach (var item in data.Items) { if (selectedItemIds.Contains(Tuple.Create(item.ReferenceID, item.OriginalDataID))) { selectedItems.Add(item); } } return data; }
内容的提问来源于stack exchange,提问作者Travis.fahey
相关产品推荐
相关产品推荐

