You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 19:36:01