WPF MVVM模式下DataGrid编辑时获取单元格新旧值的实现方法问询
WPF DataGrid编辑场景获取新旧值解决方案
以下是三种可直接落地的实现方式,均符合MVVM架构规范:
方案1:利用DataGridCellEditEnding事件特性直接获取(无需修改模型)
DataGridCellEditEnding事件触发时,绑定数据源默认还未完成更新,此时实体属性值就是编辑前的旧值,新值可直接从编辑控件中提取,不需要额外做历史值缓存:
- 首先确保你的EventToCommand配置开启
PassEventArgsToCommand="True",将事件参数直接传递到ViewModel的Command - 示例代码如下:
// ViewModel中Command定义 public ICommand CellEditEndingCommand { get; } public YourViewModel() { CellEditEndingCommand = new RelayCommand<object>(OnCellEditEnding); } private void OnCellEditEnding(object parameter) { if (parameter is not DataGridCellEditEndingEventArgs e) return; // 获取当前行绑定的实体对象 var currentEntity = e.Row.Item as YourBusinessModel; if (currentEntity == null) return; // 此时实体属性未更新,直接读取即为旧值 var oldValue = currentEntity.TargetProperty; // 根据编辑控件类型提取新值,此处以默认TextBox编辑为例 var newValue = (e.EditingElement as TextBox)?.Text; // 后续业务逻辑处理 }
注意:如果你的绑定手动修改了
UpdateSourceTrigger="PropertyChanged",该方案不生效,需使用另外两种方案。
方案2:实体层单独缓存对应属性旧值
如果需要在多处业务逻辑中使用属性旧值,可以直接在实体的属性Setter中缓存旧值:
public class YourBusinessModel : INotifyPropertyChanged { private string _targetProperty; // 缓存对应属性的旧值 private string _targetPropertyOldValue; public string TargetProperty { get => _targetProperty; set { if (_targetProperty == value) return; // 赋值前先存储旧值 _targetPropertyOldValue = _targetProperty; _targetProperty = value; OnPropertyChanged(); } } // 对外暴露只读旧值属性 public string TargetPropertyOldValue => _targetPropertyOldValue; public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
该方案符合MVVM分层原则,旧值获取逻辑完全和视图层解耦。
方案3:通用实体属性变更跟踪基类
如果需要跟踪大量属性的旧值,可以封装通用的跟踪基类,避免每个属性重复写缓存逻辑:
public class TrackableEntityBase : INotifyPropertyChanged { private readonly Dictionary<string, object> _propertyOldValues = new(); public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, newValue)) return false; // 自动缓存旧值 _propertyOldValues[propertyName] = field; field = newValue; OnPropertyChanged(propertyName); return true; } // 对外提供旧值查询方法 public bool TryGetOldValue<T>(string propertyName, out T oldValue) { if (_propertyOldValues.TryGetValue(propertyName, out var value) && value is T typedValue) { oldValue = typedValue; return true; } oldValue = default; return false; } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } // 业务实体直接继承即可 public class YourBusinessModel : TrackableEntityBase { private string _targetProperty; public string TargetProperty { get => _targetProperty; set => SetProperty(ref _targetProperty, value); } }
内容的提问来源于stack exchange,提问作者Quentin
相关产品推荐
相关产品推荐

