0
votes

I actually have a custom-built UserControl similar to a TreeView. The only thing it's missing is the CollapseAll() method from a TreeView, so I'm looking to either a) find the source code for the CollapseAll method so I can copy it, or b) manually (and recursively) iterate through all the child nodes of a selected node and collapse them.

Here is my current collapse method:

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
    }
}

I only want to collapse child nodes, not the whole tree. Is there a way of doing that?

A good solution is this: Recursion with yield return elements order in tree.

1
Post your code for the UserControlSajeetharan
@Sajeetharan Here is the code for the UserControl itself: pastebin.com/P9EpjjCX It's based on this: code.msdn.microsoft.com/windowsdesktop/…Abluescarab

1 Answers

2
votes

You could add an extension like this for your Custom Control, and make use of the following Expand/Collapse Method

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
            }
        }
    }
}

Complete Code: Treeview Recursive Expand/Collapse

EDIT:

Since OP wanted to do it for WinForm UserControl, You could loop through the Child Controls using the method like this,

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