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();
}
}
}
Related
You need to create a binary search tree, and then copy the tree and display in the TreeView.
tree creation method
public DTreeNode Created(DTreeNode root,char temp, int nums) //temp - information field, nums - key
{
if (root == null)
{
root = new DTreeNode(temp, nums);
root.Left = null;
root.Right = null;
}
else
{
if (nums < root.Key)
{
root.Left = Created(root.Left, temp, nums);
}
else
{
root.Right = Created(root.Right, temp, nums);
}
}
return root;
}
Methods for outputting a tree in TreeView
public void Show(TreeView tree, DTreeNode root)
{
tree.Nodes.Clear();
if (root != null)
{
tree.Nodes.Add(root.Info + " (" + root.Key + ")");
KLP(tree.Nodes[0], root.Left);
KLP(tree.Nodes[0], root.Right);
}
}
public void KLP(TreeNode node, DTreeNode place)
{
if (place != null)
{
TreeNode branch = node.Nodes.Add(place.Info + " (" + place.Key + ")");
KLP(branch, place.Left);
KLP(branch, place.Right);
}
}
But how to copy a binary search tree and display it in a TreeView I don’t know. Please help, I can’t do it already 5 days. All work is done in Windows Forms.
EDIT:
Right thanks for helping earlier, I have been using and the step into and step over and it looks to be working but the nodes are not being deleted and I'm not sure why.
I actually use 5 arguments for the BST but just using the one for testing purposes. It compares and finds if it has any children no problem. Just wont set it to null.
only testing nodes with 0 or 1 children.
main
Tree aTree = new Tree();
aTree.InsertNode("a");
aTree.InsertNode("s");
aTree.InsertNode("3");
aTree.InsertNode("1");
aTree.InsertNode("p");
aTree.PreorderTraversal();
aTree.RemoveNode("p");
aTree.RemoveNode("3");
aTree.PreorderTraversal();
Console.ReadKey();
My Delete Methods are:
Tree Node
public void Remove(TreeNode root, TreeNode Delete) {
if (Data == null) {
}
if (Delete.Data.CompareTo(root.Data) < 0) {
root.nodeLeft.Remove(root.nodeLeft, Delete);
}
if (Delete.Data.CompareTo(root.Data) > 0) {
root.nodeRight.Remove(root.nodeRight, Delete);
}
if (Delete.Data == root.Data) {
//No child nodes
if (root.nodeLeft == null && root.nodeRight == null) {
root = null;
}
else if (root.nodeLeft == null)
{
TreeNode temp = root;
root = root.nodeRight;
root.nodeRight = null;
temp = null;
}
//No right child
else if (root.nodeRight == null)
{
TreeNode temp = root;
root = root.nodeLeft;
root.nodeLeft = null;
temp = null;
}
//Has both child nodes
else
{
TreeNode min = minvalue(root.nodeRight);
root.Data = min.Data;
root.nodeRight.Remove(root.nodeRight, min);
}
}
}
Find Min
public TreeNode minvalue(TreeNode node)
{
TreeNode current = node;
/* loop down to find the leftmost leaf */
while (current.nodeLeft != null)
{
current = current.nodeLeft;
}
return current;
}
Tree
public void RemoveNode(string Nation)
{
TreeNode Delete = new TreeNode(Nation);
root.Remove(root, Delete);
}
Remove is of return type void, but you're trying to assign it to root.nodeLeft and root.nodeRight, causing your type conversion error.
In general your Remove function needs to return the root of the sub-tree as the result, as in
public void Remove(TreeNode root, TreeNode Delete) {
if (Data == null) {
return null;
}
if (Delete.Data.CompareTo(root.Data) < 0) {
root.nodeLeft = (root.nodeLeft.Remove(root.nodeLeft, Delete));
return root;
}
... and so on.
Otherwise, since your nodes don't refer to their parents, there would be no way for the parent to know that the child node is gone, or that a new node is now at the root of the sub-tree.
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
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 have a Treeview where on selecting a node the attributes and values has to be displayed in listbox.
In treeView1_AfterSelect, the text parsing code depends on the textual representation for a node in the tree view, which can be changed at any time and break the entire logic of list display. This strong dependency between the tree view and the list display should be eliminated by binding nodes in the treeview to nodes of the XML document, so that the raw Xml data can be used to display text in the list.What should i write here?
private static void AddingNodesToTree(XmlNode xmlNode,TreeNode tnode)
{
//Adding nodes to tree while looping through the entire XML file
if (xmlNode.HasChildNodes)
{
XmlNodeList nodeList = xmlNode.ChildNodes;
for (int i = 0; i <= nodeList.Count - 1; i++)
{
XmlNode xmladdtreeNode = xmlNode.ChildNodes[i];
String nodetype = "" + xmladdtreeNode.NodeType;
if (nodetype.Equals("Text") || nodetype.Equals("Comment"))
{
tnode.Nodes.Add(new TreeNode(xmladdtreeNode.InnerText));
}
else
{
String name = "<" + xmladdtreeNode.Name;
XmlAttributeCollection attCol = xmladdtreeNode.Attributes;
foreach (XmlAttribute xmlatt in attCol)
{
name += " " + xmlatt.Name + "=\"" + xmlatt.Value + "\"";
}
name += ">";
TreeNode tn = new TreeNode(xmladdtreeNode.Name);
tn.Text = name;
tnode.Nodes.Add(tn);
TreeNode treeNode = tnode.Nodes[i];
AddingNodesToTree(xmladdtreeNode,treeNode);
}
}//for
}//if
else
{
tnode.Text = xmlNode.OuterXml.Trim();
}//else
}//AddingNodesToTree
//To show Attributes and values of selected Nodes.
private void treeView1_AfterSelect(object sender,TreeViewEventArgs e)
{
TreeNode treenode = e.Node; //Node selected in Treeview
String text = treenode.Text;
String relevent = text;
Boolean flag = true;
while (flag)
{
int SpaceIndex = relevent.IndexOf(" ");
if (SpaceIndex != -1)
{
int indexofEqual = relevent.IndexOf('=', SpaceIndex);
if (indexofEqual != -1)
{
int indexOFValue = relevent.IndexOf("\"", indexofEqual + 2);
if (indexOFValue != -1)
{
String attribute = relevent.Substring(SpaceIndex + 1, indexofEqual - SpaceIndex - 1);
String value = relevent.Substring(indexofEqual + 2, indexOFValue - indexofEqual - 2);
listBox1.Items.Add("Attribute : " + attribute + " Value : " + value);
relevent = relevent.Substring(indexOFValue);
}
else
{
listBox1.Items.Add("Bad format of the xml file for this node");
flag = false;
}
}
else
{
flag = false;
}
}
else
{
flag = false;
}
}
}//AfterSelect()
Thanks....
If I understand the question correctly you want to get back to the XmlNode when a TreeNode is selected. The usual solution is to store the XmlNode in the Tag property:
TreeNode tn = new TreeNode();
tn.Text = name;
tn.Tag = xmladdtreeNode;
and in the AfterSelect
TreeNode treenode = e.Node;
XmlNode xmlNode = (XmlNode) treeNode.Tag;
i tried this but got the NullRefrenceException at this line
foreach (XmlAttribute xmlatt in attCol) on attcol
This is the code i have written..
private void treeView1_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
{
listBox1.Items.Clear();
XmlNode xNode = e.Node.Tag as XmlNode;
XmlAttributeCollection attCol = xNode.Attributes;
foreach (XmlAttribute xmlatt in attCol)
{
listBox1.Items.Add(xmlatt.Name);
listBox1.Items.Add(xmlatt.Value);
}
} //AfterSelect()