Reputation: 1068
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
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
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