Удалить элемент из ObservableCollection в обработчике события CollectionChanged - PullRequest
11 голосов
/ 16 марта 2012

Я надеюсь, что смогу отклонить некоторые элементы после их добавления в коллекцию ObservableCollection.Я не могу создать подкласс ObservableCollection или использовать какое-либо представление, поэтому я ограничен использованием одного определенного обработчика событий (CollectionChanged) для выполнения .Remove () над запрещенными элементами.Хорошо, если элементы существуют в течение короткого периода времени между событием, которое вызывается, а затем обрабатывается;предметы не должны сохраняться в коллекции.Вызов .Remove () в обработчике события CollectionChanged не разрешен.Во время выполнения .NET генерирует исключение InvalidOperationException:

"Невозможно изменить ObservableCollection во время события CollectionChanged."

Лично я считаю, что .NET должен разрешить мне.Если я создаю бесконечный цикл, это моя собственная ошибка.

Код, который я хотел бы использовать, выглядел бы так:

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

Я не уверен, какие варианты у меня есть.Использование диспетчера не похоже на работу.Инициирование другого события и помещение вызова .Remove в другой обработчик - единственная другая опция, которая приходит на ум.

Ответы [ 4 ]

17 голосов
/ 17 марта 2012

Оформить Распространенные ошибки с использованием наблюдаемой коллекции .

Сказав это, если вы все еще хотите пойти по этому пути - вы можете раскрутить новую тему

13 голосов
/ 17 марта 2012

если вы действительно хотите изменить коллекцию, то вы захотите перебрать копию коллекции.это потому, что вы пытаетесь изменить коллекцию в цикле foreach, что вызывает у вас горе.

пример

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

}

при этом я согласен с Анурагом, что вы не должны делать этот типвещи с наблюдаемой коллекцией и, конечно, не внутри события CollectionChanged.

0 голосов
/ 11 декабря 2018

Использовал это в oncollection изменилось, и это работает (пример WPF и MVVM):

new System.Threading.Thread(t =>
{
  Application.Current.Dispatcher.Invoke((Action)delegate
  {
    OnHoldMessages.Add(_selectedOnHoldMessage);
    RaisePropertyChanged(propertyName: "OnHoldMessages");
  });
}).Start();
0 голосов
/ 30 октября 2017

используйте ToList() для перебора списка.

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