RemoveAll for ObservableCollections?
How about this implementation for a one-liner?
observableCollection.Where(l => l.type == invalid).ToList().All(i => observableCollection.Remove(i))
-- Edit --
Sorry, yes, you need a ToList() in the middle to force the first half to evaluate, as LINQ does lazy evaluation by default.
Each of solution proposed here which uses routine to remove item one by one has one fault. Imagine that you have many items in observable collection, lets say 10.000 items. Then you want to remove items which meets some condition.
If you use solution from Daniel Hilgarth and call: c.Remove(x => x.IsSelected);
and there are for example 3000 items to be removed, proposed solution will notify about each item removal. This is due to fact that internal implementation of Remove(item)
notify about that change. And this will be called for each of 3000 items in removal process.
So instead of this i created descendant of ObservableCollection and add new method 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));
}
}
Interesting line is itemsToRemove.ForEach(item => Items.Remove(item));
. Calling directly Items.Remove(item)
will not notify about item removed.
Instead after removal of required items, changes are notified at once by calls:
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
I am not aware of a way to remove only the selected items. But creating an extension method is straight forward:
public static class ExtensionMethods
{
public static int Remove<T>(
this ObservableCollection<T> coll, Func<T, bool> condition)
{
var itemsToRemove = coll.Where(condition).ToList();
foreach (var itemToRemove in itemsToRemove)
{
coll.Remove(itemToRemove);
}
return itemsToRemove.Count;
}
}
This removes all items from the ObservableCollection
that match the condition. You can call it like that:
var c = new ObservableCollection<SelectableItem>();
c.Remove(x => x.IsSelected);
Iterating backwards should be more efficient than creating a temporary collection as in Daniel Hilgarth's example.
public static class ObservableCollectionExtensions
{
public static void RemoveAll<T>(this ObservableCollection<T> collection,
Func<T, bool> condition)
{
for (int i = collection.Count - 1; i >= 0; i--)
{
if (condition(collection[i]))
{
collection.RemoveAt(i);
}
}
}
}