Wednesday, January 24, 2007

How to propagate changes across threads in WPF?

If you are reading this blog, I assume you already knew that in WPF,
it doesn't not support collection change notifications across threads.

Beatriz Costa has a great post about this (see http://www.beacosta.com/Archive/2006_09_01_bcosta_archive.html).

Kent (http://www.newsalloy.c8/681/) has written a nice wrap class DispatchingNotifyingCollection to solve this problem. But unfortunately, his solution didn't work when used together with CollectionView because of a bug in CollectionView as mentioned in the following post http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1144125&SiteID=1. Also, his solution seems make it harder to solve the multi thread problems since different threads can change both the wrapped collection and DispatchingNotifyingCollection at the same time.

So how to fix the filter problems?
Inspired by Kent's code, here is my solution. I called it DispatchingObservableCollection.
It is simpler than Kent's solution and also works with the CollectionView filter.

This is my first post and hopefully someone will read it and find it useful. :)

public class DispatchingObservableCollection<Titem> : ObservableCollection<Titem>

{

private readonly Dispatcher _dispatcher;

public Dispatcher Dispatcher

{

get

{

return _dispatcher;

}

}

public DispatchingObservableCollection(Dispatcher dispatcher)

{

if (dispatcher == null)

{

throw new ArgumentNullException("dispatcher can not be null");

}

_dispatcher = dispatcher;

}

private delegate void OnCollectionChangedHandler(NotifyCollectionChangedEventArgs e);

protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)

{

if (_dispatcher.CheckAccess())

{

base.OnCollectionChanged(e);

}

else

{

_dispatcher.Invoke(DispatcherPriority.DataBind, new OnCollectionChangedHandler(base.OnCollectionChanged), e);

}

}

}