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

Pet*_*ter 3 c# wpf

在视图模型(SomeViewModel如下)中,Data属性返回IEnumerable<IData>两个接口都没有实现的地方INotifyPropertyChanged

但是,底层的 Data 字段是ObservableCollection<ObservableData>并且两个类都实现了INotifyPropertyChanged.

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

<Da​​taGrid ItemsSource="{绑定数据}" AutoGenerateColumns="True"/>

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

当该方法ChangeData被调用时,我可以看到 DataGrid 被更新并且被OnPropertyChanged调用了一个处理程序。

我的问题是:WPF 如何知道INotifyPropertyChanged在绑定数据返回时使用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";
    }
}
Run Code Online (Sandbox Code Playgroud)

thu*_*eys 5

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

DataObservableCollection类型,它在内部实现了INotifyCollectionChanged

因此,每当您添加或删除项目时,视图都会收到通知。


Tyl*_*Lee 4

即使您的Data属性以 的类型返回IEnumerable<IData>,对象本身仍然是ObservableCollection<ObservableData>。WPF 可以仅使用isoras运算符来测试任何特定对象是否实现INotifyPropertyChanged,而不管提供的句柄如何。

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