我正在寻找可以从我的ObservableCollection中删除所选项目的Linq方法(例如List的RemoveAll方法)。
我太新了,无法为自己创建扩展方法。我有什么办法可以通过Lambda表达式从ObservableCollection中删除项目?
我正在寻找可以从我的ObservableCollection中删除所选项目的Linq方法(例如List的RemoveAll方法)。
我太新了,无法为自己创建扩展方法。我有什么办法可以通过Lambda表达式从ObservableCollection中删除项目?
Answers:
我不知道仅删除所选项目的方法。但是创建扩展方法很简单:
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);
itemstoRemove
不会,垃圾收集器会声明。
List<T>
返回计数,因此遵循该方法将是一个好主意。我相应地更改了答案。感谢您的意见。
向后迭代比在Daniel Hilgarth的示例中创建临时集合要有效。
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默认情况下会进行惰性评估。
List<T>.ForEach
不要使用All
。我认为这All(...)
是之前ToList()
添加的人工产物。
此处提出的使用例程逐项删除项目的每种解决方案都有一个故障。想象一下,您有许多可观察的项目,假设有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));
这是我的扩展方法解决方案的版本,仅对可接受的答案稍有变化,但具有的优势是,返回的计数基于已确认从集合中移除该项目:
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, i.e. 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);
}
}
ObservableCollection<AppVariable<G>> _appVariables = new new ObservableCollection<AppVariable<G>>();
var temp = AppRepository.AppVariables.Where(i => i.IsChecked == true).OrderByDescending(k=>k.Index);
foreach (var i in temp)
{
AppRepository.AppVariables.RemoveAt(i.Index);
}