Count nodes with and without subsequent child nodes - c#

I am trying to count number of tree nodes with (A) and without subsequent child nodes (B). For example the image below should return 2/1.
I tried to play around with TreeView methods but cant figure out how to work with deeper level nodes.
private void tvResources_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
int a=0,b=0;
foreach (TreeNode node in e.Node.Nodes)
{
if (e.Node.Nodes.Contains(node))
a += 1;
else
b += 1;
}
e.Node.Text += #" - " + a+"/"+b;
}
This can probably be done with some recursive function, but is there any easier solution?

If you need just the current node (before expanding), you could just use the foreach loop to check the number of nodes for each direct child and that will give you the answer directly.
private void tvResources_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
CalculateAB( e.Node );
}
private void CalculateAB( TreeNode node )
{
int a = 0;
int b = 0;
foreach ( TreeNode child in node.Nodes )
{
if ( child.Nodes.Count() > 0 )
{
a++;
}
else
{
b++;
}
}
node.Text += #" - " + a + "/" + b;
}
You can then use recursion if you want to calculate the values for the whole TreeView at once. You can use depth-first search and calculate the a/b values of all nodes you encounter using the CalculateAB method.
private void CalculateForTree( TreeNode root )
{
foreach ( var child in root.Nodes )
{
CalculateForTree( child );
}
CalcualteAB( root );
}

Related

Algorithm check last node in the tree

public void Convert(Node)
{
StartGrouping();
DoSomething();
int childCount = node.GetChildCount();
for (int i = 0; i < childCount; i++)
{
Convert(node.GetChild(i));
}
if(last_node)
{
EndGrouping();
}
}
What is the correct way to check when we reach the last node (as in the picture).
If you want to find the last node that has no children: i.e. find the last node of the current level and if it has children go deeper otherwise return it, then you can do it easily:
private Node FindLast(Node[] nodes)
{
var node = nodes.GetLast();
if (node.HasChildren())
{
return FindLast(node.GetChildren());
}
return node;
}

add the count of child node in each branch of asp.net treeview

I want to add the count of child node in each branch of asp.net treeview.
for example ..
root (2)
parent (3)
child
child
child
parent (2)
child
child
You need to use code-behind. You could do:
void Page_Load(Object sender, EventArgs e)
{
// Iterate through the root nodes in the Nodes property.
for(int i=0; i<YourTreeView.Nodes.Count; i++)
{
// Set the text to include children count.
SetChildNodeText(YourTreeView.Nodes[i]);
}
}
void SetChildNodeText(TreeNode node)
{
if(node.ChildNodes.Count > 0)
{
node.Text += ' (' + node.ChildNodes.Count.ToString() + ')'; // append child node count to the text
}
for(int i=0; i<node.ChildNodes.Count; i++)
{
// recursion
SetChildNodeText(node.ChildNodes[i]);
}
}

How to search child nods in a treeview

I tride it in this way,
private void btnFind_Click(object sender, EventArgs
{
for (int i = 0; i < treeView1.Nodes.Count - 1; i++)
{
MessageBox.Show(i.ToString());
treeView1.Nodes[i].BackColor = Color.Empty;
}
var result = from TreeNode node in treeView1.Nodes
where node.Text.Contains( Convert.ToString(txtFind.Text))
select node.Index;
foreach (int search in result)
{
treeView1.Nodes[search].BackColor = Color.Yellow;
}
}
But in this way I can find only parent nodes. Is there a proper way to do this
You can have a method to process the TreeView and then another to recursively call the child nodes. This will load _matchingNodes with all of the nodes that match your text.
Private List<TreeNode> _matchingNodes;
// Process the TreeView.
private void ProcessTreeView(TreeView treeView, String FindText)
{
_matchingNodes = new List<TreeNode>();
// Process each node recursively.
foreach (TreeNode n in treeView.Nodes)
{
if(n.Text.Contains(FindText))
_matchingNodes.Add(n);
ProcessRecursive(n, FindText);
}
}
private void ProcessRecursive(TreeNode treeNode, String FindText)
{
// Process each node recursively.
foreach (TreeNode n in treeNode.Nodes)
{
if(n.Text.Contains(FindText))
_matchingNodes.Add(n);
ProcessRecursive(n, FindText);
}
}
private void btnFind_Click(object sender, EventArgs e)
{
CallRecursive(treeView1);
}
private void PrintRecursive(TreeNode treeNode)
{
if (treeNode.Text.Contains(txtFind.Text.ToString()))
{
//MessageBox.Show(treeNode.Text);
treeNode.BackColor = Color.Blue;
}
else
{
treeNode.BackColor = Color.Empty;
}
// Print each node recursively.
foreach (TreeNode tn in treeNode.Nodes)
{
PrintRecursive(tn);
}
}
// Call the procedure using the TreeView.
private void CallRecursive(TreeView treeView)
{
// Print each node recursively.
TreeNodeCollection nodes = treeView.Nodes;
foreach (TreeNode n in nodes)
{
PrintRecursive(n);
}
}
I solved It Like this and it works as expected.
TreeView.nodes.find(nodeName,1)
The numeral 1 specifies to look at all child nodes too. A 0 means say to not include children. Only tested in Powershell.
Perhaps not so helpful for searching the text of the nodes but hopefully you can obtain the node name.

How can I find a root node in TreeView

I have a TreeView in my Windows application. Tn this TreeView, the user can add some root nodes and also some sub nodes for these root nodes and also some sub nodes for these sub nodes and so on ...
For example:
Root1
A
B
C
D
E
Root2
F
G
.
.
.
Now my question is that if I am at node 'E' what is the best way to find its first root node ('Root1')?
Here is a little method for you:
private TreeNode FindRootNode(TreeNode treeNode)
{
while (treeNode.Parent != null)
{
treeNode = treeNode.Parent;
}
return treeNode;
}
you can call in your code like this:
var rootNode = FindRootNode(currentTreeNode);
public TreeNode RootTreeNode(TreeNode n) { while (n.Level > 0) { n = n.Parent; } return n; }
Example to get root treenode:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
var node = (e == null ? ((System.Windows.Forms.TreeView)sender).SelectedNode : e.Node);
var rootNode = RootTreeNode(node);
}
Enjoy

