C# 为什么ObservableCollection实现INotifyPropertyChanged?

C# 为什么ObservableCollection实现INotifyPropertyChanged?,c#,.net,data-binding,observablecollection,inotifypropertychanged,C#,.net,Data Binding,Observablecollection,Inotifypropertychanged,在.NET4.0中,ObservableCollection没有定义一个属性,也没有覆盖其父级或接口的任何属性。那么为什么ObservableCollection实现INotifyPropertyChanged呢 我能想到的一个原因是,它使子类更容易定义自己的属性并使用ObservaleCollection实现的OnPropertyChanged方法。但这是主要原因吗?计数和项目[]更改都会得到通知。下面是一个仅用于字符串插值的C 6示例: using System; using System.

在.NET4.0中,ObservableCollection没有定义一个属性,也没有覆盖其父级或接口的任何属性。那么为什么ObservableCollection实现INotifyPropertyChanged呢

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

计数和项目[]更改都会得到通知。下面是一个仅用于字符串插值的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";
    }
}
在属性Item、Items和Count中,只有Item实际具有setter,所以不需要重写Items或Count,因为您无法设置它们,所以不需要从中引发事件。它们仅在响应其他方法(如Add或Remove)时更改,这些方法将引发必要的属性更改事件。实际上,如果查看源代码,ObservableCollection也不会重写这些方法,而是重写由基类中的Add和Remove调用的受保护方法

现在对于Item,属性不会被覆盖,但是如果查看SetItem方法的:


总之,集合中的项调用在ObservaleCollection中被重写的SetItem,该SetItem会触发PropertyChanged事件。

ObservaleCollection有3个属性,分别为Item、indexer、Count和Items。@Jonsket看起来像indexer和Count do,但不是Items。看见source@redcurry:仅因为属性本身是继承的,并不意味着它们更改的原因不能引发事件。请参阅我的答案,以获得它们确实引发事件的证据。@redcurry,看看我提供的源代码,它清楚地表明,即使属性是继承的,事件也由ObservableCollection类处理。请注意,在Item、Count和Items中,只有Item具有setter。ObservableCollection不需要重写Count或Items,因为它们只能通过其他方法(如Add和Remove)获得更改,并且在这些方法的代码中,将触发NotifyPropertyChanged事件。您可能想说这是一个C6示例:@RonBeyer:正在考虑这样做,但我不知道这会持续多久。。。将添加一个小便条。
Adding
  Count changed
  Item[] changed
Adding
  Count changed
  Item[] changed
Removing
  Count changed
  Item[] changed
Changing
  Item[] changed
/// <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);
}
    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);
        }
    }