【问题标题】:How does WPF know to use INotifyPropertyChanged when I bind to IEnumerable?当我绑定到 IEnumerable 时,WPF 如何知道使用 INotifyPropertyChanged?
【发布时间】: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&lt;&gt;,它实现了INotifyCollectionChanged, INotifyPropertyChanged...
  • 将集合暴露为IEnumerable 无关紧要,Binding 将检查实际实例是否实现INotifyCollectionChanged。由于实例实际上是一个ObservableCollection,它确实实现了它,并且绑定可以简单地订阅CollectionChanged 事件。
  • @almulo,这是否意味着WPF使用反射来检查返回的对象是否实现INotifiyCollectionChanged
  • 差不多。例如,您可以通过object 类型的属性公开复杂类,并且仍然可以毫无问题地绑定到类属性。

标签: c# wpf


【解决方案1】:

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

DataObservableCollection 类型,它在内部实现 INotifyCollectionChanged

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

【讨论】:

  • 但是返回的数据是IEnumerable,而不是ObservableCollection
【解决方案2】:

即使您的Data 属性以IEnumerable&lt;IData&gt; 的类型返回,对象本身仍然是ObservableCollection&lt;ObservableData&gt;。 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;
}

【讨论】:

  • 谢谢@nekizalb!你的isas 运营商启发了我,让我觉得这个问题是多么愚蠢。 XD。
猜你喜欢
  • 1970-01-01
  • 2011-04-17
  • 2013-07-31
  • 2023-03-13
  • 1970-01-01
  • 2010-11-13
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多