尝试在树视图中设置所有节点检查状态 - 获取StackOverflowException

时间:2017-02-20 13:45:11

标签: c# winforms treeview

我在TreeView(trvP)中添加了一些节点。根元素的Tag属性设置为Root

我试图这样做,如果我检查根元素,所有其他节点将具有相同的状态。但是,执行以下代码会导致StackOverflowException

private void trvP_AfterCheck(object sender, TreeViewEventArgs e)
{
        if(e.Node.Tag.Equals("Root"))
        {
            var nodes = TreeViewExtensions.GetAllNodes(e.Node.TreeView);
            foreach (TreeNode node in nodes)
                node.Checked = e.Node.Checked;
        }
}

GetAllNodes函数的代码:

public static List<TreeNode> GetAllNodes(this TreeView _trv)
{
        List<TreeNode> result = new List<TreeNode>();
        foreach (TreeNode child in _trv.Nodes)
        {
            result.AddRange(child.GetAllNodes());
        }
        return result;
}
public static List<TreeNode> GetAllNodes(this TreeNode _trn)
    {
        List<TreeNode> result = new List<TreeNode>();
        result.Add(_trn);
        foreach (TreeNode child in _trn.Nodes)
        {
            result.AddRange(child.GetAllNodes());
        }
        return result;
    }

从调试开始,它一遍又一遍地运行var nodes = ...代码,而只在foreach循环(根节点)内设置单个节点。但是,nodes是具有正确值的正确节点列表。

我无法理解为什么这种情况反复执行会导致异常。

2 个答案:

答案 0 :(得分:1)

GetAllNodes()的{​​{1}}扩展名从第一个子节点开始,并为此TreeView调用GetAllNodes()扩展名。

TreeNode扩展程序会将此GetAllNodes()添加到结果列表中 因此,列表中的第一个 TreeNode再次是根节点

这意味着在行

TreeNode

您设置了根节点node.Checked = e.Node.Checked; 属性,该属性又为此根节点再次调用处理程序Checked 。这现在无限重复,充斥你的筹码并提升trvP_AfterCheck

要解决此问题,请过滤掉根节点:

StackOverflowException
顺便说一下:扩展方法的优点在于你可以在语法上调用它们,就好像它们是instanc方法一样。所以这个

private void trvP_AfterCheck(object sender, TreeViewEventArgs e)
{
        if(e.Node.Tag.Equals("Root"))
        {
            var nodes = e.Node.TreeView.GetAllNodes();
            foreach (TreeNode node in nodes)
            {
                if (node == e.Node) continue; // don't do it for root again
                node.Checked = e.Node.Checked;
            }
        }
}

可以简单地写成

var nodes = TreeViewExtensions.GetAllNodes(e.Node.TreeView)

答案 1 :(得分:0)

你正在递归地调用GetAllNodes,这使得循环进入无限状态..

    public static List<TreeNode> GetAllNodes(this TreeView _trv)
{
        List<TreeNode> result = new List<TreeNode>();
        foreach (TreeNode child in _trv.Nodes)
        {
            result.Add(child);
        }
        return result;
}

当你已经将treenode循环到_trv.Nodes时,你需要将当前节点添加到foreach语句中。