I use Win forms treeview class. I need to have possibililty to navigate to specified node by its fullpath propety. i.e. I have fullpath ("country\region1\city2") and wish to select this node by this path automatically. Can anyone help me?
This is treeview navigation by msdn
private void PrintRecursive(TreeNode treeNode)
{
// Print the node.
System.Diagnostics.Debug.WriteLine(treeNode.Text);
MessageBox.Show(treeNode.Text);
// 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);
}
}
This could help you too
codeproject variant of explorer with treeview navigation
Related
When i'm running the program i see the root node
Countries
Then when i click on it i see all the countries nodes under Countries
But i want when running the program that it already will show all the countries nodes without clicking on Countries.
I tried in the constructor:
PopulateTree(mainPath, treeView1.Nodes.Add("Countries"));
treeView1.CollapseAll();
treeView1.Nodes[0].Expand();
The populatetree
public void PopulateTree(string dir, TreeNode node)
{
DirectoryInfo directory = new DirectoryInfo(dir);
foreach (DirectoryInfo d in directory.GetDirectories())
{
TreeNode t = new TreeNode(d.Name);
PopulateTree(d.FullName, t);
node.Nodes.Add(t);
}
foreach (FileInfo f in directory.GetFiles())
{
TreeNode t = new TreeNode(f.Name);
node.Nodes.Add(t);
}
}
But it's not doing it i still see Countries when running the program and to see all the childs nodes i need to click on Countries.
This lines not effect
treeView1.CollapseAll();
treeView1.Nodes[0].Expand();
TreeNode.Expand expands only Nodes[0] down to the next level of nodes. You should use TreeNode.ExpandAll to expand all child nodes of Countries node:
treeView1.Nodes[0].ExpandAll()
NOTE: There is one thing you should keep in mind. If handle is not created for TreeView control, then something like lazy collapsing-expanding is working here. I.e. each node has expandOnRealization and collapseOnRealization fields. When you are trying to expand node before tree handle is created, then just expandOnRealization flag is set to true. No TVM_EXPAND windows messages are sent to actually expand that node. Same for collapsing. When tree node is realized, then there is following code executed:
// If node expansion was requested before the handle was created,
// we can expand it now.
if (expandOnRealization) {
Expand();
}
// If node collapse was requested before the handle was created,
// we can expand it now.
if (collapseOnRealization) {
Collapse();
}
So, if node was marked both for collapsing and expanding, then it would be expanded first and then collapsed. I believe it's your case.
I have a method that is used as a threadsafe callback to update a treeview. It takes two string parameters. The first is the passed data and the second is the IP of the host it checked.
I am trying to check whether or not the treeview currently contains the string containing the input string and if it doesn't than it is supposed to add it to the treeview as a parent node, then add the ip string underneath as a child. Although if it does already contain that input string as a parent node than it should add only the Ip address underneath the parent that the data string matches. So it basically sorts the ips. Each parent node will have multiple ips underneath.
My issue is that my method is adding each string as it's own parent regardless if it is a duplicate, which also means that it is not adding the IP of the duplicate input underneath the parent. Can anyone take a look and see where I am going wrong?
public void UpdateScan(string input, string ip)
{
lock (outputTree)
{
outputTree.BeginUpdate();
if (!(outputTree.Nodes.ContainsKey(input)))
{
TreeNode treeNode = new TreeNode(input);
//Add our parent node
outputTree.Nodes.Add(treeNode);
//Add our child node
treeNode.Nodes.Add(ip);
}
else
{
TreeNode[] treeNode = outputTree.Nodes.Find(input, true);
//Add only child node
foreach (var node in treeNode)
{
node.Nodes.Add(ip);
}
}
outputTree.EndUpdate();
}
}
I was able to get it working. By dynamically adding a key containing the data to the parent node, so I can then use that key to find the parents to add the correct children to them.
public void UpdateScan(string input, string ip)
{
lock (outputTree)
{
outputTree.BeginUpdate();
if (! outputTree.Nodes.ContainsKey(input))
{
TreeNode treeNode = new TreeNode(input);
treeNode.Name = input;
//Add our parent node
outputTree.Nodes.Add(treeNode);
//Add our child node
treeNode.Nodes.Add(ip);
}
else
{
TreeNode[] found = outputTree.Nodes.Find(input, true);
TreeNode newChild = new TreeNode(ip);
//Add only child node
found[0].Nodes.Add(newChild);
}
outputTree.EndUpdate();
}
}
I've created a directory and file browser TreeView on the left side. I want the users to be able to browse the tree and check the files and directories that they would like to move to another treeview.
The other TreeView is a user control I found online called TreeViewColumn. I will be using that control to allow the user to add other data (categories, attributes) to the files and folders selected.
The trouble I'm running into is two-fold, I need to recursively add all children (I can figure this out) but I need to add unchecked parents to checked children (to preserve the hierarchy).
private void IterateTreeNodes(TreeNode originalNode, TreeNode rootNode)
{
//Take the node passed through and loop through all children
foreach (TreeNode childNode in originalNode.Nodes)
{
// Create a new instance of the node, will need to add it to the recursion as a root item
// AND if checked it needs to get added to the new TreeView.
TreeNode newNode = new TreeNode(childNode.Text);
newNode.Tag = childNode.Tag;
newNode.Name = childNode.Name;
newNode.Checked = childNode.Checked;
if (childNode.Checked)
{
// Now we know this is checked, but what if the parent of this item was NOT checked.
//We need to head back up the tree to find the first parent that exists in the tree and add the hierarchy.
if (tvSelectedItems.TreeView.Nodes.ContainsKey(rootNode.Name)) // Means the parent exist?
{
tvSelectedItems.TreeView.SelectedNode = rootNode;
tvSelectedItems.TreeView.SelectedNode.Nodes.Add(newNode);
}
else
{
AddParents(childNode);
// Find the parent(s) and add them to the tree with their CheckState matching the original node's state
// When all parents have been added, add the current item.
}
}
IterateTreeNodes(childNode, newNode);
}
}
private TreeNode AddParents(TreeNode node)
{
if (node.Parent != null)
{
//tvDirectory.Nodes.Find(node.Name, false);
}
return null;
}
Could anyone help with this code so that it recursively adds checked nodes (and their parent, regardless of checked state). I need to maintain directory hierarchy.
Thanks for any help!
A rather (not-so-clean and not-preferred) solution could be to clone the tree first, and then remove unchecked branches.
Else, when you are adding a node, write a recursive method to traverse through node's parent node until you hit the root. And simply optimize it by checking if childNode.parent already exists, just ignore the branch and move on. i.e. Backtrack to root node.
I got it working. I was already aware of what #Yahya was saying, I was hoping for an easier way / better approach.
The code below is certainly not optimal, I will continue improving it on my end but at this point it is looking through a treeview on the left and copying all of the checked items (and their parents - regardless of CheckedState) to a treeview on the right.
Hopefully this helps someone and thanks for answering #Yahya.
I'm open to improvements but keep in mind this is a one-time use utility.
private void cmdMoveRight_Click(object sender, EventArgs e)
{
tvSelectedItems.TreeView.Nodes.Clear();
// Traverse first level Tree Nodes
foreach (TreeNode originalNode in tvDirectory.Nodes)
{
TreeNode newNode = new TreeNode(originalNode.Text);
newNode.Name = originalNode.Name;
newNode.Tag = originalNode.Tag;
newNode.Checked = originalNode.Checked;
//Only add to the new treeview if the node is checked
if (originalNode.Checked)
{
tvSelectedItems.TreeView.Nodes.Find(originalNode.Parent.Name,true)[0].Nodes.Add(newNode);
}
//Start recursion - this will be called for each first level node - there should technically only be 1 "ROOT" node.
IterateTreeNodes(originalNode, newNode);
}
}
private void IterateTreeNodes(TreeNode originalNode, TreeNode rootNode)
{
//Take the node passed through and loop through all children
foreach (TreeNode childNode in originalNode.Nodes)
{
// Create a new instance of the node, will need to add it to the recursion as a root item
// AND if checked it needs to get added to the new TreeView.
TreeNode newNode = new TreeNode(childNode.Text);
newNode.Tag = childNode.Tag;
newNode.Name = childNode.Name;
newNode.Checked = childNode.Checked;
if (childNode.Checked)
{
// Now we know this is checked, but what if the parent of this item was NOT checked.
//We need to head back up the tree to find the first parent that exists in the tree and add the hierarchy.
TreeNode[] nodestest = tvSelectedItems.TreeView.Nodes.Find(childNode.Parent.Name, true);
if (nodestest.Length > 0)
{
tvSelectedItems.TreeView.Nodes.Find(childNode.Parent.Name,true)[0].Nodes.Add(newNode);
}
else
{
AddParents(childNode);// Find the parent(s) and add them to the tree with their CheckState matching the original node's state
}
}
//recurse
IterateTreeNodes(childNode, newNode);
}
}
private void AddParents(TreeNode node)
{
if (node.Parent != null)// Check if parent is null (would mean we're looking at the root item
{
TreeNode[] nodestest = tvSelectedItems.TreeView.Nodes.Find(node.Parent.Name, true);
if (nodestest.Length > 0)
{
TreeNode[] nodes = tvDirectory.Nodes.Find(node.Name, true);
TreeNode newNode = new TreeNode(nodes[0].Text);
newNode.Name = nodes[0].Name;
newNode.Tag = nodes[0].Tag;
newNode.Checked = nodes[0].Checked;
tvSelectedItems.TreeView.Nodes[node.Parent.Name].Nodes.Add(newNode);
}
else
{
AddParents(node.Parent);
TreeNode newNode = new TreeNode(node.Text);
newNode.Name = node.Name;
newNode.Tag = node.Tag;
newNode.Checked = node.Checked;
tvSelectedItems.TreeView.Nodes.Find(node.Parent.Name,true)[0].Nodes.Add(newNode);
}
}
else // deal with root node
{
TreeNode rootNode = new TreeNode(node.Text);
rootNode.Name = node.Name;
rootNode.Tag = node.Tag;
rootNode.Checked = node.Checked;
tvSelectedItems.TreeView.Nodes.Add(rootNode);
}
}
when my page opens it runs this method:
private void PrintRecursive(TreeNode treeNode, string problemValue)
{
// Print the node.
System.Diagnostics.Debug.WriteLine(treeNode.Text);
if (treeNode.Value == problemValue.Split(':')[0])
{
treeNode.Checked = true;
// Then expand the SelectedNode and ALL its parents until no parent found
treeNode.Expand();
while (treeNode.Parent != null)
{
treeNode = treeNode.Parent;
treeNode.Expand();
}
if (problemValue.Contains(":"))
treeNode.Text += problemValue.Split(':')[1];
return;
}
// Print each node recursively.
foreach (TreeNode tn in treeNode.ChildNodes)
{
PrintRecursive(tn, problemValue);
}
}
treeNode.Checked = true works fine!
treeNode.Expand() work great!
however treeNode.Text += problemValue.Split(':')[1]; does nothing!
the value of problemValue is "111:someproblem"
what am i doing wrong?
You need to move
if (problemValue.Contains(":"))
treeNode.Text += problemValue.Split(':')[1];
above the while statement.
The problem is that while you are expanding the parents, you are updating the value of treeNode, so when you try to set the text of treeNode, you are actually at one of the parent nodes.
If you are wanting to see how to do this check out this previous StackOverFlow Posting as well for additional ideas on how to Enumerate TreeNodes Implementing IEnumerable
if you are wanting to print TreeNodes Recursively look at this example
private void PrintRecursive(TreeNode treeNode)
{
// Print the node.
System.Diagnostics.Debug.WriteLine(treeNode.Text);
MessageBox.Show(treeNode.Text);
// 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);
}
}
If you want to do this as IEmumerable try the following below
public static class Extensions
{
public static IEnumerable<T> GetRecursively<T>(this IEnumerable collection,
Func<T, IEnumerable> selector)
{
foreach (var item in collection.OfType<T>())
{
yield return item;
IEnumerable<T> children = selector(item).GetRecursively(selector);
foreach (var child in children)
{
yield return child;
}
}
}
}
Here's an example of how to use it
TreeView view = new TreeView();
// ...
IEnumerable<TreeNode> nodes = view.Nodes.
.GetRecursively<TreeNode>(item => item.Nodes);
Im using c#.net windows form application. I have a xml file .I need to populate this xml file into a tree view. I can do that using "xml document" but i need to do it using xElement.
Please refer to the article Populating a TreeView Control from XML, which says
This post describes how to populate a WinForms TreeView control from an XML file assuming you are targeting the .NET Framework Version 3.5.
XElement doc = XElement.Load("testXML.xml");
TreeNode stateNode;
TreeNode regionNode;
foreach (XElement state in doc.Descendants("State"))
{
stateNode = treeView1.Nodes.Add(state.Attribute("name").Value);
foreach (XElement region in state.Descendants("Region"))
{
regionNode =
stateNode.Nodes.Add(region.Attribute("name").Value);
foreach (XElement area in region.Descendants("Area"))
{
regionNode.Nodes.Add(area.Attribute("name").Value);
}
}
}
The following Class loads your .xml into an XElement collection then iterates over it, adding nodes according to their position in the original document and using XML node attributes for tree node naming:
using System.Windows.Forms;
using System.Xml.Linq;
namespace _Solution.Class
{
class Load
{
public void tree_pop(TreeView treeview)
{
treeview.Nodes.Clear();
XElement doc = XElement.Load("xml_file.xml");
TreeNode root = new TreeNode("root");
treeview.Nodes.Add(root);
add_nodes(root, doc);
treeview.ExpandAll();
}
private void add_nodes(TreeNode t_node, XElement x_node)
{
foreach (XElement node in x_node.Elements())
{
TreeNode n_node = t_node.Nodes.Add(node.Attribute("name").Value);
add_nodes(n_node, node);
if (n_node.Nodes.Count == 0) n_node.EnsureVisible();
}
}
}
}
Instantiate and call as follows:
Load load = new Load();
private void Form1_Load(object sender, EventArgs e)
{
load.tree_pop(treeview);
}
What's happening in tree_pop is that you're clearing your treeview of any nodes that may already exist, loading your .xml document into an XElement collection, establishing your treeview's root node, calling add_nodes to iterate over the XElement collection then expanding the treeview nodes.
What's happening in add_nodes is that you're iterating over the XElement collection as passed from tree_pop, creating and adding a new node to the treeview then searching each XElement for children and, if found, adding those to the node you just added to the tree.
For copy / paste, remember to adjust your Class namespace to match that of your solution.
Try the following:
var data = XElement.Load(source.xml);
foreach (XElement single in data.Elements())
{
treeNode.Nodes.Add(single.Element("name of element").Value);
}