Каждое из предложенных здесь решений, в котором используется процедура удаления элемента одно за другим, имеет одну ошибку.Представьте, что у вас есть много предметов в наблюдаемой коллекции, скажем, 10.000 предметов.Затем вы хотите удалить элементы, которые удовлетворяют некоторым условиям.
Если вы используете решение из Daniel Hilgarth
и звоните: c.Remove(x => x.IsSelected);
и, например, необходимо удалить 3000 элементов, предлагаемое решение будет уведомлять о каждом удалении элемента.Это связано с тем, что внутренняя реализация Remove(item)
уведомляет об этом изменении.И это будет вызываться для каждого из 3000 элементов в процессе удаления.
Так что вместо этого я создал потомка ObservableCollection и добавил новый метод RemoveAll(predicate)
[Serializable]
public class ObservableCollectionExt<T> : ObservableCollection<T>
{
public void RemoveAll(Predicate<T> predicate)
{
CheckReentrancy();
List<T> itemsToRemove = Items.Where(x => predicate(x)).ToList();
itemsToRemove.ForEach(item => Items.Remove(item));
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
Интересная строка - itemsToRemove.ForEach(item => Items.Remove(item));
.Прямой вызов Items.Remove(item)
не будет уведомлять об удаленном элементе.
Вместо этого после удаления необходимых элементов об изменениях сразу сообщается по телефонам:
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));