How to detect if an item in my ObservableCollection has changed
Solution 1
- Implement
INotifyPropertyChanged
in yourProduct
class with notification for every property. - Implement
INotifyPropertyChanged
in your viewmodel. - Add property
IsDirty
to your ViewModel (with notification throughINotifyPropertyChanged
. 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 bindButton.IsEnabled
property directly to it.
Solution 2
Just use the ObservableCollection. It has an event called CollectionChanged. If you register it, you can do what you want. Example:
ObservableCollection<string> strings = new ObservableCollection<string>();
strings.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(changed);
strings.Add("Hello");
strings[0] = "HelloHello";
And:
private void changed(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args)
{
//You get notified here two times.
}
Solution 3
The logic needs to go in your Model (Product class).
A clean approach would be to expose IsDirty
property (backed by field) in your model.
And your ViewModel would have a Command binding with CanSave
checking the internal collection, and return true if Any of the item in collection IsDirty=true
.
Charlie Kou
Updated on July 09, 2022Comments
-
Charlie Kou almost 2 years
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?
-
Stealth Rabbi about 11 yearsDespite the MSDN documentation, CollectionChanged doesn't get invoked when objects in the collection change. Only when the collectoin itself has objects added or deleted.
-
Oystein over 6 yearsThis ought to be set as the answer.
-
Junior about 6 yearsFor this code to work,
foreach(var oldItem in args.OldItems)
should be changed toforeach(Product oldItem in args.OldItems)
andforeach(var newItem in args.NewItems)
toforeach(Product newItem in args.NewItems)
. Also this answer should be accepted