c# - 使用 TrulyObservableCollection 从 CollectionChanged 事件中获取更改的项目

标签 c# wpf class events observablecollection

我正在使用 TrulyObservableCollection 作为 WPF DataGrid 中的数据源。我的类(class)正确地实现了 PropertyChange 事件(属性更改时我会收到通知)。 CollectionChanged 事件也会被触发。但是,我的问题在于 PropertyChanged 事件和 CollectionChanged 事件之间的连接。我可以在 PropertyChanged 事件中看到正在更改的项目(在本例中为 sender 对象),但是我似乎无法找到一种方法来查看哪个是从 CollectionChanged 事件中更改。 sender 对象是整个集合。查看 CollectionChanged 事件中哪个项目已更改的最佳方法是什么?相关代码片段如下。感谢您的帮助,如果需要澄清,请告诉我。

设置集合的代码:

    private void populateBret()
    {
        bretList = new TrulyObservableCollection<BestServiceLibrary.bretItem>(BestClass.BestService.getBretList().ToList());
        bretList.CollectionChanged += bretList_CollectionChanged;
        dgBretList.ItemsSource = bretList;
        dgBretList.Items.Refresh();
    }

    void bretList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        //Do stuff here with the specific item that has changed
    }

集合中使用的类:

public class bretItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private int _blID;
    public string _blGroup;

    [DataMember]
    public int blID
    {
        get { return _blID; }
        set
        {
            _blID = value;
            OnPropertyChanged("blID");
        }
    }

    [DataMember]
    public string blGroup
    {
        get { return _blGroup; }
        set
        {
            _blGroup = value;
            OnPropertyChanged("blGroup");
        }
    }

    protected void OnPropertyChanged (String name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

TrulyObservableCollection 类

public class TrulyObservableCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged
    {
        public TrulyObservableCollection()
            : base()
        {
            CollectionChanged += new NotifyCollectionChangedEventHandler(TrulyObservableCollection_CollectionChanged);
        }
        public TrulyObservableCollection(List<T> list)
            : base(list)
        {
            foreach (var item in list)
            {
                item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
            }
            CollectionChanged += new NotifyCollectionChangedEventHandler(TrulyObservableCollection_CollectionChanged);
        }

        void TrulyObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (Object item in e.NewItems)
                {
                    (item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
                }
            }
            if (e.OldItems != null)
            {
                foreach (Object item in e.OldItems)
                {
                    (item as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
                }
            }
        }

        void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            NotifyCollectionChangedEventArgs a = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
            OnCollectionChanged(a);
        }
    }

编辑:

item_PropertyChanged 事件中,NotifyCollectionChangedEventArgs 设置为 NotifyCollectionChangedAction.Reset。这会导致 OldItemsNewItems 为空,因此在这种情况下我无法获得更改的项目。我不能使用 .Add,因为 Datagrid 更新了一个额外的项目。我似乎无法让 .Replace 工作以获取更改的项目。

最佳答案

这个怎么样:

在包含 bretItemObservableCollectionViewModel 中,ViewModel 订阅了 CollectionChanged 事件ObservableCollection

这将避免需要从 ObservableCollection 派生的新类 TrulyObservableCollection 耦合到其集合中的项目。

在您的 ViewModel 的处理程序中,您可以像现在一样添加和删除 PropertyChanged 事件处理程序。由于现在通知您的 ViewModel 集合中对象的更改,您可以采取适当的操作。

public class BretListViewModel
{

    private void populateBret()
    {
        bretList = new ObservableCollection<BestServiceLibrary.bretItem>(BestClass.BestService.getBretList().ToList());
        bretList.CollectionChanged += bretList_CollectionChanged;              
    }

    void bretList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
         if (e.NewItems != null)
        {
            foreach (Object item in e.NewItems)
            {
                (item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }
        if (e.OldItems != null)
        {
            foreach (Object item in e.OldItems)
            {
                (item as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }
    }


    void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        var bret = sender as bretItem;

        //Update the database now!

        //One note:
        //The ObservableCollection raises its change event as each item changes.
        //You should consider a method of batching the changes (probably using an ICommand)
    }

}

注意事项:

顺便说一句,看起来你正在打破基于这个片段的 MVVM 模式:

dgBretList.ItemsSource = bretList;
dgBretList.Items.Refresh();

您可能应该考虑加载您的 ViewModel 并将您的 View 绑定(bind)到它,而不是在您的 View 的代码隐藏中编码逻辑。

关于c# - 使用 TrulyObservableCollection 从 CollectionChanged 事件中获取更改的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13401403/

相关文章:

c# - 如何在 C# 中打开平板电脑模式的屏幕键盘?

c# - WPF中Form对应的 "this"是什么?

python - 我对 Blender 中的 Python 脚本有一个严重的问题

c# - 从单独的类库访问 web.config?

c++ - 从类中打印变量

c# - 将 .Net Remoting 从 Framework 2 迁移到 4 的问题

c# - 在关闭表格之前进行检查吗?

c# - Null To Boolean IValueConverter 不工作

c# - 重复双动画

c# - 在 Kendo UI 网格中控制组顺序