How to add a child of a child? - c#

I'm a beginner in C# and have a simple question about TreeView.
I want to do something like this:
> -Root
> -child1
> -child2
> -child3
> -....
I have this:
child.Text = des[j];
root.Nodes.Add(child);
But it just yields something like this:
> -Root
> -child1
I want:
To have a child of a child.
To create 10 TreeNodes in a for statement.
With different names like: root1, root2, root3, etc.
for (i = 0; i < 10; i++)
{
TreeNode root = new TreeNode();
}

You need to add the TreeNode to the Nodes collection of the child, not the root.
child.Text = des[j];
root.Nodes.Add(child);
TreeNode NextChild = new TreeNode();
NextChild.Text = "something";
child.Nodes.Add(NextChild);
For your second Question, you would need to store those treenodes in some kind of datastructure. If you want to name each one, a hashtable would be a good bet.
Hashtable myHT = new Hashtable();
for (int i = 0; i < 10; i++)
{
TreeNode root = new TreeNode();
myHT.Add("Root" + i, root);
}
You would then access them like,
TreeNode myRoot = (TreeNode)myHT["Root1"];
If you are comfortable with Generics you can use the System.Collections.Generic.Dictionary instead for a generic version.

You only need to keep track of the current node and the child to be inserted.
At i = 0, the current node value is the root node.
At i > 0, the current node value is the last child node inserted.
Then, you can try something like this...
TreeNode current = new TreeNode(); // Root node.
current.Text = string.Format("Root");
for (int i = 0; i < 10; i++)
{
TreeNode child = new TreeNode();
child.Text = string.Format("Child: {0}", i);
current.Nodes.Add(child);
current = child;
}
The result of this code will be:
Root
Child: 0
Child: 1
Child: 2

Related

How can I add child nodes to a treeview with deciding the depth level?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Treeview_Test
{
public partial class Form1 : Form
{
int numberofroots = 1000;
int childsnum = 50;
int leveldepth = 0;
public Form1()
{
InitializeComponent();
AddNodes();
}
private void AddNodes()
{
advancedTreeView1.Nodes.Clear();
for (int i = 0; i < numberofroots; i++)
{
advancedTreeView1.Nodes.Add("New Node " + i.ToString());
TreeNode subnode = advancedTreeView1.Nodes[i];
if(allRootsWithChilds.Checked)
{
subnode.Nodes.Add("New Node " + i.ToString());
}
else
{
if (i < childsnum)
{
subnode.Nodes.Add("New Node " + i.ToString());
}
}
}
}
private void allRootsWithChilds_CheckedChanged(object sender, EventArgs e)
{
AddNodes();
}
}
}
Now if the checkbox is checked it will add one child to all the root nodes. All the 1000 root nodes will have one child. If unchecked only the first 50 root nodes out of the 1000 will have one child.
What I want to do now is if the checkbox is checked or not the root nodes that have once child I want to decide the depth level. For example if the depth level is 1 then the first 50 root nodes or all the root nodes will have one child.
But if the depth level is for example 4 then each of the root nodes if it's 50 or all of them will have 4 childs :
Node0
Node1
Node2
Node3
Node4
Node1
Node1
Node2
Node3
Node4
....
Node49
Node1
Node2
Node3
Node4
The variable childsnum decide how many root nodes will have childs.
The variable leveldepth should decide how deep to add childs to each root node.
And then I want to add another int variable to decide on each level how many childs to have.
For example in level 3 there will be 50 nodes for each root node.
And at level 1 there will be only 1 node for each root nodes.
I think all you're missing is the logic to continue to add children to the next node. All you have to do is create another loop based on the value of leveldepth, and continue to set subNode equal to subNode.Nodes[0] in the loop.
Note that we can also use the return value of Nodes.Add (which is the node we just added) to set our subnode variable:
private void AddNodes()
{
advancedTreeView1.Nodes.Clear();
for (int i = 0; i < numberOfRoots; i++)
{
TreeNode subnode = advancedTreeView1.Nodes.Add("New Node " + i);
if (allRootsWithChilds.Checked || i < childCount)
{
for (int j = 0; j < depthLevel; j++)
{
// Add a new child node and set subnode to the new node we just added
subnode = subnode.Nodes.Add(subnode.Text);
}
}
}
}

