ObservableCollection (int .NET 3.5) 似乎以一种有趣的方式实现了 PropertyChanged 事件。
protected event PropertyChangedEventHandler PropertyChanged;
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;
这意味着受保护的PropertyChanged事件可能仅用于内部实现。另一个INotifyPropertyChanged.PropertyChanged事件实际上是作为显式接口实现INotifyPropertyChanged接口的事件。奇怪的是,我在 ObservableCollection 中没有看到实际引发INotifyPropertyChanged.PropertyChanged的任何地方。这可能表明这是 .NET 3.5 中的一个错误,尽管我尚未测试以确认在将项目添加到集合时是否会为 Count 引发属性更改事件,但这似乎是它应该如何工作.
在 .NET 4.0 实现中,INotifyPropertyChanged.PropertyChanged事件似乎与受保护的PropertyChanged事件使用的同一私有委托挂钩,这可能是一个错误修复。这也可能只是由于.NET 4.0 中自动事件实现的处理方式不同。
更正:我已验证INotifyPropertyChanged.PropertyChanged事件是由 ObservableCollection 引发的,因此我上面基于使用 Reflector 查看 ObservableCollection 实现的结果所做的假设一定是不准确的。我的猜测是反射器正在做一些奇怪的错误,我还没有证据。
因此,要使您的示例正常工作,您需要为此编写代码,就像下面的示例一样,正如 Will 在他的回答中所展示的那样。
SelectableList<int> intList = new SelectableList<int>();
((INotifyPropertyChanged)intList).PropertyChanged +=
new PropertyChangedEventHandler(intList_Changed);
很有趣吧?使用显式接口主要用于避免给定接口所需的成员中不可避免的冲突,但它们可以用来在某种意义上隐藏成员的存在。
如果您想为您在子类中引入的自定义属性引发属性更改事件,请查看覆盖和/或调用ObservableCollection 也实现的受保护的OnPropertyChanged方法。这种技术是一种被广泛采用的标准,它允许子类在不访问底层事件委托的情况下引发事件或处理事件。顺便说一下,通常更喜欢使用这种技术,而不是让子类挂钩事件处理程序到它自己的基类事件。有关更多示例,请查看如何在 WinForms 和 WPF 中实现各种控件中的事件。