7

TreeView内のすべてのノードを簡単に反復処理し、それらの.Checkedプロパティを調べてから、チェックされたすべてのノードを削除するにはどうすればよいでしょうか。

簡単に思えますが、反復しているコレクションを変更して、「foreach」ループの可能性を排除することは想定されていません。(.Nodes.Remove呼び出しはコレクションを変更しています。)これを試みると、.Checkedノードの約半分だけが削除されます。

2つのパスを使用する場合でも、最初に一時インデックスのリストを作成し、次に2番目のパスでインデックスごとに削除します。削除するたびにインデックスが変更され、インデックスリストの整合性が無効になります。

それで、これを行うための最も効率的な方法は何ですか?

見た目は良いが、実際には.Checkedノードの約半分しか削除されないコードの例を次に示します。

            foreach (TreeNode parent in treeView.Nodes)
            {
                if (parent.Checked)
                {
                    treeView.Nodes.Remove(parent);
                }
                else
                {
                    foreach (TreeNode child in parent.Nodes)
                    {
                        if (child.Checked) parent.Nodes.Remove(child);
                    }
                }
            }

(はい、意図は2レベルの深さのツリーからノードをプルーニングすることだけです。)

4

4 に答える 4

8

ノードを逆方向に歩いてみてください。そうすれば、インデックスがノードサイズを超えて増加することはありません。

for(int ndx = nodes.Count; ndx> 0; ndx--)
{{
  TreeNodeノード=ノード[ndx-1];
  if(node.Checked)
  {{
     ノード.Remove(ノード);
  }
   //子ノードを再帰します...
}
于 2009-05-05T15:17:43.850 に答える
7

これにより、ノードを列挙した後にノードが削除され、ノードのn層に再帰的に使用できます。

void RemoveCheckedNodes(TreeNodeCollection nodes)
{
    List<TreeNode> checkedNodes = new List<TreeNode>();

    foreach (TreeNode node in nodes)
    {
        if (node.Checked)
        {
            checkedNodes.Add(node);
        }
        else
        {
            RemoveCheckedNodes(nodes.ChildNodes);
        }
    }

    foreach (TreeNode checkedNode in checkedNodes)
    {
        nodes.Remove(checkedNode);
    }
}
于 2009-05-05T15:22:10.847 に答える
3

効率的に実行したい場合は、チェックされたノードをチェックしながら追跡する必要があります。チェックされたツリーノードをリストに保存します(チェックされていないので削除します)。

一意のキーと追跡するノードがたくさんある場合は、辞書も検討してください。しかし、10-50しか扱っていない場合、おそらく大きな違いはありません。

次に、ツリー全体をループする代わりに、(小さい)ノードのリストをループします。

于 2009-05-05T15:35:17.240 に答える
1

繰り返しながら、チェックされていないアイテムの新しいリストを作成し、ツリービューをその新しいリストに再バインドすることができます(古いリストを破棄します)。

于 2009-05-05T15:17:24.243 に答える