views:

63

answers:

2

I need to raise the CollectionChanged event of an ObservableCollection on the UI thread.

I have seen different approaches ranging from a wrapper class to custom implementation of the relevant interface.

Is there any simple way to override INotifyCollectionChanged on an ObservableCollection to accomplish this?

Thanks.

A: 

The simplest way to do this is to just ensure that you add/remove items from the collection on the UI thread. This can be done with a short function like this:

private void AddItemsToCollection(List<whatever> newItems)
{
    if (this.Dispatcher.CheckAccess()) 
    {
        newItems.ForEach(x => myObservableCollection.Add(x));
    }
    else 
        this.Dispatcher.BeginInvoke(new Action<List<whatever>>(AddItemsToCollection), newItems);
}
slugster
Thanks, but I have a lot going on in the background (like async load operations etc.). Any other ideas?
Derick
I will give your suggestion a go.
Derick
@Derick - that is the beauty of that function - it doesn't matter what thread you call it on, it will marshall itself onto the UI thread (if not already there) before it does the update.
slugster
@Slugster: It seems I can call this from Mars and it still works. Thanks dude!
Derick
+1  A: 

You could subclass the ObservableCollection and override the OnCollectionChanged and OnPropertyChanged methods to marshall the event back to the UI thread using the correspending Dispatcher.

public class DispatcherObservableCollection<T> : ObservableCollection<T>
{
    Dispatcher _dispatcher;
    public DispatcherObservableCollection(Dispatcher dispatcher)
    {
        if (dispatcher == null)
            throw new ArgumentNullException("dispatcher");
        _dispatcher = dispatcher;
    }

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (!_dispatcher.CheckAccess())
        {
            _dispatcher.Invoke(
                new Action<PropertyChangedEventArgs>(base.OnPropertyChanged), e);
        }
        else
        {
            base.OnPropertyChanged(e);
        }
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (!_dispatcher.CheckAccess())
        {
            _dispatcher.Invoke(
                new Action<NotifyCollectionChangedEventArgs>(base.OnCollectionChanged), e);
        }
        else
        {
            base.OnCollectionChanged(e);
        }
    }
}
Islam Ibrahim