【发布时间】:2015-07-27 15:16:06
【问题描述】:
在视图模型(下面的SomeViewModel)中,Data 属性返回IEnumerable<IData>,其中两个接口都没有实现INotifyPropertyChanged。
但是,底层数据字段是ObservableCollection<ObservableData>,并且两个类都实现了INotifyPropertyChanged。
最后在 XAML 中,`Data 被绑定到一个 DataGrid。
我认为这个绑定可能会导致KB938416 中描述的绑定内存泄漏,但令我惊讶的是它没有。
当方法ChangeData被调用时,我可以看到DataGrid被更新并且OnPropertyChanged被调用了一个处理程序。
我的问题是:当绑定数据返回IEnumerable<IData>(两者都没有实现INotifyPropertyChanged)时,WPF怎么知道使用INotifyPropertyChanged??
public interface IData
{
string Name { get; }
}
// In addition to IData, implements INotifyPropertyChanged
public class ObservableData : IData, INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return this._name; }
set
{
if (_name == value) { return; }
_name = value;
OnPropertyChanged("Name");
}
}
// 'OnPropertyChanged' omitted for brevity
}
// here is some ViewModel
public class SomeViewModel
{
private ObservableCollection<ObservableData> _data = new ObservableCollection<ObservableData>();
// In XAML, a DataGrid's ItemsSource is bound to this.
public IEnumerable<IData> Data { get { return _data; } }
public void ChangeData()
{
// test OC's notification
_data.Add(new ObservableData {Name = "new" });
// test ObservableData's notification
_data[0].Name += " and changed";
}
}
【问题讨论】:
-
Data的实际类型是ObservableCollection<>,它实现了INotifyCollectionChanged, INotifyPropertyChanged... -
将集合暴露为
IEnumerable无关紧要,Binding 将检查实际实例是否实现INotifyCollectionChanged。由于实例实际上是一个ObservableCollection,它确实实现了它,并且绑定可以简单地订阅CollectionChanged事件。 -
@almulo,这是否意味着WPF使用反射来检查返回的对象是否实现
INotifiyCollectionChanged? -
差不多。例如,您可以通过
object类型的属性公开复杂类,并且仍然可以毫无问题地绑定到类属性。