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);
Related
I want to get the node's keys just 'only in view' on treeview.
Here is the example;
I am using below code to get all node recursively. It just return all nodes key as expected. however i need to get the keys that only in treeview's view;
public void PrintNodesRecursive(UltraTreeNode oParentNode)
{
if (oParentNode.Nodes.Count == 0)
{
return;
}
foreach (UltraTreeNode oSubNode in oParentNode.Nodes)
{
MessageBox.Show(oSubNode.Key.ToString());
PrintNodesRecursive(oSubNode);
}
}
private void ultraButton3_Click(object sender, EventArgs e)
{
PrintNodesRecursive(ultraTree1.Nodes[0]);
}
I don't know i should follow different path or just reorganize code.
I just stacked after many hours. Need your help.
You can find the first visible node using Nodes collection and IsVisible property of the Node. Then create a recursive method which uses NextVisibleNode to find the next visible node in TreeView.
private void button1_Click(object sender, EventArgs e)
{
var visibleNodes = GetVisibleNodes(treeView1).ToList();
}
public IEnumerable<TreeNode> GetVisibleNodes(TreeView t)
{
var node = t.Nodes.Cast<TreeNode>().Where(x => x.IsVisible).FirstOrDefault();
while (node != null)
{
var temp = node;
node = node.NextVisibleNode;
yield return temp;
}
}
Also as another option, you can rely on Descendants extension method to flatten the TreeView and then using IsVisible property, get all visible nodes.
In the textBox2 i type a word/string for example Hello and i checked Hello does exist but it never color it in Yellow. I used a breakpoint and it never pass this line and color it in Yellow: if (tn.Text == this.textBox2.Text)
private void FindByText()
{
TreeNodeCollection nodes = treeView1.Nodes;
foreach (TreeNode n in nodes)
{
FindRecursive(n);
}
}
private void FindRecursive(TreeNode treeNode)
{
foreach (TreeNode tn in treeNode.Nodes)
{
// if the text properties match, color the item
if (tn.Text == this.textBox2.Text)
tn.BackColor = Color.Yellow;
FindRecursive(tn);
}
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
FindByText();
}
EDIT
This is an example image of what i want to do: Free search text: I type in textBox2 for example na or hello and it will highlight anywhere the places hello for example. in nodes names in nodes childs inside nodes anyhwere just like it is in the image.
Ofcourse if i type only a or b or c don't highlight it but do highlight any string i type in the textBox2 that is longer then 2 letters
The image is only for example to show what i need to it to do:
You never check the top level, only the their children
(note: the way you do the comparison may need fixing as others have said, but that is a different issue.)
private void FindByText()
{
TreeNodeCollection nodes = treeView1.Nodes;
foreach (TreeNode n in nodes)
{
if (n.Text == this.textBox2.Text)
n.BackColor = Color.Yellow;
FindRecursive(n);
}
}
Use following code:
private void FindRecursive(TreeNode treeNode)
{
// Use this condition if you want a case sensitive search, else use treeNode.Text.ToLower() == this.textBox2.Text.ToLower()
if (treeNode.Text == this.textBox2.Text)
treeNode.BackColor = Color.Yellow;
else
treeNode.BackColor = Color.White; // Here use your default background color
foreach (TreeNode tn in treeNode.Nodes)
{
FindRecursive(tn);
}
}
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);
}
}
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
after tweaking my code for a bit I ended up with this little proof of concept code:
private void button1_Click(object sender, EventArgs e)
{
DepartmentRepository repo = new DepartmentRepository();
var entries = repo.FindAllDepartments(); //Returns IQueryable<Department>
treeView1.BeginUpdate();
var parentDepartments = entries.Where(d => d.IDParentDepartment == null).ToList();
foreach (var parent in parentDepartments)
{
TreeNode node = new TreeNode(parent.Name);
treeView1.Nodes.Add(node);
var children = entries.Where(x => x.IDParentDepartment == parent.ID).ToList();
foreach (var child in children)
{
node.Nodes.Add(child.Name);
}
}
treeView1.EndUpdate();
}
It places every parent Department in the TreeView control and then correctly assigns it's children to the correct Parent.
My problem is, how do I handle children of children? Nested Departments.
I can't seem to wrap my head around it.
Thanks for any guidance.
You need to use recursion:
void LoadNode(TreeNode node, Department d)
{
foreach (var child in d.Children)
{
TreeNode childNode = node.Nodes.Add(child.Name);
LoadNode(childNode, child); // calls the method again for the next level
}
}
Have a look here for sample of recursion:
http://www.codeproject.com/KB/cs/recursionincsharp.aspx