MudBlazor MudTable输入计算后表格值不更新问题
问题根因
- 数据源绑定写法错误:Razor中直接写
Items="@Elements.Take(9)",会导致每次组件渲染时Take(9)生成全新的IEnumerable序列对象,MudTable内部变更检测无法识别到序列内原有实例的属性修改,只会判定数据源引用变更,不会逐行更新单元格内容。 - 数据模型无变更通知:
Element是普通POCO类,没有实现INotifyPropertyChanged接口,MudTable默认不会跟踪普通类的单个属性值变化,即使手动调用StateHasChanged(),只要表格判定行实例引用未发生替换,就不会触发单元格重渲染。 - 冗余查询可能导致引用不一致:
doTheMath方法中没有直接修改当前行绑定的@context实例,而是重新从Elements集合查询匹配项,配合每次Take生成的新序列,很容易出现修改的对象和界面实际绑定的行对象不是同一个引用的问题,自然无法触发界面更新。 - 原生input仅做单向值绑定,没有和数据源建立双向联动,输入过程中DOM值和渲染逻辑容易出现不同步。
修复步骤
修正数据源绑定逻辑,不要在Razor组件参数上直接调用Linq方法,提前将展示数据存为固定引用的集合:
// 定义固定引用的List存储数据,不要每次渲染生成新序列 private List<Element> Elements = new(); protected override void OnInitialized() { Elements = new List<Element>() { new Element() { CashValue="0", CashAmount = "x 1000", Total = "0"}, new Element() { CashValue="0", CashAmount = "x 500", Total = "0"}, new Element() { CashValue="0", CashAmount = "x 200", Total = "0"}, new Element() { CashValue="0", CashAmount = "x 100", Total = "0"}, new Element() { CashValue="0", CashAmount = "x 50", Total = "0"}, new Element() { CashValue="0", CashAmount = "x 20", Total = "0"}, new Element() { CashValue="0", CashAmount = "x 10", Total = "0"}, new Element() { CashValue="0", CashAmount = "x 5", Total = "0"}, new Element() { CashValue="0", CashAmount = "x 1", Total = "0"}, }; }对应MudTable的Items参数直接绑定固定集合:
<MudTable Items="@Elements" Hover="true" Breakpoint="Breakpoint.Sm" @ref="mudTable" RowClassFunc="@SelectedRowClassFunc" OnRowClick="RowClickEvent" T="Element">简化计算逻辑,直接操作当前行的
@context实例,不要重复从集合查询对象,修改完成后调用MudTable的Reload方法强制刷新表格渲染:private void doTheMath(Element element, ChangeEventArgs c) { try { // 直接修改传入的当前行实例,不需要重新查询 if(!int.TryParse(c.Value?.ToString(), out int inputVal)) { inputVal = 0; } var cashAmount = int.Parse(element.CashAmount.Replace("x", "").Trim()); element.CashValue = inputVal.ToString(); element.Total = (inputVal * cashAmount).ToString("###,###.00"); // 调用MudTable内置的Reload方法强制刷新行数据,替代无效的StateHasChanged mudTable.Reload(); } catch (Exception e) { Console.WriteLine(e.Message); } }(可选优化)替换原生input为MudBlazor自带的数值输入组件,避免原生输入的绑定问题,同时自带非法输入校验:
<RowTemplate> <MudTd DataLabel="Cash Value"> <MudNumericField Value="@int.Parse(context.CashValue)" ValueChanged="@(v => doTheMath(context, new ChangeEventArgs{Value = v}))" Class="table-input" HideSpinButtons="true" /> </MudTd> <MudTd DataLabel="Cash Amount" Style="text-align:center; width: 100px;">@context.CashAmount</MudTd> <MudTd DataLabel="Total"> <MudTextField Value="@context.Total" Disabled="true" Class="table-input" /> </MudTd> </RowTemplate>
如果需要更流畅的实时更新体验,可以给
Element类实现INotifyPropertyChanged接口,属性修改时主动触发变更通知,就不需要每次调用Reload方法刷新整个表格。
内容的提问来源于stack exchange,提问作者Ibanez1408
相关产品推荐
相关产品推荐

