如何处理WPF DataGrid行内元素值修改事件,如复选框状态变更问题
现有代码问题解答
疑问1:订阅的生效范围问题
- 构造函数中的订阅仅对构造执行时刻
SelectedItem指向的行对象生效,当DataGrid切换选中行导致SelectedItem指向新对象时,旧订阅不会自动迁移到新对象,后续新选中行的属性变更不会触发处理逻辑,同时旧对象上的未取消订阅还会导致内存泄漏。
疑问2:空引用异常问题
- 会触发空引用异常。构造函数执行时
SelectedItem默认值为null,直接访问SelectedItem.PropertyChanged会直接抛出NullReferenceException,这是原代码的明显bug。
原方案优化方法
如果你的需求是仅处理当前选中行的属性变更,可以把订阅逻辑移到SelectedItem的setter中,自动处理新旧对象的订阅解绑和绑定,构造函数中原来的订阅代码直接删除即可:
public YourDataType SelectedItem { get { return selectedItem; } set { // 解绑旧选中对象的订阅 if (selectedItem != null) { selectedItem.PropertyChanged -= SelectedItem_PropertyChanged; } selectedItem = value; // 给新选中对象添加订阅 if (selectedItem != null) { selectedItem.PropertyChanged += SelectedItem_PropertyChanged; } NotifyPropertyChanged(nameof(SelectedItem)); } } private void SelectedItem_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "YourPropertyName") DoSomethingHere(); else if (e.PropertyName == "OtherPropertyName") DoSomethingElse(); }
处理所有行属性变更的方案
如果你需要监听DataGrid中任意行的属性变更(无论行是否被选中),可以监听集合的变更,给所有行对象统一添加订阅:
public ObservableCollection<YourDataType> Items { get { return items; } set { if (items != null) { // 解绑旧集合所有元素的订阅 foreach (var item in items) { item.PropertyChanged -= Item_PropertyChanged; } items.CollectionChanged -= Items_CollectionChanged; } items = value; if (items != null) { // 给新集合所有元素添加订阅 foreach (var item in items) { item.PropertyChanged += Item_PropertyChanged; } // 监听集合增删事件,动态处理新增/删除元素的订阅 items.CollectionChanged += Items_CollectionChanged; } NotifyPropertyChanged(nameof(Items)); } } private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (YourDataType item in e.NewItems) { item.PropertyChanged += Item_PropertyChanged; } } if (e.OldItems != null) { foreach (YourDataType item in e.OldItems) { item.PropertyChanged -= Item_PropertyChanged; } } } private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "你的复选框绑定属性名") { var changedRow = sender as YourDataType; // 此处写入你的业务逻辑 } }
内容的提问来源于stack exchange,提问作者Álvaro García
相关产品推荐
相关产品推荐

