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