Remove item from ObservableCollection in CollectionChanged event handler

I hope I can reject some elements after adding them to the ObservableCollection. I cannot subclass ObservableCollection or use any kind, so I seem to be limited to using one event handler (CollectionChanged) to execute .Remove () on forbidden elements. It is good if the elements exist for a short period between the event raised and processed; items should simply not be stored in the collection. Calling .Remove () inside the CollectionChanged event handler does not seem valid. When starting, .NET throws an InvalidOperationException:

"Cannot change ObservableCollection during CollectionChanged event."

Personally, I believe that .NET should let me do this. If I create an infinite loop, this is my own mistake.

The code I would like to use would look like this:

myCollection.CollectionChanged += (sender, args) => { if (args.Action == NotifyCollectionChangedAction.Remove) return; foreach (var itm in myCollection) { if (itm.name == "Fred") myCollection.Remove(itm); } } 

I'm not sure what my options are. Using dispatcher does not work. Triggering another event and placing the .Remove call in another handler is the only other option that comes to mind.

+8
source share
4 answers

Note Common Errors Using the Observable Collection .

Having said that, if you still want to go this route, you can unscrew the new thread

+16
source

if you really want to change the collection that you are going to iterate over a copy of the collection. because you are trying to change the collection in the foreach loop, which makes you sad.

Example

 var copy = new ObservableCollection<YourType>(collection) foreach(var item in copy) { if(item.Name == "Fred") { collection.Remove(item); } } 

which said, I agree with Anurag that you should not do such things with an observable collection and, of course, not inside the CollectionChanged event.

+12
source

use ToList() to ToList() over the list.

 foreach(var item in collection.ToList()) { if(item.Name == "Fred") { collection.Remove(item); } } 
0
source

Used this in the oncollection has changed, and it works:

 new System.Threading.Thread(t => { Application.Current.Dispatcher.Invoke((Action)delegate { OnHoldMessages.Add(_selectedOnHoldMessage); RaisePropertyChanged(propertyName: "OnHoldMessages"); }); }).Start(); 
0
source

All Articles