How to set position while traversing through Treeview - c#

I want to traverse through a treeview & set the value property to be its position in the tree as shown below
A[val:1]->A1[val:11]
l l--->A2[val:12]
l----->A3[val:13]
B[val:2]->B1[val:21]
l l--->B2[val:22]
C[val:3]->C1[val:31]
l l--->C2[val:32]
I have written a recursive which returns me all the nodes but i am unable to assign the desired position to its nodes.
private void TraverseTreeNode(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
TraverseTreeNode(node.ChildNodes);
}
}

Considering that TreeNode.Value is of type string, this will, starting at level = 1:
private static void TraverseTreeNode(TreeNodeCollection nodes, int parentNumber)
{
var childNumber = 1;
foreach (TreeNode node in nodes)
{
node.Value = string.Format("{0}{1}", parentNumber, childNumber ).Substring(0,node.Depth+1);
TraverseTreeNode(node.ChildNodes, parentNumber);
childNumber++;
if (node.Depth == 0) { parentNumber++; }
}
}
Only works for two levels but is easily extendable by adding additional parameters to TraverseTreeNode.
UPDATE
The following will work for any depth in hierarchy:
private static void TraverseTreeNode(TreeNodeCollection nodes, int parentNumber)
{
var childNumber = 1;
foreach (TreeNode node in nodes)
{
node.Value = node.Parent != null && node.Parent.Value != null
? string.Format("{0}{1}", node.Parent.Value, childNumber)
: string.Format("{0}{1}", parentNumber, childNumber).Substring(0, node.Depth + 1);
TraverseTreeNode(node.ChildNodes, parentNumber);
childNumber++;
if (node.Depth == 0) { parentNumber++; }
}
}

As you need recursive method, try this
private void Caller()
{
TraverseTreeNode(treeView1.Nodes);
}
private void TraverseTreeNode(TreeNodeCollection nodes)
{
int index = 1;
foreach (TreeNode node in nodes)
{
node.Text = (node.Parent != null ? node.Parent.Text : string.Empty) + index++;
TraverseTreeNode(node.Nodes);
}
}

Related

How to find all the checked nodes in a Treeview using C#

This is the code which I am using, but I am always getting a blank string from the function.
How do I solve such a problem?
private string GetArrayofCheckedNodes()
{
string arrCheckedNodes = "";
ArrayList al = new ArrayList();
foreach (TreeNode node in TreeView1.Nodes)
{
if (node.Checked == true) // Checking whether a node is checked or not.
{
al.Add(node.Text);
}
}
for (int i = 0; i < al.Count; i++)
{
arrCheckedNodes += al[i].ToString() + " , ";
}
return arrCheckedNodes;
}
I'm assuming you want ALL checked nodes. TreeView1.Nodes only returns the first level so you will need to recurse down the tree. Also, you can use string.Join() to join the resultant values together.
private string GetArrayofCheckedNodes()
{
return string.Join(" , ", GetCheckedNodes(treeView1.Nodes));
}
public List<string> GetCheckedNodes(TreeNodeCollection nodes)
{
List<string> nodeList = new List<string>();
if (nodes == null)
{
return nodeList;
}
foreach (TreeNode childNode in nodes)
{
if (childNode.Checked)
{
nodeList.Add(childNode.Text);
}
nodeList.AddRange(GetCheckedNodes(childNode.Nodes));
}
return nodeList;
}

Compare treeView nodes Text to a String

I'm working on a Winform application, how can I check if there is a treeNode that its text is inside string Mystring? And how can i retrieve the tag of this node please?
if (myString.Contains(treeView1.Nodes.ToString()))
This works for only first matched node.
private TreeNode FindMatchedNode(TreeNodeCollection tnCol, string text)
{
TreeNode tn = null;
foreach (TreeNode node in tnCol)
{
if (text.ToLower().Contains(node.Text.ToLower()))
{
tn = node;
break;
}
else if (node.Nodes != null)
{
tn = FindNode(node.Nodes, text);
if (tn != null)
break;
}
}
return tn;
}
and for all matched nodes
private List<TreeNode> FindAllMatchedNodes(TreeNodeCollection tnCol, string text)
{
List<TreeNode> retVal = new List<TreeNode>();
foreach (TreeNode node in tnCol)
{
if (text.ToLower().Contains(node.Text.ToLower()))
{
retVal.Add(node);
}
else if (node.Nodes != null)
{
retVal.AddRange(FindNode(node.Nodes, text));
}
}
return retVal;
}
This method will traverse tree from root and find first node that Text is inside of myString
public object FindNode()
{
var queue = new Queue<TreeNode>();
foreach (var n in treeView1.Nodes)
{
// Add all root nodes to queue
queue.Enqueue(n);
}
while (queue.Count > 0)
{
// Take the next node from the front of the queue
var node = queue.Dequeue();
// Check if myString contains node text
if (myString.Contains(node.Text))
return node.Tag;
// Add the node’s children to the back of the queue
foreach (var child in node.Children)
{
queue.Enqueue(child);
}
}
// None of the nodes matched the specified string.
return null;
}

