当我绑定到IEnumerable时,WPF如何知道使用INotifyPropertyChanged?

时间:2015-07-27 15:16:06

标签: c# wpf

在视图模型(SomeViewModel下面)中,Data属性返回IEnumerable<IData>,其中两个接口都不实现INotifyPropertyChanged

但是,基础数据字段为ObservableCollection<ObservableData>,两个类都实现INotifyPropertyChanged

最后在XAML中,`数据绑定到DataGrid。

  

&lt; DataGrid ItemsSource =&#34; {Binding Data}&#34;的AutoGenerateColumns =&#34;真&#34; /&GT;

我认为这种绑定可能会引入KB938416中描述的绑定内存泄漏,但令我惊讶的是它没有。

调用方法ChangeData时,我可以看到DataGrid已更新,OnPropertyChanged称为处理程序。

我的问题是:当绑定数据返回INotifyPropertyChanged时,WPF如何知道使用IEnumerable<IData>(两者都没有实现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";
    }
}

2 个答案:

答案 0 :(得分:3)

在您的情况下,INotifyPropertyChanged属性不需要Data

Data的类型为ObservableCollection,内部实现INotifyCollectionChanged

因此,只要您添加或删除项目,视图就会收到通知。

答案 1 :(得分:2)

即使返回的Data属性类型为IEnumerable<IData>,对象本身仍为ObservableCollection<ObservableData>。无论提供什么句柄,WPF都可以使用isas运算符来测试任何特定对象是否实现INotifyPropertyChanged

IEnumerable<IData> test = Data;
if (test is INotifyPropertyChanged) { 
    //This if block enters because test is really ObservableCollection<ObservableData>
    INotifyPropertyChanged test2 = (INotifyPropertyChanged)test;
}