Does anyone know why this code doesn't work:
public class CollectionViewModel : ViewModelBase {
public ObservableCollection<EntityViewModel> ContentList
{
get { return _contentList; }
set
{
_contentList = value;
RaisePropertyChanged("ContentList");
//I want to be notified here when something changes..?
//debugger doesn't stop here when IsRowChecked is toggled
}
}
}
public class EntityViewModel : ViewModelBase
{
private bool _isRowChecked;
public bool IsRowChecked
{
get { return _isRowChecked; }
set { _isRowChecked = value; RaisePropertyChanged("IsRowChecked"); }
}
}
ViewModelBase
containts everything for RaisePropertyChanged
etc. and it's working for everything else except this problem..
The ContentList's Set method will not get called when you change a value inside the collection, instead you should be looking out for the CollectionChanged event firing.
Okay, that's twice today I've been bitten by the MSDN documentation being wrong. In the link I gave you it says:
But it actually doesn't fire when an item is changed. I guess you'll need a more bruteforce method then:
If you are going to need this a lot you may want to subclass your own
ObservableCollection
that triggers theCollectionChanged
event when a member triggers itsPropertyChanged
event automatically (like it says it should in the documentation...)This uses the above ideas but makes it a derived 'more sensitive' collection:
Here is my version of the implementation. It checks and throws an error, if the objects in list doesnt implement INotifyPropertyChanged, so can't forget that issue while developing. On the outside you use the ListItemChanged Event do determine whether the list or the list item itself has changed.
Simple solution in 2 lines of code. Just use the copy constructor. No need to write TrulyObservableCollection etc.
Example:
Another method without copy constructor. You can use serialization.
I've put together what I hope is a pretty robust solution, including some of the techniques in other answers. It is a new class derived from
ObservableCollection<>
, which I'm callingFullyObservableCollection<>
It has the following features:
ItemPropertyChanged
. I've deliberately kept this separate from the existingCollectionChanged
:ItemPropertyChangedEventArgs
that accompanies it: the originalPropertyChangedEventArgs
and the index within the collection.ObservableCollection<>
.ObservableCollection<>.Clear()
), avoiding a possible memory leak.OnCollectionChanged()
, rather than a more resource-intensive subscription to theCollectionChanged
event.Code
The complete
.cs
file follows. Note that a few features of C# 6 have been used, but it should be fairly simple to backport it:NUnit Tests
So you can check changes you might make (and see what I tested in the first place!), I've also included my NUnit test class. Obviously, the following code is not necessary just to use
FullyObservableCollection<T>
in your project.NB The test class uses
BindableBase
from PRISM to implementINotifyPropertyChanged
. There is no dependency on PRISM from the main code.ObservableCollection will not propagate individual item changes as CollectionChanged events. You will either need to subscribe to each event and forward it manually, or you can check out the BindingList[T] class, which will do this for you.