How to expand a new added node in TreeView

I have a TreeView in my form, I need to add programmatically a new node on particolar mouse event. Then I need to expand the tree just to the new added node. I try to call the function Expand() on the new added node but I does not works.
This is a snippet of my code:
TreeNodeCollection tree = treeViewProtocolli.Nodes["Radice"].Nodes["ModBus"].Nodes;
if (tree != null)
{
TreeNode node = new TreeNode();
node.Text = "MBRTU";
node.Name = "MBRTU";
node.Tag = "BASE";
node.ForeColor = System.Drawing.Color.Red;
tree.Add(node);
TreeNode skBase = treeViewProtocolli.Nodes["Radice"].Nodes["ModBus"].Nodes["MBRTU"];
if(skBase != null)
{
TreeNode sknode = new TreeNode();
sknode.Text = nome + " -> [Slave = " + slave + " | Indirizzo = " + indirizzo +
" | Funzione = " + funzione + " | Abilitato = " + abil + " | Lunghezza blocco = " + lunghezza + "]";
sknode.Name = "MBRTU";
skBase.Nodes.Add(sknode);
sknode.Expand();
}
}
Any suggestion? Thanks.
You can call EnsureVisible method of node. It ensures that the tree node is visible, expanding tree nodes and scrolling the tree view control as necessary.
For example:
var node = treeView1.Nodes[0].Nodes[0].Nodes.Add("something");
node.EnsureVisible();
Use TreeNode.Expand() on every node from the root to the leaf you wanted to be expanded, using Expand on the leaf node or the node you want to expand make only the node itself to show its subchildren.
ex. root -> nextnode1 -> somennode2
If you want to be expanded truout somennode2 you should expand all of its parrent nodes (root.expand,nextnode1.expand and if you want you last node expanded somennode2.expand.
First of all, thanks to all those who answered me.
I've find an easy solution: first I build a List with all the parent of the desidered node to expand, then i browse the list backwards to expand each TreeNode. This is my code.
private void OpenTree(TreeNode node)
{
List<TreeNode> parents = new List<TreeNode>();
parents.Add(node); // Add the actual node to expand
TreeNode actPa = node;
do
{
actPa = actPa.Parent;
if (actPa != null)
parents.Add(actPa); // Add all the parent node
}
while (actPa != null);
if(parents.Count > 0)
{
for(int iRep = parents.Count - 1; iRep >= 0; iRep --)
{
parents[iRep].Expand();
}
}
}

how to append node to a specific place in xml file

I have an XML file like this, in it there is more than one table and I am trying to add a new node at the end of a specific table in the xml file. The user will choose the table and enter his data into a DataGridView.
<?xml version="1.0" encoding="UTF-8"?>
<table name="emloyees">
<emloyees>
<emp_num>employee 1</emp_num>
<department>sales</department>
<salary>1000</salary>
</employees>
<employees>
<emp_num>employee 2</emp_num>
<department>IT</department>
<salary>2000</salary>
</employees>
((for example I want to add new employees node here))
<table name="projects">
<projects>
<proj_num>project 1</proj_num>
<name>hosbital system</name>
<num_mempers>5 members</num_mempers>
</projects>
<projects>
<proj_num>project 2</proj_num>
<name>library system</name>
<num_mempers>4 members</num_mempers>
</projects>
</table>
</table>
I wrote this code, but instead of inserting a new node, the last node of the table gets replaced with the new node instead. How do I fix this?
private void button4_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load("Data.xml");
string tablename = comboBox1.SelectedItem.ToString();
XmlNodeList row = doc.GetElementsByTagName(tablename);
int c = row.Count;
for (int j = 0; j < dataGridView1.Rows.Count - 1; j++)
{
XmlNodeList child = row[c - 1].ChildNodes;
XmlElement element = doc.CreateElement(tablename);
for (int k = 0; k < child.Count; k++)
{
XmlElement node = doc.CreateElement(child[k].ToString());
child[k].InnerText = dataGridView1.Rows[j].Cells[k].Value.ToString();
element.AppendChild(node);
}
XmlElement root = doc.DocumentElement;
root.AppendChild(element);
doc.Save("Data.xml");
}
dataGridView1.Rows.Clear();
MessageBox.Show("Successfully Added !!");
}
It seems the problem is here.
for (int k = 0; k < child.Count; k++)
{
XmlElement node = doc.CreateElement(child[k].ToString());
child[k].InnerText = dataGridView1.Rows[j].Cells[k].Value.ToString(); // < here
element.AppendChild(node);
}
You are setting the child[k]'s inner text, not the value of the node you created.
Change child[k] to node
node.InnerText = dataGridView1.Rows[j].Cells[k].Value.ToString();
Your title asks to place the node at a specific place, but your code isn't doing it. You'll need to use the parentNode.InsertAfter(newNode, refNode) method.
So instead of root.AppendChild(element);. Which puts the node at the bottom of the file, use root.InsertAfter(element, child[child.Count - 1]) to put the new node after the last child type you are setting.
AppendChild MSDN docs.

