Items in your collection should be of type that implements INotifyPropertyChanged interface. This way your list box will be notified that property value in your single item object has changed. ObservableCollection raises CollectionChanged event only when collection changes (items added, removed, etc.)
Quote from the MSDN library article on ObservableCollection
To fully support transferring data
values from binding source objects to
binding targets, each object in your
collection that supports bindable
properties must implement an
appropriate property changed
notification mechanism such as the
INotifyPropertyChanged interface.
New option for .NET 4.5
Starting from .NET 4.5 there is a built-in mechanism to automatically synchronize access to the collection and dispatch CollectionChanged
events to the UI thread. To enable this feature you need to call BindingOperations.EnableCollectionSynchronization
from within your UI thread.
EnableCollectionSynchronization
does two things:
- Remembers the thread from which it is called and causes the data binding pipeline to marshal
CollectionChanged
events on that thread.
- Acquires a lock on the collection until the marshalled event has been handled, so that the event handlers running UI thread will not attempt to read the collection while it's being modified from a background thread.
Very importantly, this does not take care of everything: to ensure thread-safe access to an inherently not thread-safe collection you have to cooperate with the framework by acquiring the same lock from your background threads when the collection is about to be modified.
Therefore the steps required for correct operation are:
1. Decide what kind of locking you will be using
This will determine which overload of EnableCollectionSynchronization
must be used. Most of the time a simple lock
statement will suffice so this overload is the standard choice, but if you are using some fancy synchronization mechanism there is also support for custom locks.
2. Create the collection and enable synchronization
Depending on the chosen lock mechanism, call the appropriate overload on the UI thread. If using a standard lock
statement you need to provide the lock object as an argument. If using custom synchronization you need to provide a CollectionSynchronizationCallback
delegate and a context object (which can be null
). When invoked, this delegate must acquire your custom lock, invoke the Action
passed to it and release the lock before returning.
3. Cooperate by locking the collection before modifying it
You must also lock the collection using the same mechanism when you are about to modify it yourself; do this with lock()
on the same lock object passed to EnableCollectionSynchronization
in the simple scenario, or with the same custom sync mechanism in the custom scenario.
Best Solution
The ObservableCollection has no way of knowing if you make changes to the objects it contains - if you want to be notified when those objects change then you have to make those objects observable as well (for example by having those objects implement INotifyPropertyChanged)