RemoveAll for ObservableCollections?

时间:2011-02-25 14:41:54

标签: c# observablecollection removeall

我正在寻找Linq方式(如List的RemoveAll方法),它可以从我的ObservableCollection中删除所选项目。

我太新了,无法为自己创建扩展方法。有没有办法从ObservableCollection中删除传递Lambda表达式的项目?

7 个答案:

答案 0 :(得分:88)

我不知道只删除所选项目的方法。但是创建扩展方法很简单:

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);

答案 1 :(得分:39)

向后迭代应该比在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);
            }
        }
    }
}

答案 2 :(得分:13)

单线程的实现怎么样?

String target_url = "http://www.google.com";
Uri uri = Uri.parse(target_url);
NdefRecord recordNFC = NdefRecord.createUri(uri);
NdefMessage message = new NdefMessage(recordNFC);

- 编辑 -

很抱歉,是的,您需要在中间强制使用ToList()来强制评估上半部分,因为默认情况下LINQ会进行延迟评估。

答案 3 :(得分:9)

这里提出的每个解决方案使用例程逐个删除项目都有一个错误。想象一下,在可观察集合中有很多项目,可以说是10.000项。然后你想要删除符合某些条件的项目。

如果您使用来自Daniel Hilgarth的解决方案并致电:c.Remove(x => x.IsSelected);并且有例如要移除的3000个项目,则建议的解决方案将通知每个项目移除。这是因为Remove(item)的内部实施会通知该更改。这将在删除过程中为每个项目调用。

因此,我创建了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));

答案 4 :(得分:0)

无法将表达式传递给ObservableCollection以删除匹配项,与通用列表的方式相同。 ObservableCollection一次添加和删除一个项目。

为了做到这一点,你必须创建自己的INotifyCollectionChanged实现,或者当你提到创建扩展方法时。

答案 5 :(得分:0)

这是我的扩展方法解决方案版本,只是对接受的答案略有不同,但其优点是返回的计数是基于已确认从集合中删除项目:

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);
    }
}

答案 6 :(得分:0)

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);
}