Notify ObservableCollection when Item changes Notify ObservableCollection when Item changes wpf wpf

Notify ObservableCollection when Item changes


The spot you have commented as // Code to trig on item change... will only trigger when the collection object gets changed, such as when it gets set to a new object, or set to null.

With your current implementation of TrulyObservableCollection, to handle the property changed events of your collection, register something to the CollectionChanged event of MyItemsSource

public MyViewModel(){    MyItemsSource = new TrulyObservableCollection<MyType>();    MyItemsSource.CollectionChanged += MyItemsSource_CollectionChanged;    MyItemsSource.Add(new MyType() { MyProperty = false });    MyItemsSource.Add(new MyType() { MyProperty = true});    MyItemsSource.Add(new MyType() { MyProperty = false });}void MyItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e){    // Handle here}

Personally I really don't like this implementation. You are raising a CollectionChanged event that says the entire collection has been reset, anytime a property changes. Sure it'll make the UI update anytime an item in the collection changes, but I see that being bad on performance, and it doesn't seem to have a way to identify what property changed, which is one of the key pieces of information I usually need when doing something on PropertyChanged.

I prefer using a regular ObservableCollection and just hooking up the PropertyChanged events to it's items on CollectionChanged. Providing your UI is bound correctly to the items in the ObservableCollection, you shouldn't need to tell the UI to update when a property on an item in the collection changes.

public MyViewModel(){    MyItemsSource = new ObservableCollection<MyType>();    MyItemsSource.CollectionChanged += MyItemsSource_CollectionChanged;    MyItemsSource.Add(new MyType() { MyProperty = false });    MyItemsSource.Add(new MyType() { MyProperty = true});    MyItemsSource.Add(new MyType() { MyProperty = false });}void MyItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e){    if (e.NewItems != null)        foreach(MyType item in e.NewItems)            item.PropertyChanged += MyType_PropertyChanged;    if (e.OldItems != null)        foreach(MyType item in e.OldItems)            item.PropertyChanged -= MyType_PropertyChanged;}void MyType_PropertyChanged(object sender, PropertyChangedEventArgs e){    if (e.PropertyName == "MyProperty")        DoWork();}


I solved this case by using static Action


public class CatalogoModel {    private String _Id;    private String _Descripcion;    private Boolean _IsChecked;    public String Id    {        get { return _Id; }        set { _Id = value; }    }    public String Descripcion    {        get { return _Descripcion; }        set { _Descripcion = value; }    }    public Boolean IsChecked    {        get { return _IsChecked; }        set        {           _IsChecked = value;            NotifyPropertyChanged("IsChecked");            OnItemChecked.Invoke();        }    }    public static Action OnItemChecked;} public class ReglaViewModel : ViewModelBase{    private ObservableCollection<CatalogoModel> _origenes;    CatalogoModel.OnItemChecked = () =>            {                var x = Origenes.Count;  //Entra cada vez que cambia algo en _origenes            };}


A simple solution is to use BindingList<T> instead of ObservableCollection<T> . Indeed the BindingList relay item change notifications. So with a binding list, if the item implements the interface INotifyPropertyChanged then you can simply get notifications using the ListChanged event.

See also this SO answer.