在.NET 4.0中,没有ObservableCollection<T>
定义的单个属性,也不会覆盖其父或接口的任何属性。那么为什么ObservableCollection<T>
实施INotifyPropertyChanged
?
我能想到的一个原因是,它使子类更容易定义自己的属性并使用OnPropertyChanged
实现的ObservableCollection<T>
方法。但这是主要原因吗?
答案 0 :(得分:3)
通知Count
和Item[]
更改。这是一个示例(仅使用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)
在属性Item
,Items
和Count
中,只有Item
实际上有一个setter,因此无需覆盖Items
或{{ 1}}因为你无法设置它们,所以不需要从中引发事件。它们只会针对其他方法(例如Count
或Add
)进行更改,而这些方法会引发必要的属性更改事件(实际上,如果您查看源代码,{ {1}}也不会覆盖这些方法,而是覆盖基类中Remove
和ObservableCollection<T>
调用的protected
方法。
现在Add
,该属性未被覆盖,但如果您查看Remove
方法的source:
Item
您会从评论中注意到,当设置SetItem
时,基类会调用此值,并且您还会注意到它会触发/// <summary>
/// Called by base class Collection<T> 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>
事件。