Recursively adding a ChildNode to a Parent Node

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

TreeNode Breadth first enum?

Right now my loop is
for (TreeNode n = e.Node.FirstNode; n != null; n = n.NextNode)
and my data is something like
a
a1
a2
b
b1
I want to enum breadth only (a, b etc, not a1, a2 etc). How do i do this?
Breadth first enumeration is typically done by using a queue of some sort as an ancillary data structure.
First push the root onto the queue.
Then, while there is something in the queue:
Pop the first item from the front of
the queue.
Push its children onto the end of the queue.
Process the item you popped.
Try
foreach (TreeNode n in e.Node.Parent.Nodes)
you might have to check for a null parent and use
TreeNodeCollection nodes;
if(e.Node.Parent != null)
{
nodes = e.Node.Parent.Nodes;
}
else
{
nodes = e.Node.TreeView.Nodes;
}
This should cover the breadth first algorithm (sorry I haven't tested it)
Queue<TreeNode> currentLevel = new Queue<TreeNode>( nodes );
Queue<TreeNode> nextLevel = new Queue<TreeNode>();
while( currentLevel.Count > 0 )
{
while( currentLevel.Count > 0 )
{
TreeNode n = currentLevel.Dequeue();
// Add child items to next level
foreach( TreeNode child in n.Nodes )
{
nextLevel.Enqueue( child );
}
}
// Switch to next level
currentLevel = nextLevel;
nextLevel = new Queue<TreeNode>();
}
Modify code provided by bstoney
1. push root node to currentLevel queue
2. mark nextLevel = new Queue();
Queue<TreeNode> currentLevel = new Queue<TreeNode>();
Queue<TreeNode> nextLevel = new Queue<TreeNode>();
// 1. push root to the queue
currentLevel.Enqueue(treeView1.Nodes[0]);
// pop the first item from the front of the queue
while (currentLevel.Count > 0)
{
while (currentLevel.Count > 0)
{
TreeNode n = currentLevel.Dequeue();
Console.WriteLine(n.Text);
// Add child items to next level
foreach (TreeNode child in n.Nodes)
{
nextLevel.Enqueue(child);
}
}
// Switch to next level
currentLevel = nextLevel;
// 2. mark this line
//nextLevel = new Queue<TreeNode>();
}

Categories

Resources