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
Related
hi how i can set a image for my treeView nodes... I have a parent and a child node.
here is my code:
private void btnShowLicstate_Click(object sender, EventArgs e)
{
treeLic.Nodes.Clear();
string command = "\"C:\\lmxendutil.exe\" -licstatxml -host lwserv005 -port 6200";
string output = ExecuteCommand(command);
string final_output = output.Substring(90, output.Length - 90);
XmlReader xr = XmlReader.Create(new StringReader(final_output));
var xDoc = XDocument.Load(xr);
TreeNode root = new TreeNode();
LoadTree(xDoc.Root.Element("LICENSE_PATH"), root);
treeLic.Nodes.Add(root);
treeLic.ImageList = imageList1;
}
public void LoadTree(XElement root, TreeNode rootNode)
{
foreach (var e in root.Elements().Where(e => e.Attribute("NAME") != null))
{
var node = new TreeNode(e.Attribute("NAME").Value);
rootNode.Nodes.Add(node);
if (e.Name == "FEATURE")
{
node.SelectedImageIndex = 1;
}
else if (e.Name == "USER")
{
node.SelectedImageIndex = 0;
}
LoadTree(e, node);
}
}
my problem is that i have everyone the same picture but i want for FEATURE the index 1 and for USER the Index 2 but why it don't work ? :(
You should use ImageIndex property instead of SelectedImageIndex.
The first one is the index from ImageList for node in unselected state and the second one is applied when you select node using mouse, keyboard or through code.
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.
I have a problem that I cannot seem to solve.
I am building a TreeView dynamically and I have an ordered list. I want the TreeView to build in such a way:
Node1
_Node2
__ Node3
__ _Node..N
My code is as follows:
TreeNode tn = new TreeNode();
for (int i = 0; i < EmployeesReportingLine.Count; i++ )
{
Employee ep = EmployeesReportingLine[i];
while (tn.ChildNodes.Count > 0)
tn = tn.ChildNodes[0];
TreeNode temp = new TreeNode(ep.FullName);
if (i > 0)
tn.ChildNodes.Add(temp);
else
tn = temp;
}
TreeView1.Nodes.Add(tn);
I have made several other attempts at using recursive functions but the snippet above was my best attempt.
Thanks in advance.
private void addNode(TreeNodeCollection nodes, TreeNode newnode) {
if (nodes.Count == 0) nodes.Add(newnode);
else addNode(nodes[0].Nodes, newnode);
}
Or:
private void addNode2(TreeNode start, TreeNode newnode) {
if (start.Nodes.Count == 0) start.Nodes.Add(newnode);
else addNode2(start.Nodes[0], newnode);
}
I have many nodes in the treeview like nodes it children, children of children....
i wanted to copy those entire content and paste it in another node.
I dont want to use clone method since it affects object of original node from which it s copied.
Try using recursive like this
private void IterateTreeNodes( TreeNode originalNode, TreeNode rootNode )
{
foreach ( TreeNode childNode in originalNode.Nodes )
{
TreeNode newNode = new TreeNode( childNode.Text );
newNode.Tag = childNode.Tag;
treeView2.SelectedNode = rootNode;
treeView2.SelectedNode.Nodes.Add( newNode );
IterateTreeNodes( childNode, newNode );
}
}
// copy nodes from treeView1 to treeView2
private void button1_Click( object sender, EventArgs e )
{
foreach ( TreeNode originalNode in treeView1.Nodes )
{
TreeNode newNode = new TreeNode( originalNode.Text );
newNode.Tag = originalNode.Tag;
treeView2.Nodes.Add( newNode );
IterateTreeNodes( originalNode, newNode );
}
}
it's a code snippet from http://windowsclient.net/blogs/faqs/archive/2006/05/30/how-do-i-clone-or-copy-all-the-nodes-from-one-treeview-control-to-another.aspx
You can use any of the traversal algorithm
at each step, you can you can put the traversed node to an object and put that object in an objectList...
All the best...
I am trying to construct a TreeView from a Menu. My Code is like this:
public class MenuExtractionUtility
{
public TreeView MenuTraverse(MainMenu mainMenu)
{
TreeView treeView = new TreeView();
TreeNode mainNode = new TreeNode();
foreach (MenuItem mi in mainMenu.MenuItems)
{
System.Diagnostics.Debug.WriteLine(mi.Text);
mainNode.Text = mi.Text;
TreeNode tn = MenuItemTraverse(mi);
mainNode.Nodes.Add(tn);
}
treeView.Nodes.Add(mainNode);
return treeView;
}
private TreeNode MenuItemTraverse(MenuItem menuItem)
{
TreeNode treeNode = new TreeNode();
foreach(MenuItem mi in menuItem.MenuItems)
{
System.Diagnostics.Debug.WriteLine(mi.Text);
treeNode.Text = mi.Text;
TreeNode tr = MenuItemTraverse(mi);
if (tr!=null && tr.Text != "")
{
treeNode.Nodes.Add(tr);
}
}
return treeNode;
}
}
But this is not working.
What can be the problem?
I think there are two problems in the methods. Let's start with the MenuItemTraverse method. You get a MenuItem as input. You declare a TreeNode variable, and assign a new TreeNode instance to it. Then you loop over the menu item's sub items. For each iteration you assign the text from the sub item to the TreeNode (I would assume that you would want the text of the incoming menu item on this TreeNode). To get the intended behaviour you should remove this line from the loop:
treeNode.Text = mi.Text;
...and add this line before the loop:
treeNode.Text = menuItem.Text;
It looks like you have the exact same problem in the MenuTraverse method, so do the same change there. I think that would solve it for you (didn't test the code yet; might have missed something).
Update
I gave it a bit of though, since I felt that the code could probably be simplified a bit, and this is what I came up with. Instead of having two different methods for MainMenu and MenuItem input, this one encapsulates the process into one single method. Also, it takes a TreeNodeCollection, which means that you can have the method inject the menu structure into an already existing (and populated) TreeView control, at any level in the tree.
public class MenuExtractionUtility
{
public static void MenuItemTraverse(TreeNodeCollection parentCollection, Menu.MenuItemCollection menuItems)
{
foreach (MenuItem mi in menuItems)
{
System.Diagnostics.Debug.WriteLine(mi.Text);
TreeNode menuItemNode = parentCollection.Add(mi.Text);
if (mi.MenuItems.Count > 0)
{
MenuItemTraverse(menuItemNode.Nodes, mi.MenuItems);
}
}
}
}
Usage example:
treeView1.Nodes.Clear();
MenuExtractionUtility.MenuItemTraverse(treeView1.Nodes, mainMenu1.MenuItems);
This code was just quickly put together, so you may want to "stabilize" it a bit by adding null checks and similar.
here it is...
public class MenuExtractionUtility
{
public void MenuTraverse(MainMenu mainMenu, TreeView treeView)
{
TreeNode ultimateMainNode = new TreeNode();
ultimateMainNode.Text = "Root";
TreeNode mainNode = null;
foreach (MenuItem mi in mainMenu.MenuItems)
{
if (mi != null && mi.Text != "")
{
mainNode = null;
if (mi.MenuItems.Count <= 0)
{
mainNode = new TreeNode();
mainNode.Text = mi.Text;
}
else if (mi.MenuItems.Count > 0)
{
mainNode = MenuItemTraverse(mi);
}
ultimateMainNode.Nodes.Add(mainNode);
}
}
treeView.Nodes.Add(ultimateMainNode);
}
private TreeNode MenuItemTraverse(MenuItem menuItem)
{
TreeNode treeNode = new TreeNode();
System.Diagnostics.Debug.Write(menuItem.Text+",");
treeNode.Text = menuItem.Text;
foreach (MenuItem mi in menuItem.MenuItems)
{
if (mi != null && mi.Text != "")
{
TreeNode tr = MenuItemTraverse(mi);
if (tr != null && tr.Text != "")
{
treeNode.Nodes.Add(tr);
}
}
}
return treeNode;
}