1

次のコードに問題があります。

AllAgents.CollectionChanged += (sender, e) =>
            {
                if (e.Action != NotifyCollectionChangedAction.Remove) return;

                foreach (var s in AllSnapshots)
                {
                    foreach (var stat in s.Stats.Where(stat => stat.Model.Agent == null))
                        s.Stats.Remove(stat);
                }
            };

もちろん、これは「コレクションが変更されました。列挙操作が実行されない可能性があります」をスローします。私にとって完全に理にかなっている例外。問題は、Model.Agent プロパティが null であるすべてのアイテムを ObservableCollection から削除するための最良の方法は何ですか? 私は他のソリューションにもオープンです。基本的に、Agent が AllAgents コレクションから削除された場合、その Agent を参照していた AllSnapshots.Stats コレクションからすべてのエントリを削除する必要があります。

4

4 に答える 4

4

このようなコレクションからアイテムを削除する最良の方法は、標準のforループ構造を使用して、コレクションを逆方向に反復処理することです。コレクションを反復処理するために列挙子に依存しなくなったため、ループに干渉することなく安全に変更できます。

逆に繰り返すことで、ループの過程で削除がインデックスに干渉するのを防ぎます。そうしないと、一部の要素が削除されなくなる可能性があります。

ObservableCollection<Stat> o = new ObservableCollection<Stat>();
for (int i = o.Count - 1; i >= 0; i--) {
    if (o[i] == null) 
        o.RemoveAt(i);                
}
于 2012-09-12T16:36:35.773 に答える
1

問題は、反復して削除し、もう一度反復しようとしていることです。ObservableCollectionこれは、削除された要素を追跡しないため、サポートされていません。

foreachyourを、変更されないコレクションに依存しない標準の数値化されたものに置き換えます。それだけです。

この解決策は、別のリストを作成するために追加のメモリを使用しないという点で、Sam I am reply を延期します (要素の数が十分に大きい場合、これはかなり高価になる可能性があります)。

于 2012-09-12T16:33:52.933 に答える
0

私がおそらく行うことは、削除する統計のリストを生成し、個別の foreach ループでそれらをすべて削除することです

foreach (var s in AllSnapshots)
{
    list<object> stats = new list<object> 
   //if this doesn't work i'll leave it up to you to look up how to list a generic type

    foreach (var stat in s.Stats.Where(stat => stat.Model.Agent == null))
        stats.add(stat);

    foreach(var stat in stats)
        s.Stats.Remove(stat);
}
于 2012-09-12T16:30:32.343 に答える
0

各スナップショットの統計数がかなり少ない場合は、おそらく次のようにします。

foreach(var s in AllSnapShots)
{
    s.Stats = new ObservableCollection<Stats>(s.Where(stat =>stat.Model.Agent != null));
}

したがって、nullではない要素を含む新しいコレクションが作成されます。ただし、統計のリストがかなり大きい場合は、次のようにすることもできます。

List<WhateverYourCollectionWasOf> statsToDelete;

foreach(var s in AllSnapShots)
{
    statsToDelete.AddRange(s.Stats.Where(stat => stat.Model.Agent == null));

    foreach (var stat in statsToDelete)
    {
         s.Stats.Remove(stat);
    }
}

または、もう少し将来性のあるものにしたい場合は、この種のことを行う拡張メソッドを作成できます。

public static class ExtensionMethods
{
    public static ObservableCollection<T> RemoveAll<T>(
        this ObservableCollection<T> collection, Func<T, bool> predicate)
    {
        List<T> collectionAsList = collection.ToList();
        List<T> itemsToRemove = collection.Where(predicate);            
        collectionAsList.RemoveAll(i => itemsToRemove.Contains(i));
        collection = new ObservableCollection<T>(collectionAsList);
        return collection;
    }
}

次に、次のように呼び出されます。

foreach(var s in AllSnapShots)
{
    s.Stats.RemoveAll(stat => stat.Model.Agent == null);
}
于 2012-09-12T16:40:52.090 に答える