递归地折叠自定义UserControl中父节点的所有子节点

时间:2014-06-13 04:17:59

标签: c# winforms user-controls treeview nodes

我实际上有一个类似于TreeView的自定义UserControl。它唯一缺少的是来自TreeView的CollapseAll()方法,因此我要求a)找到CollapseAll方法的源代码,以便我可以复制它,或者b)手动(并递归地)遍历所选节点的所有子节点并折叠它们。

这是我当前的崩溃方法:

private void OnNodeCollapsed(TreeNode node) {
    foreach(FileSystemNode n in node.Nodes) {
        if(n.NodeType != FileSystemNodeType.Computer && n.NodeType != FileSystemNodeType.Drive) {
            if(n.Nodes.Count > 0) {
                n.Nodes.Clear();
            }
        }
    }

    foreach(TreeNode child in node.Nodes) {
        // and this is where I lose it
    }
}

我只想折叠子节点,而不是整个树。有没有办法做到这一点?

这是一个很好的解决方案:Recursion with yield return elements order in tree

1 个答案:

答案 0 :(得分:2)

您可以为自定义控件添加这样的扩展名,并使用以下展开/折叠方法

public static class TreeViewExt
{
     public static void ExpandRecursively(this ItemsControl itemsControl, bool expand, int levelDepth)
    {
        int depth = levelDepth == int.MaxValue ? levelDepth : levelDepth - 1;
       TreeViewItem treeViewItem = itemsControl as TreeViewItem;
        if (treeViewItem != null)
            treeViewItem.IsExpanded = expand || levelDepth >= 0; // expand, or keep expanded when levelDepth >= 0
         if (levelDepth > 0 || !expand)
        {
            // get container generator of itemsControl
            ItemContainerGenerator itemContainerGenerator = itemsControl.ItemContainerGenerator;
             // if containers have already been generated, the subItems can be expanded/collapsed
            if (itemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
            {
                for (int i = itemsControl.Items.Count - 1; i >= 0; --i)
                {
                    ItemsControl childControl = itemContainerGenerator.ContainerFromIndex(i) as ItemsControl;
                    if (childControl != null)
                        childControl.ExpandRecursively(expand, depth);
                }
            } 
            else
            {
                EventHandler handler = null; // store in variable, so the handler can be detached
                handler = new EventHandler((s, e) =>
                {
                    if (itemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
                    {
                        for (int i = itemsControl.Items.Count - 1; i >= 0; --i)
                        {
                            ItemsControl childControl = itemContainerGenerator.ContainerFromIndex(i) as ItemsControl;
                            if (childControl != null)
                                childControl.ExpandRecursively(expand, depth);
                            itemContainerGenerator.StatusChanged -= handler; // detach
                        }
                    }
                });
                itemContainerGenerator.StatusChanged += handler; // attach
            }
        }
    }
}

完整代码:Treeview Recursive Expand/Collapse

修改

由于OP想要为WinForm UserControl执行此操作,您可以使用这样的方法遍历子控件,

private IEnumerable<Node> getAllNodesRecursively(Node subnode) 
{ 
    // Return the parent before its children
    yield return subnode; 

    foreach (Node node in subnode.Nodes) 
    {
        foreach(Node n in getAllNodesRecursively(node))
        {
            yield return n;
        }
    }
} 

Recursion with yield return elements order in tree