In our app, we have a TreeView bound to an ObservableCollection, which we regularly update in a background thread, requesting data from our storage. It works perfectly!
Whoops. I was mis-informed =))
Right, we're actually subclassing the ObservableCollection<T>
and override the OnCollectionChanged
method to avoid the UI crossthreading exception. We're using this solution:
public class MTObservableCollection<T> : ObservableCollection<T>
{
public override event NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
var eh = CollectionChanged;
if (eh != null)
{
Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
let dpo = nh.Target as DispatcherObject
where dpo != null
select dpo.Dispatcher).FirstOrDefault();
if (dispatcher != null && dispatcher.CheckAccess() == false)
{
dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
}
else
{
foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
nh.Invoke(this, e);
}
}
}
}
Without that override you'd get an exception like that
System.NotSupportedException : This
type of CollectionView does not
support changes to its
SourceCollection from a thread
different from the Dispatcher thread.
Now the only problem we have is the selected item position, in some cases if the currently selected item is deleted from the collection the TreeView moves the selection to the next item (which causes some other unnecessary UI actions in our app). But that's a small issue.