Peter
Peter

Reputation: 1068

How does WPF know to use INotifyPropertyChanged when I bind to IEnumerable?

In a view model(SomeViewModel below), a Data property returns IEnumerable<IData> where both interfaces do not implement INotifyPropertyChanged.

However, the underlying Data field is ObservableCollection<ObservableData> and both classes implement the INotifyPropertyChanged.

Finally in XAML, `Data is bound to a DataGrid.

<DataGrid ItemsSource="{Binding Data}" AutoGenerateColumns="True"/>

I thought this binding could introduce the binding memory leak described in KB938416, but to my surprise it does not.

When the method ChangeData is called, I can see DataGrid is updated and the OnPropertyChanged called a handler.

My question is: How does WPF know to use INotifyPropertyChanged when the bound data returns IEnumerable<IData> (that both do not implement 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";
    }
}

Upvotes: 5

Views: 1082

Answers (2)

Tyler Lee
Tyler Lee

Reputation: 2785

Even though your Data property is returned with the type of IEnumerable<IData>, the object itself is still a ObservableCollection<ObservableData>. WPF can just use the is or as operators to test whether any particular object implements INotifyPropertyChanged, regardless of the handle provided.

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

Upvotes: 4

thumbmunkeys
thumbmunkeys

Reputation: 20764

In your case INotifyPropertyChanged is not needed for the Data property.

Data is of type ObservableCollection which internally implements INotifyCollectionChanged.

Due to this the view gets notified whenever you add or remove items.

Upvotes: 5

Related Questions