WPF .NET 5下EF Core 5重载实体未触发NotifyPropertyChanged问题咨询
问题现象
- 定义了两个属性:
Items集合属性、单个Item属性 Items绑定到DataGrid控件,双击DataGrid行时选中项会赋值到Item属性- 文本框绑定路径为
Item.Name,绑定配置了UpdateSourceTrigger=PropertyChanged,修改文本框内容时会实时同步到DataGrid显示 - 执行取消操作时,调用
_context.Entry(Item).Reload()从数据库重载实体数据,UI没有同步刷新,OnPropertyChanged未触发 - 手动调用
OnPropertyChanged(nameof(Item))也无法生效,目前只能用以下临时hack写法触发更新:
_itemRepository.Reload(Item); Item.Name = Item.Name; //OnPropertyChanged(nameof(Post));
环境说明
技术栈:.NET 5 + WPF + EF Core 5Item模型代码如下:
public class Item : BaseEntity { private string _name; public string Name { get => _name; set { _name = value; OnPropertyChanged(nameof(Name)); } } }
原因说明
这是EF Core的设计特性,并非Bug。
EF Core默认重载实体时会直接修改实体对应的私有字段(如上面代码中的_name),不会走属性的set访问器,因此写在set中的OnPropertyChanged通知逻辑不会执行,UI感知不到数据变更。
手动调用OnPropertyChanged(nameof(Item))不生效的原因是:绑定路径为Item.Name,属于子属性绑定,WPF绑定系统只会监听Name属性的变更通知,不会因为父属性Item的变更通知就刷新所有子属性绑定。
解决方案
方案1:手动触发子属性变更通知
实体重载完成后,手动调用所有变更过的属性的通知方法:
_context.Entry(Item).Reload(); OnPropertyChanged(nameof(Item.Name)); // 若有其他变更属性,依次添加对应通知即可
方案2:替换Item实例而非修改原有实例
不从数据库重载原有实例,而是重新查询新的实例赋值给Item属性,赋值后触发Item属性的通知:
Item = _context.Items.Find(Item.Id); OnPropertyChanged(nameof(Item));
方案3:配置EF Core使用属性setter赋值
在DbContext的OnModelCreating方法中配置实体属性的访问模式,强制EF Core走属性的set访问器赋值,重载时会自动触发通知:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Item>() .Property(p => p.Name) .UsePropertyAccessMode(PropertyAccessMode.Property); }
临时修复方案
在找到最终适配方案前,可调用DataGrid的刷新方法强制更新UI:
Datagrid.Items.Refresh();
内容的提问来源于stack exchange,提问作者andySF
相关产品推荐
相关产品推荐

