问题
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:
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
来源:https://stackoverflow.com/questions/24197633/recursively-collapse-all-child-nodes-of-parent-node-in-custom-usercontrol