如何在树视图中修复 foreach

How to fix foreach in treeview

我正在通过本教程执行我的树视图删除按钮事件: Youtube tutorial

我做了所有与教程中所示相同的事情:

private void button2_Click(object sender, EventArgs e)
        {
            RemoveCheckedNodes(treeView1.Nodes);
        }
        List<TreeNode> checkedNodes = new List<TreeNode>();

        void RemoveCheckedNodes(TreeNodeCollection nodes)
        {
            foreach (TreeNode node in nodes )
            {
                if (node.Checked)
                {
                    checkedNodes.Add(node);
                }
                else
                {
                    RemoveCheckedNodes(node.Nodes);
                }
                foreach (TreeNode checkedNode in checkedNodes)
                {
                    nodes.Remove(checkedNode);
                }
            }
        }

但是它在 foreach 中抛出错误:'System.NullReferenceException' 类型的未处理异常发生在 project_TreeView.exe

同样很奇怪的是,一切都适用于最后一个节点。所以我猜我的 foreach 不工作。有什么想法吗?

EDIT: So I found this is working, If I am removing last and before last node. How to make it, that I could remove any node(For example first and last)

谢谢。

如果我是对的,foreach 循环是只读迭代,我认为您应该使用 for 循环从集合中删除对象。

第二个 foreach 应该在第一个之外。

private void button2_Click(object sender, EventArgs e)
    {
        RemoveCheckedNodes(treeView1.Nodes);
    }
    List<TreeNode> checkedNodes = new List<TreeNode>();

    void RemoveCheckedNodes(TreeNodeCollection nodes)
    {
        foreach (TreeNode node in nodes )
        {
            if (node.Checked)
            {
                checkedNodes.Add(node);
            }
            else
            {
                RemoveCheckedNodes(node.Nodes);
            }
        }
        foreach (TreeNode checkedNode in checkedNodes)
        {
            nodes.Remove(checkedNode);
        }
    }

我会将已检查节点的搜索移动到一个单独的方法中。所以你先找到所有节点,然后删除它们。

目前您的代码会多次尝试删除相同的节点(在 RemoveCheckedNodes 的每次递归调用中,即使您将循环移出另一个循环,删除仍会被多次调用。

我还会为 checkedNodes 列表使用局部变量。您的列表未清除,因此它将包含已删除的项目。

如果您的问题是查找或删除节点,这种方式更易于调试:

  private void button2_Click(object sender, EventArgs e)
  {
      RemoveChecked(treeView1.Nodes);
  }

  void RemoveChecked(TreeNodeCollection nodes)
  {
      foreach (TreeNode checkedNode in FindCheckedNodes(nodes))
      {
        nodes.Remove(checkedNode);
      }
  }


  private List<TreeNode> FindCheckedNodes(TreeNodeCollection nodes)
  {
      List<TreeNode> checkedNodes = new List<TreeNode>()
      foreach (TreeNode node in nodes)
      {
        if (node.Checked)
        {
          checkedNodes.Add(node);
        }
        else
        {
          // find checked childs        
          checkedNodes.AddRange(FindCheckedNodes(node.Nodes));               
        }
      }
      return checkedNodes;
  }