How to detect if an item in my ObservableCollection has changed

Remotec picture Remotec · Jan 24, 2012 · Viewed 22.6k times · Source

I have a datagrid which is bound to ObservableCollection<Product>. When the grid is updated this automatically updates the Product object in my collection.

What I want to do now is to have some sort of even that is triggered when any object in the collection is updated -or- some sort of binding to the collection that will return true/false depedant on if any Product has been updated.

The overall objective is to have a save button on my main window that is disabled if no changes have been made to my collection and enabled if changes have been made.

I have read into INotifyPropertyChange but I dont see how I can use this to monitor changes on a whole collection.

Additionally, if I implement this interface on my Product class I dont see how my UI can monitor every product in the collection - or can it?

Answer

chopikadze picture chopikadze · Jan 24, 2012
  • Implement INotifyPropertyChanged in your Product class with notification for every property.
  • Implement INotifyPropertyChanged in your viewmodel.
  • Add property IsDirty to your ViewModel (with notification through INotifyPropertyChanged.
  • In your viewmodel, subscribe to CollectionChanged

    public YourViewModel()
    {
        ...
        YourCollection.CollectionChanged += YourCollection_CollectionChanged; 
        ...
    }
    
    private void YourCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args)
    {
        if (args.OldItems != null)
            foreach(var oldItem in args.OldItems)
                oldItem.PropertyChanged -= YourItem_PropertyChanged;
    
        if (args.NewItems != null)
            foreach(var newItem in args.NewItems)
                newItem.PropertyChanged += YourItem_PropertyChanged;
    }
    
    private void Youritem_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs args)
    {
        IsDirty = true;
    }
    
  • Now you can bind to IsDirty property of your viewmodel, for example, you can bind Button.IsEnabled property directly to it.