Re-Sorting treeview Nodes[0] only after being populated

I have the following tree:
Animals
|
|___Zebra
| |__Head
| |__Arms
| |__Legs
|
|___Monkey
|__Head
|__Arms
|__Legs
Each animal has an ID number stored in the Tag field and their name is in Name field of node.I want to press a button that says "Sort by ID" and have the "Zebra" above turn into "14" etc, and then resort numerically. However, I want the children to stay with the head, arms, legs order. When I use the following code, it works, but it also re-sorts the head arms legs into arms, head, legs. I've tried a NodeSorter, but I just didn't get any different results. I'm also very new to C# so I might have implemented it incorrectly. :) I'm also using a custom node with a few extra fields to store data and boolean values. That's what the "JacksNode" refers to below.
Here's the code:
public static void sortByAnimalID(TreeView tv)
{
tv.BeginUpdate();
foreach (TreeNode treeNode in tv.Nodes[0].Nodes)
{
if (((JacksNode)treeNode).IsAnimal)
{
treeNode.Text = Convert.ToString(treeNode.Tag);
treeNode.Name = Convert.ToString(treeNode.Tag);
}
}
tv.Sort();
tv.EndUpdate();
}
Any ideas on what I'm doing wrong? I've searched the web for two weeks and have been overwhelmed with all the treeview articles. However, none have been this specific.
Thanks guys/gals for any suggestions.
Use the TreeNode.Level property to figure out how to compare node properties. Like this:
private void SortButton_Click(object sender, EventArgs e) {
if (treeView1.TreeViewNodeSorter == null) {
treeView1.TreeViewNodeSorter = new NodeSorter();
}
}
private class NodeSorter : System.Collections.IComparer {
public int Compare(object x, object y) {
TreeNode node1 = (TreeNode)x;
TreeNode node2 = (TreeNode)y;
if (node1.Level == 1) {
return Convert.ToInt32(node1.Tag).CompareTo(Convert.ToInt32(node2.Tag));
}
else {
return node1.Index.CompareTo(node2.Index);
}
}
}
//bubble sort
public void Sort_TV_ByTag(TreeNodeCollection treeNodeCollection)
{
int i, j;
int n = treeNodeCollection.Count;
for (i = 0; i < n; i++)
{
for (j = 1; j < (n - i); j++)
{
int firstValue = int.Parse(treeNodeCollection[j - 1].Tag.ToString());
int secondValue = int.Parse(treeNodeCollection[j].Tag.ToString());
//you can compare by Tag , Text , anything
if (firstValue > secondValue)
{
//swap the nodes
TreeNode n1 = treeNodeCollection[j - 1];
TreeNode n2 = treeNodeCollection[j];
treeNodeCollection.Remove(n1);
treeNodeCollection.Remove(n2);
treeNodeCollection.Insert(j, n1);
treeNodeCollection.Insert(j - 1, n2);
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Sort_TV_ByTag(treeView1.Nodes[0].Nodes);
}

Categories

Resources