RemoveAll为ObservableCollections?
我正在寻找Linq的方式(像RemoveAll方法列表),可以从我的ObservableCollection中删除选定的项目。
我太新,无法为自己创build扩展方法。 有没有什么办法从ObservableCollection中移除传递Lambdaexpression式的项目?
我不知道只能删除所选项目的方法。 但创build一个扩展方法是直接的:
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; } }
这将删除ObservableCollection
中与条件匹配的所有项目。 你可以这样称呼它:
var c = new ObservableCollection<SelectableItem>(); c.Remove(x => x.IsSelected);
在Daniel Hilgarth的例子中,迭代迭代应该比创build一个临时集合更有效率。
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); } } } }
这个单线程的实现呢?
observableCollection.Where(l => l.type == invalid).ToList().All(i => observableCollection.Remove(i))
– 编辑 –
对不起,你需要中间的ToList()强制前半部分进行评估,因为LINQ默认情况下是懒惰评估。
这里提出的每个使用例程逐个删除项目的解决scheme都有一个错误。 想象一下,你有很多可观察的物品,比如说10.000个物品。 然后你想删除符合条件的物品。
如果您使用Daniel Hilgarth
解决scheme,请调用: Daniel Hilgarth
c.Remove(x => x.IsSelected);
并且有例如3000个被移除的项目,build议的解决scheme将通知关于每个项目移除。 这是由于Remove(item)
内部实现通知有关此更改的事实。 这将被删除过程中的3000个项目的每个要求。
所以,而不是我创buildObservableCollection的后代,并添加新的方法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));
没有办法将expression式传递给ObservableCollection来移除匹配的项目,就像通用列表一样。 ObservableCollection一次添加和删除一个项目。
您将不得不创build您自己的INotifyCollectionChanged实现,以便执行此操作,或者像您提到的那样创build一个扩展方法。
这是我的扩展方法解决scheme的版本,这只是接受的答案的一个小的变化,但有一个优点,返回的计数是基于确认从集合中删除项目:
public static class ObservableCollectionExtensionMethods { /// <summary> /// Extends ObservableCollection adding a RemoveAll method to remove elements based on a boolean condition function /// </summary> /// <typeparam name="T">The type contained by the collection</typeparam> /// <param name="observableCollection">The ObservableCollection</param> /// <param name="condition">A function that evaluates to true for elements that should be removed</param> /// <returns>The number of elements removed</returns> public static int RemoveAll<T>(this ObservableCollection<T> observableCollection, Func<T, bool> condition) { // Find all elements satisfying the condition, ie that will be removed var toRemove = observableCollection .Where(condition) .ToList(); // Remove the elements from the original collection, using the Count method to iterate through the list, // incrementing the count whenever there's a successful removal return toRemove.Count(observableCollection.Remove); } }