Reputation: 25
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.
Upvotes: 0
Views: 1871
Reputation: 1469
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);
}
}
}
Upvotes: 3
Reputation: 49965
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);
}
Upvotes: 0