Reputation: 346
Hello I currently have a TreeView
with the following structure:
Child
The TreeView structure can basically have NRootNodes - NChildren and the NRootNodes can have NRoots and NChildren so basically just like Windows Explorer Window.
My current issue that I have is that I have to get all the Parents or Root, in this case Roots / RootN and then I have to Remove all of their Child Nodes, in this case Child / ChildN. In the end I have to have only the Parent Nodes and then Clone them so I can move them to a different location within the TreeView.
RootNodes have a unique Tag - Folder and ChildNodes have another unique Tag - Calculations, as I have said earlier, I have to get rid of all Calculations in the Selected Node so only the Structure of that Selected Node will Remain.
Basically in the end I have to have something like this:
I have a recursive method that "scans" the SelectedNode and gets all the Parents:
public List<TreeNode> CollectParentNodes(TreeNodeCollection parentCollection, List<TreeNode> collectedNodes)
{
foreach (TreeNode node in parentCollection)
{
if (!collectedNodes.Contains(node.Parent))
{
collectedNodes.Add(node.Parent);
parentNodeAdded = true;
}
if (node.Level != 0 && node.Tag.ToString() != Enumerations.NodeType.Calculation.ToString())
collectedNodes.Add(node);
if (node.Nodes.Count > 0)
CollectParentNodes(node.Nodes, collectedNodes);
}
parentNodeAdded = false;
return collectedNodes;
}
In the end I have a List that will hold all the Parents but the problem I'm facing is that that Parents also contain their descendents, in this case the Calculations
I have searched Google and StackOverFlow but I could not find anything of help, I appologize in advance if this has already been answered.
Thank you.
Upvotes: 0
Views: 6814
Reputation: 125217
You can create an extension method GetAllNodes for TreeView that return List
Remember using using System.Linq;
at top of your code
public static class Extensions
{
public static List<TreeNode> GetAllNodes(this TreeView tree)
{
var firstLevelNodes = tree.Nodes.Cast<TreeNode>();
return firstLevelNodes.SelectMany(x => GetNodes(x)).Concat(firstLevelNodes).ToList();
}
private static IEnumerable<TreeNode> GetNodes(TreeNode node)
{
var nodes = node.Nodes.Cast<TreeNode>();
return nodes.SelectMany(x => GetNodes(x)).Concat(nodes);
}
}
And the usage will be:
var result = this.treeView1.GetAllNodes().Where(x => x.Tag == "FOLDER").ToList();
Remember to add namespace of your extensions class at top of your code wherever you want to use it.
As an example you can set All nodes with tag of Folder to be in Red forecolor:
var result = this.treeView1.GetAllNodes().Where(x => (x.Tag as string) == "FOLDER").ToList();
result.ForEach(x => x.ForeColor = Color.Red);
And here is an Screenshot
Upvotes: 2
Reputation: 28988
This will create a new tree with the selected node as root and which child nodes consists only of nodes that are tagged "Folder".
You need to create a copy constructor (or extension method) to deep copy the node to prevent the manipulation on the node objects to impact your original tree source:
public TreeNode CollectFolderChildNodes(TreeNode selectedNode)
{
if (selectedNode.Tag == "Calculation")
return null;
// Get all the children that are tagged as folder
var childRootNodes = selectedNode.Children.Where((childNode) => childNode.Tag == "Folder";
// Clone root node using a copy constructor
var newRoot = new TreeNode(selectedNode);
newRoot.Children.Clear();
foreach (var childNode in childRootNodes)
{
// Iterate over all children and add them to the new tree
if (childNode.Children.Any())
{
// Repeat steps for the children of the current child.
// Recursion stops when the leaf is reached
newRoot.Children.Add(CollectFolderChildNodes(childNode));
}
else
{
// The current child item is leaf (no children)
newRoot.Children.Add(new TreeNode(childNode));
}
}
return newRoot;
}
I think this should do it, but I didn't tested it. But maybe at least the idea behind it is clear.
But as I mentioned before, maybe it's better to traverse the tree (using same ItemsSource
) and set a property (e.g. IsHidingCalculations) to true
so that only the folders will show up. You would need to implement an ItemsStyle
and use a trigger that sets the items Visibility
to Collapsed
when your IsHidingCalculations evaluates to true.
Upvotes: 1
Reputation: 18013
To clone a node without its children you can create an extension method like this:
public static TreeNode CloneWithoutChildren(this TreeNode node)
{
return new TreeNode(node.Text, node.ImageIndex, node.SelectedImageIndex)
{
Name = node.Name,
ToolTipText = node.ToolTipText,
Tag = node.Tag,
Checked = node.Checked
}
}
and then:
collectedNodes.Add(node.CloneWithoutChildren());
Upvotes: 0