为什么ObservableCollection <t>实现了INotifyPropertyChanged?

时间:2015-07-10 13:41:06

标签: c# .net data-binding observablecollection inotifypropertychanged

在.NET 4.0中,没有ObservableCollection<T>定义的单个属性,也不会覆盖其父或接口的任何属性。那么为什么ObservableCollection<T>实施INotifyPropertyChanged

我能想到的一个原因是,它使子类更容易定义自己的属性并使用OnPropertyChanged实现的ObservableCollection<T>方法。但这是主要原因吗?

2 个答案:

答案 0 :(得分:3)

通知CountItem[]更改。这是一个示例(仅使用C#6进行字符串插值):

using System;
using System.ComponentModel;
using System.Collections.ObjectModel;

class Test
{
    static void Main(string[] args)
    {
        var collection = new ObservableCollection<string>();
        ((INotifyPropertyChanged)collection).PropertyChanged += (sender, e) =>
        {
            Console.WriteLine($"  {e.PropertyName} changed");
        };

        Console.WriteLine("Adding");
        collection.Add("Item");
        Console.WriteLine("Adding");
        collection.Add("Other item");
        Console.WriteLine("Removing");
        collection.RemoveAt(0);
        Console.WriteLine("Changing");
        collection[0] = "Different";
    }
}

输出:

Adding
  Count changed
  Item[] changed
Adding
  Count changed
  Item[] changed
Removing
  Count changed
  Item[] changed
Changing
  Item[] changed

答案 1 :(得分:1)

在属性ItemItemsCount中,只有Item实际上有一个setter,因此无需覆盖Items或{{ 1}}因为你无法设置它们,所以不需要从中引发事件。它们只会针对其他方法(例如CountAdd)进行更改,而这些方法会引发必要的属性更改事件(实际上,如果您查看源代码,{ {1}}也不会覆盖这些方法,而是覆盖基类中RemoveObservableCollection<T>调用的protected方法。

现在Add,该属性未被覆盖,但如果您查看Remove方法的source

Item

您会从评论中注意到,当设置SetItem时,基类会调用此值,并且您还会注意到它会触发/// <summary> /// Called by base class Collection&lt;T&gt; when an item is set in list; /// raises a CollectionChanged event to any listeners. /// </summary> protected override void SetItem(int index, T item) { CheckReentrancy(); T originalItem = this[index]; base.SetItem(index, item); OnPropertyChanged(IndexerName); OnCollectionChanged(NotifyCollectionChangedAction.Replace, originalItem, item, index); } 事件。

如果您查看Item的{​​{3}},可以确认是这种情况:

OnPropertyChanged

总而言之,Collection<T>中的 public T this[int index] { #if !FEATURE_CORECLR [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] #endif get { return items[index]; } set { if( items.IsReadOnly) { ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); } if (index < 0 || index >= items.Count) { ThrowHelper.ThrowArgumentOutOfRangeException(); } SetItem(index, value); } } 调用了Item Collection<T>SetItem会触发ObservableCollection<T>事件。