adding a child node to specific node in c# - c#

I have a problem adding a childnode to specific node. Here is my code:
Method for painting tree
public void paint()
{
treeView1.Nodes.Clear();
TreeNode root = new TreeNode("Katalogas");
root.Name = "root";
treeView1.Nodes.Add(root);
foreach (string or in categories)
{
TreeNode subcat = new TreeNode(or);
subcat.Name = or;
root.Nodes.Add(subcat);
}
foreach (Preke or in PrekiuListas)
{
TreeNode subcat = new TreeNode(or.name);
subcat.Name = or.name;
TreeNode temp = FindNode(or.category);
temp.Nodes.Add(subcat);
}
Method for finding node
private TreeNode FindNode(String name)
{
foreach (TreeNode node in treeView1.Nodes[0].Nodes)
{
if (node.Nodes.Count > 0)
return FindNode(name);
if (node.Name == name)
return node;
}
return null;
}
I can add one child node to both nodes, but when i try to add another, i get stack overflow exception.. Please help, thanks

You have to pass the root node along with the method:
private TreeNode FindNode(String name, TreeNode root)
{
if(root.Name == name) return root;
Stack<TreeNode> nodes = new Stack<TreeNode>();
nodes.Push(root);
while(nodes.Count > 0)
{
var node = nodes.Pop();
foreach(TreeNode n in node.Nodes){
if (n.Name == name) return n;
nodes.Push(n);
}
}
return null;
}
//Usage
var node = FindNode(someName, treeView1.Nodes[0]);
//if your treeView has more root nodes, you have to loop through them
TreeNode node = null;
foreach(TreeNode node in treeView1.Nodes){
node = FindNode(someName, node);
if(node != null) break;
}

If the problem is just that of finding the node name, you can use the built-in TreeNodeCollection.Find() method for better performance:
public TreeNode[] Find(string key, bool searchAllChildren);
Example:
n.Nodes.Find("name", true);
The second parameter indicates that you want to search in all nodes recursively.
Also, this returns an entire TreeNode[] array, not a single node. So, you have to loop in them to fill or take the node[0] element if yo want to use just the first one.

Related

How to find a path to a specific object from a tree of objects? [duplicate]

I have TreeNode node.
something = treeview.Nodes[1].Nodes[4].Nodes[0];
TreeNode myNode = something;
And wish to know how pany parents it has and what indexes i need to use to find whole path out from this node.
I mean get "treeview.Nodes[1].Nodes[4].Nodes[0]" out from myNode
Something like this should work:
public IList<int> GetNodePathIndexes(TreeNode node)
{
List<int> indexes = new List<int>();
TreeNode currentNode = node;
while (currentNode != null)
{
TreeNode parentNode = currentNode.Parent;
if (parentNode != null)
indexes.Add(parentNode.Nodes.IndexOf(currentNode));
else
indexes.Add(currentNode.TreeView.Nodes.IndexOf(currentNode));
currentNode = parentNode;
}
indexes.Reverse();
return indexes;
}
You can then look at the result of this to get the indexes, and the count, to get the number of parents.
IList<int> path = GetNodePathIndexes(myNode);
StringBuilder fullPath = new StringBuilder("treeview");
foreach (int index in path)
{
fullPath.AppendFormat(".Nodes[{0}]", index);
}
Then fullPath.ToString() should return treeview.Nodes[1].Nodes[4].Nodes[0]
//...
string path = GetPath(treeView1.Nodes[0].Nodes[0].Nodes[1].Nodes[0]);
// now path is "treeView.Nodes[0].Nodes[0].Nodes[1].Nodes[0]"
//...
string GetPath(TreeNode node) {
int index;
Stack<string> stack = new Stack<string>();
while(node != null) {
if(node.Parent != null) {
index = node.Parent.Nodes.IndexOf(node);
stack.Push(string.Format("Nodes[{0}]", index));
}
else {
index = node.TreeView.Nodes.IndexOf(node);
stack.Push(string.Format("treeView.Nodes[{0}]", index));
}
node = node.Parent;
}
return string.Join(".", stack.ToArray());
}

asp.net treeview with folders and file from database

I have a requirement to bind folders and files to the treeview based on table data from data base, i tried lot of solution but failed to meet specific requirement.
Here is what im looking
Top folders
I have found one sample code and tried to achieve this
`
private void PopulateTreeview(DataTable dtFolders)
{
tvVendors.Nodes.Clear();
HierarchyTrees hierarchyTrees = new HierarchyTrees();
HierarchyTrees.HTree objHTree = null;
if (dtFolders.Rows.Count > 0)
{
foreach (DataRow dr in dtFolders.Rows)
{
objHTree = new HierarchyTrees.HTree();
objHTree.LevelDepth = int.Parse(dr["level"].ToString());
objHTree.NodeID = int.Parse(dr["folderid"].ToString());
objHTree.UnderParent = int.Parse(dr["parentid"].ToString());
objHTree.FIleName=dr["filename"].ToString();
objHTree.FilePath=dr["filepath"].ToString();
hierarchyTrees.Add(objHTree);
}
}
//Iterate through Collections.
foreach (HierarchyTrees.HTree hTree in hierarchyTrees)
{
//Filter the collection HierarchyTrees based on
//Iteration as per object Htree Parent ID
HierarchyTrees.HTree parentNode = hierarchyTrees.Find
(delegate(HierarchyTrees.HTree vendor)
{ return vendor.NodeID == hTree.UnderParent; });
//If parent node has child then populate the leaf node.
if (parentNode != null)
{
foreach (TreeNode tn in tvVendors.Nodes)
{
//If single child then match Node ID with Parent ID
if (tn.Value == parentNode.NodeID.ToString())
{
tn.ChildNodes.Add(new TreeNode
(hTree.NodeDescription.ToString(), hTree.NodeID.ToString()));
}
//If Node has multiple child ,
//recursively traverse through end child or leaf node.
if (tn.ChildNodes.Count > 0)
{
foreach (TreeNode ctn in tn.ChildNodes)
{
RecursiveChild(ctn, parentNode.NodeID.ToString(), hTree);
}
}
}
}
//Else add all Node at first level
else
{
tvVendors.Nodes.Add(new TreeNode
(hTree.NodeDescription, hTree.NodeID.ToString()));
}
}
tvVendors.ExpandAll();
}
public void RecursiveChild(TreeNode tn, string searchValue, HierarchyTrees.HTree hTree)
{
if (tn.Value == searchValue)
{
tn.ChildNodes.Add(new TreeNode
(hTree.NodeDescription.ToString(), hTree.NodeID.ToString()));
}
if (tn.ChildNodes.Count > 0)
{
foreach (TreeNode ctn in tn.ChildNodes)
{
RecursiveChild(ctn, searchValue, hTree);
}
}
}
Problem: I'm not able to bind file name to leaf node, if folder does not have any subfolder. bind the files. or if folder has subfolder and file both.bind both at same level. if folder is empty, it has nothing just bind it blank.
Could please test the code provide some solution`
foreach (TreeNode childnode in GetChildFolderNode(dataRow[ID].ToString(), table))
{
//Bind all folders
}
foreach (TreeNode childnode in GetChildFileNode(dataRow[ID].ToString(), table))
{
//bind all files
}

How to set position while traversing through Treeview

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

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

Categories