Cannot change ObservableCollection during a CollectionChanged event

aw04 picture aw04 · Jun 6, 2013 · Viewed 10.4k times · Source

I have a CollectionChanged event that is tied to an ObservableCollection. This CollectionChanged event then calls another function which is intended to update another collection (of the same type) with an item from the original collection. I have read other posts on the "Cannot change ObservableCollection during a CollectionChanged event" and I understand completely why it is frowned upon to modify a collection inside of a CollectionChanged event and why this can result in a circular reference... but in this particular case I am not modifying the original collection, I'm only adding an Item from it to an unrelated collection.

So to my question.. is there anything wrong with what I am doing? I don't see how adding an item from the collection with the event tied to it to another collection would fire the event again and create a circular reference (although please tell me if I'm wrong about this).

Also... is there any way around it? I read several posts advising to run this on a separate thread but when I try that I get the following error instead.

This type of CollectionView does not support changes to its SourceCollection
from a thread different from the Dispatcher thread.

I'm really just after a better understanding of what's going on here. Any advice would be much appreciated.

Edit

Simplified example as requested

void originalCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    update(originalCollection);
}

private void update(object parameter)
{
    foreach (var originalCollectionItem in parameter)
        newCollection.Add(originalCollectionItem);
}

Answer

Roberto Hernandez picture Roberto Hernandez · Jun 6, 2013

If you are using WindowsForms just make sure to use the Invoke method on the Form to keep the executing code on the Dispatcher's thread.

http://msdn.microsoft.com/en-us/library/system.windows.forms.form.invoke.aspx

Or, if using WPF use the Dispatcher class.

http://dotnetpattern.com/wpf-dispatcher