Blazor中为何需重复实例化List才能填充Syncfusion DataGrid?
Blazor Syncfusion DataGrid 数据更新不显示问题解析
问题场景与代码示例
以下是用于填充Syncfusion Blazor DataGrid的C#代码,网格通过绑定_monitoringDatas变量加载数据:
namespace ligprod.Client.Pages { public partial class Monitoring_ligne { ... private Monitoring Monit; private List<Monitoring> _monitoringDatas; protected override async Task OnInitializedAsync() { ... _monitoringDatas = new List<Monitoring>(); } Task ReceiveLidarValue(string arg) { _monitoringDatas = new List<Monitoring>(); Monitoring Monit = new Monitoring() { IdMonotoring = 1, RealProduction = false, Machine = "remplisseuse", DatePassage = DateTime.Now, }; _monitoringDatas.Add(Monit); } } }
核心疑问
已在OnInitializedAsync()中完成_monitoringDatas的实例化,为何必须在SignalR消息触发的ReceiveLidarValue方法中重新实例化List,网格才会显示数据?
- 移除
_monitoringDatas = new List<Monitoring>();后,网格无数据显示且无报错; - 保留该行代码时,网格每次仅显示最新一条数据(原有内容被覆盖)。
整体流程
- 服务端启动后持续监听外部电子卡的MQTT消息;
- 客户端页面加载时,
OnInitializedAsync()执行,完成_monitoringDatas实例化; - 传感器检测到运动时,服务端通过SignalR Hub向客户端推送消息;
- 客户端接收消息触发
ReceiveLidarValue(),创建Monitoring对象并添加至_monitoringDatas。
原因分析
Blazor的UI更新机制依赖组件状态变更的检测,而Syncfusion DataGrid绑定List<T>时,默认仅在集合的引用发生变化时才会触发重新渲染:
- 当你只调用
_monitoringDatas.Add(Monit)时,List的内存引用没有改变,Blazor无法检测到状态变化,因此不会通知Grid刷新数据; - 重新实例化
_monitoringDatas = new List<Monitoring>()时,变量的引用指向了新的内存对象,Blazor检测到这个变更后,会触发组件重新渲染,Grid也就绑定了新的List数据(但旧数据会被清空,所以只能看到最新一条)。
解决方案
方案1:手动触发状态变更
在添加数据后,调用StateHasChanged()方法手动通知Blazor组件状态已更新,这样无需重新实例化List,还能保留历史数据:
Task ReceiveLidarValue(string arg) { Monitoring Monit = new Monitoring() { IdMonotoring = 1, RealProduction = false, Machine = "remplisseuse", DatePassage = DateTime.Now, }; _monitoringDatas.Add(Monit); StateHasChanged(); // 手动触发UI更新 }
方案2:使用支持变更通知的集合
将List<Monitoring>替换为ObservableCollection<Monitoring>,该集合在元素添加/删除时会自动触发变更通知,无需手动调用StateHasChanged():
步骤1:修改集合类型
// 替换List为ObservableCollection private ObservableCollection<Monitoring> _monitoringDatas; protected override async Task OnInitializedAsync() { ... _monitoringDatas = new ObservableCollection<Monitoring>(); }
步骤2:更新接收方法
Task ReceiveLidarValue(string arg) { Monitoring Monit = new Monitoring() { IdMonotoring = 1, RealProduction = false, Machine = "remplisseuse", DatePassage = DateTime.Now, }; _monitoringDatas.Add(Monit); // 自动触发UI更新 }
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

