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

如何处理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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 15:06:07