WPF DataGrid修改子对象属性时ValueTotal不更新问题求助
问题描述
用Caliburn.Micro做WPF应用,DataGrid绑定的是ProductModel集合。现在遇到个问题:修改Value1或Value2里的MinValue、MaxValue时,ValueTotal不更新;但改Value3的时候,ValueTotal能正常变化。调试发现改Min/MaxValue时,Value1和Value2的Setter根本没触发。
问题根源
- MyModel未实现属性变更通知:MyModel的MinValue、MaxValue是自动属性,修改时不会对外通知变化,ProductModel根本不知道这些值变了,自然不会更新ValueTotal。
- ProductModel只监听对象替换,不监听子属性变化:ProductModel里的Value1、Value2只有在整个对象被替换时才会通知ValueTotal更新,但修改子对象的Min/MaxValue时,父对象感知不到。
- XAML绑定大小写不匹配:WPF绑定区分大小写,ProductModel的属性是
Value1/Value2/Value3,但XAML里写的是小写的value1/value2/value3,这会导致绑定失效,甚至可能连初始值都显示不对。 - ProductModel里Value2的字段有笔误:代码里
get { return _c_value2; }和__value2 = value;都是错误的,应该是_value2,会引发运行时错误。
解决步骤
1. 给MyModel加上属性变更通知
直接继承Caliburn.Micro的PropertyChangedBase,省得自己手动实现INotifyPropertyChanged:
public class MyModel : PropertyChangedBase { private double _minValue; private double _maxValue; public double MinValue { get => _minValue; set { _minValue = value; NotifyOfPropertyChange(); } } public double MaxValue { get => _maxValue; set { _maxValue = value; NotifyOfPropertyChange(); } } }
2. 修改ProductModel,监听子对象的属性变化
在ProductModel里,给Value1、Value2赋值时订阅它们的PropertyChanged事件,这样子对象的Min/MaxValue变了,父对象就能收到通知并更新ValueTotal;同时修正Value2的字段笔误:
public class ProductModel : Screen { private MyModel _value1 = new MyModel(); private MyModel _value2 = new MyModel(); private double _value3; public double ValueTotal { get { var sumMaxValues = _value1.MaxValue + _value2.MaxValue; var sumMinValues = _value1.MinValue + _value2.MinValue; return (sumMaxValues + sumMinValues) / 2; } } public MyModel Value1 { get => _value1; set { // 取消旧对象的事件订阅,防止内存泄漏 if (_value1 != null) _value1.PropertyChanged -= OnMyModelPropertyChanged; _value1 = value; // 给新对象订阅事件 if (_value1 != null) _value1.PropertyChanged += OnMyModelPropertyChanged; NotifyOfPropertyChange(() => ValueTotal); } } public MyModel Value2 { get => _value2; set { if (_value2 != null) _value2.PropertyChanged -= OnMyModelPropertyChanged; _value2 = value; if (_value2 != null) _value2.PropertyChanged += OnMyModelPropertyChanged; NotifyOfPropertyChange(() => ValueTotal); } } public double Value3 { get => _value3; set { _value3 = value; NotifyOfPropertyChange(() => ValueTotal); } } // 子对象属性变化时,通知ValueTotal更新 private void OnMyModelPropertyChanged(object sender, PropertyChangedEventArgs e) { // 只关心MinValue和MaxValue的变化 if (e.PropertyName == nameof(MyModel.MinValue) || e.PropertyName == nameof(MyModel.MaxValue)) { NotifyOfPropertyChange(() => ValueTotal); } } // 页面关闭时清理事件订阅,避免内存泄漏 protected override void OnDeactivate(bool close) { if (_value1 != null) _value1.PropertyChanged -= OnMyModelPropertyChanged; if (_value2 != null) _value2.PropertyChanged -= OnMyModelPropertyChanged; base.OnDeactivate(close); } }
3. 修正XAML绑定的大小写错误
把XAML里所有小写的value1/value2/value3改成大写开头的Value1/Value2/Value3,比如:
<!-- 原来的错误绑定 --> <TextBlock Text="{Binding value1.MaxValue, StringFormat='{}{0:0.00}'}" /> <!-- 修正后的正确绑定 --> <TextBlock Text="{Binding Value1.MaxValue, StringFormat='{}{0:0.00}'}" />
CellEditingTemplate里的TextBox绑定也要做同样修改,不然编辑时无法把值正确同步到ViewModel。
内容的提问来源于stack exchange,提问作者Aimluv
相关产品推荐
相关产品推荐

