Why does ObservableCollection<T> implement INotifyPropertyChanged?

懵懂的女人 提交于 2020-01-05 01:30:27

问题


In .NET 4.0, there isn't a single property defined by ObservableCollection<T> nor does it override any property of its parent or interfaces. So why does ObservableCollection<T> implement INotifyPropertyChanged?

One reason I can think of is that it makes it easier for subclasses to define their own properties and use the OnPropertyChanged method implemented by ObservableCollection<T>. But is this the main reason?


回答1:


Of the properties Item, Items and Count, only Item actually has a setter, so there is no need to override Items or Count since you can't set them, there is no need to raise an event from it. They only change in response to some other method (like Add or Remove) and those methods will raise the necessary property changed events (actually if you look at the source, ObservableCollection<T> doesn't override those methods either, but instead overrides protected methods that are called by Add and Remove in the base class).

Now for Item, the property isn't overriden, but if you look at the source for the SetItem method:

/// <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);
}

You'll note from the comment that this is called by the base class when an Item is set and you'll also note that it fires off the OnPropertyChanged event.

If you look at the source for Collection<T> you can confirm that this is the case:

    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);
        }
    }

So in summary, Item in Collection<T> calls SetItem that is overridden in ObservableCollection<T> which triggers the PropertyChanged event.




回答2:


Both Count and Item[] changes are notified. Here's a sample (using C# 6 just for the string interpolation):

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";
    }
}

Output:

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


来源:https://stackoverflow.com/questions/31342296/why-does-observablecollectiont-implement-inotifypropertychanged

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!