75

ObservableCollectionから選択したアイテムを削除できるLinqメソッド(ListのRemoveAllメソッドなど)を探しています。

私は自分で拡張メソッドを作成するには新しすぎます。Lambda式を渡してObservableCollectionからアイテムを削除する方法はありますか?

4

7 に答える 7

106

選択した項目のみを削除する方法を知りません。ただし、拡張メソッドの作成は簡単です。

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);
于 2011-02-25T14:52:48.567 に答える
51

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);
            }
        }
    }
}
于 2013-03-07T17:00:13.083 に答える
15

ワンライナーのこの実装はどうですか?

observableCollection.Where(l => l.type == invalid).ToList().All(i => observableCollection.Remove(i))

- 編集 -

申し訳ありませんが、LINQ は既定で遅延評価を行うため、前半を強制的に評価するには、途中に ToList() が必要です。

于 2015-11-13T15:13:40.033 に答える
10

ここで提案されているルーチンを使用してアイテムを 1 つずつ削除するソリューションには、それぞれ 1 つの欠点があります。観察可能なコレクションに多くのアイテムがあると想像してください。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));
于 2014-10-23T07:43:53.247 に答える
1

一般的なリストと同じように、ObservableCollection に式を渡して一致するアイテムを削除する方法はありません。ObservableCollection は一度に 1 つのアイテムを追加および削除します。

これを行うには、INotifyCollectionChanged の独自の実装を作成するか、言及したように拡張メソッドを作成する必要があります。

于 2011-02-25T14:52:55.863 に答える