treeview how to expand a fullpath

I need to expand my treeview based on a fullpath in c#
My tree view has 2 nodes which are collapsed and I want to expand Node A to number 3
so I have the fullpath of node A\1\2\3.
How can I step through and open each node based of the fullpath? Also the length of the fullpath may change, so i may need to open node be to level 6. So it needs to be done based on the fullpath. Any help would be great.
Node A
1
2
3
Node B
1
2
3
4 5 6
This is what I've tried:
TreeNode [] n= treeView1.Nodes.Find(search, true);
if (n.Length > 0)
found = true;
treeView1.Nodes[t].Collapse();
foreach (TreeNode p in n) {
string[] a = p.FullPath.Split('\\');
foreach (string b in a) {
treeView1.SelectedNode = treeView1.Nodes[b];
treeView1.SelectedNode.Expand();
I'm sorry for not commenting on above answer given by S3ddi9 which is CORRECT. I'm only adding something.
So the answer given by S3ddi9
...
string path = #"A\1\2\";
var path_list = path.Split('\\').ToList();
foreach (TreeNode node in treeView1.Nodes)
if (node.Text == path_list[0])
ExpandMyLitleBoys(node, path_list);
}
private void ExpandMyLitleBoys(TreeNode node, List<string> path)
{
path.RemoveAt(0);
node.Expand();
if (path.Count == 0)
return;
foreach (TreeNode mynode in node.Nodes)
if (mynode.Text == path[0])
{
ExpandMyLitleBoys(mynode, path); //recursive call
break; //this was missing in earlier answer
}
}
Does work, BUT you must add a BREAK (I marked it), because if the for loop doesn't finish, return; won't return you to your main function and it will throw you an exception because path[0] is null.
I hope this will be more simpler, for Treeviews the best approach is to use recursive methods
...
string path = #"A\1\2\";
var path_list = path.Split('\\').ToList();
foreach (TreeNode node in treeView1.Nodes)
if (node.Text == path_list[0])
ExpandMyLitleBoys(node, path_list);
}
private void ExpandMyLitleBoys(TreeNode node, List<string> path)
{
path.RemoveAt(0);
node.Expand();
if (path.Count == 0)
return;
foreach (TreeNode mynode in node.Nodes)
if (mynode.Text == path[0])
ExpandMyLitleBoys(mynode, path); //recursive call
}
this does the work perfectly
Cracked it!!
TreeNode[] n = treeView1.Nodes.Find(search, true);
if (n.Length > 0)
found = true;
treeView1.Nodes[t].Collapse();
foreach (TreeNode p in n)
{
i = 0;
string[] a = p.FullPath.Split('\\');
foreach (string b in a)
{
if (i == 0)
{
treeView1.SelectedNode = treeView1.Nodes[b];
current = treeView1.Nodes[b];
treeView1.SelectedNode.Expand();
i = 1;
}
else
{
treeView1.SelectedNode = current.Nodes[b];
current = current.Nodes[b];
treeView1.SelectedNode.Expand();
if (b.ToUpper().Contains(search))
{
treeView1.SelectedNode.BackColor = System.Drawing.Color.Red;
}
I wrote a little simpler routine that works great. no recursion at all...
This assumes your path is a full file path like... "C:\program files\myapp" and when you add your nodes you set the node Key equal to the folder name
string[] strFolders = strPath.Split('\'));
System.Windows.Forms.TreeNode CurrentNode = null;
System.Windows.Forms.TreeNode[] FoundNodes = null;
foreach (string folder in strFolders) {
if (!folder.Contains(":")) {
if (CurrentNode == null) {
FoundNodes = treeFolders.Nodes.Find(folder, false);
} else {
FoundNodes = CurrentNode.Nodes.Find(folder, false);
}
if (FoundNodes.Length > 0) {
CurrentNode = FoundNodes[0];
CurrentNode.Expand();
} else {
//no folder found. cant continue
break;
}
}
}
if (CurrentNode != null) {
treeFolders.SelectedNode = CurrentNode;
}

Find the level of Deepest child Treenode

I have treenode & i would like to find the deepest child in the treenode.
if there are 2 child nodes with level 11 & level 13 respectively then i need unction to return me the value 13.
How can i do that ?
public int FindLevel(TreeNode oParentNode)
{
counter++;
forech(TreeNode oSubNode in oParentNode.Nodes)
{
FindLevel(oParentNode);
}
return Counter;
}
Here is my suggestion for you:
private int GetDeepestChildNodeLevel(TreeNode node)
{
var subLevel = node.Nodes.Cast<TreeNode>().Select(GetDeepestChildNodeLevel);
return subLevel.Count() == 0 ? 1 : subLevel.Max() + 1;
}
here with explicit types:
private int GetDeepestChildNodeLevel(TreeNode node)
{
var subLevel = node.Nodes.Cast<TreeNode>().Select<TreeNode, int>(subNode => GetDeepestChildNodeLevel(subNode));
return subLevel.Count<int>() == 0 ? 1 : subLevel.Max() + 1;
}
Here's the extension method for TreeView that returns Level of the deepest node in that TreeView.
public int GetDeepestNodeLevel(this System.Windows.Forms.TreeView treeView)
{
int level = -1;
foreach (System.Windows.Forms.TreeNode node in treeView.Nodes) {
int deep = DigInNodes(node);
if (deep > level)
level = deep;
}
return level;
}
private int DigInNodes(System.Windows.Forms.TreeNode node)
{
int level = node.Level;
foreach (System.Windows.Forms.TreeNode subnode in node.Nodes) {
int deep = DigInNodes(subnode);
if (deep > level)
level = deep;
}
return level;
}
Code is tested and works for me.
This is the fast way to get level´s deep of selected node.
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
TreeNode node = treeView1.SelectedNode;
MessageBox.Show(string.Format("You selected: {0}{1}", node.Text,e.Node.Level));
}

how do I change the order of treenodes

I would like to change the order of System.Windows.Forms.TreeNodes on the same level.
any suggestions on how this might be done in .net-2.0.
You need to manipulate the TreeView's Nodes collection. See TreeNodeCollection.
If you have three tree nodes and you want to move the last one to the front, for example: (Note: not tested code, but shows the idea)
var lastNode = MyTreeView.Nodes[2];
MyTreeView.Nodes.Remove(lastNode);
MyTreeView.Nodes.Insert(0, lastNode);
void MoveNodeUp(TreeNode node)
{
TreeNode parentNode = node.Parent;
int originalIndex = node.Index;
if (node.Index == 0) return;
TreeNode ClonedNode = (TreeNode)node.Clone();
node.Remove();
parentNode.Nodes.Insert(originalIndex - 1, ClonedNode);
parentNode.TreeView.SelectedNode = ClonedNode;
}
That's what I've written:
public void MoveNode(TreeView tv, TreeNode node, bool up)
{
if ((node.PrevNode == null) && up) {
return;
}
if ((node.NextNode == null) && !up) {
return;
}
int newIndex = up ? node.Index - 1 : node.Index + 1;
var nodes = tv.Nodes;
if (node.Parent != null) {
nodes = node.Parent.Nodes;
}
nodes.Remove(node);
nodes.Insert(newIndex, node);
}
I wrote this code which does not require any cloning.
For my case it moves up one position in the sibling nodes but can be adapted
TreeNode selectedNode = treeViewChain.SelectedNode;
if (selectedNode != null && selectedNode.Index > 0)
{
TreeNode parent = selectedNode.Parent;
int selectedIndex = selectedNode.Index;
selectedNode.Remove();
parent.Nodes.Insert(selectedIndex - 1, selectedNode);
treeViewChain.SelectedNode = selectedNode;
}

Categories