Daniel
Daniel

Reputation: 1114

Remove selected items from Listbox (ObservableCollection)

I am trying to remove selected items in a ListBox which is bound to ObservableCollection.

var selectedFiles = MyList.SelectedItems;
foreach (cListEntry item in selectedFiles)
{
   _myList.Remove(item);
}

"Collection was modified; enumeration operation may not execute"

What is the proper way of doing this?

Upvotes: 3

Views: 3170

Answers (2)

vapcguy
vapcguy

Reputation: 7537

This happens when trying to modify an ObservableCollection<T> that is bound to a ListBox, for example. This is how you deal with that:

ObservableCollection<Employee> itemsToRemove = new ObservableCollection<Employee>();

foreach (Employee item in lsbxNames.SelectedItems)
{
    itemsToRemove.Add(item);
}
foreach (Employee item in itemsToRemove)
{
    ((ObservableCollection<Employee>)lsbxNames.ItemsSource).Remove(item);
}
  1. Create a new ObservableCollection<T> called itemsToRemove, with the same T as your collection you are trying to modify.
  2. Iterate through your nodes of SelectedItems in your ListBox. Add them to itemsToRemove.
  3. Iterate through itemsToRemove. Cast the ListBox ItemsSource to an ObservableCollection<T> and remove the matches in itemsToRemove from it.

Reference: http://docs.telerik.com/devtools/wpf/controls/radgridview/managing-data/deleting-entry

So this would mean you should be able to do this:

ObservableCollection<cListEntry> itemsToRemove = new ObservableCollection<cListEntry>();

foreach (cListEntry item in MyList.SelectedItems)
{
    itemsToRemove.Add(item);
}
foreach (cListEntry item in itemsToRemove)
{
    ((ObservableCollection<cListEntry>)MyList.ItemsSource).Remove(item);
}

I'm not sure what _myList is, but you don't need to modify it. Just go directly to the ListBox.

Upvotes: 1

Rohit Vats
Rohit Vats

Reputation: 81243

You can't modify the collection while enumerating it as evident from the exception itself.

Explanation:

When you remove item from ObservableCollection, MyList.SelectedItems gets update since ObservableCollecton implement INotifyCollectionChanged. Now, selectedFiles is pointing to same reference which results in modifying it.

Solution

Instead create a new list and enumerate over that so that any change in ObservableCollection doesn't reflect back to list which you are enumerating. This will work:

var selectedFiles = MyList.SelectedItems.Cast<object>().ToList();
foreach (cListEntry item in selectedFiles)
{
   _myList.Remove(item);
}

Upvotes: 6

Related Questions