How to add a child node to a dynamically added child node - c#

I am having a treeview on my main form
I have my code from a from to main form is as follows
Buttonclick
StrNode = string.Empty;
StrNode = "Batch" + Append.Batchcnt.ToString() + "(" + strSelectedClassCode + ")";
frmmain.loadFromForm(StrNode, true, strSelectedClassCode);
On my main form i have my code as follows
public void loadFromForm(string strNode, bool bResult, string strStandardClsCode)
{
if (Append.oldbatchcontrol != strNode)
{
if (tvwACH.SelectedNode.Text == "FileHeader")
{
tvwACH.SelectedNode.Nodes.Add(strNode);
}
if (tvwACH.SelectedNode.Text == "BatchHeader")
{
tvwACH.SelectedNode.Nodes.Add(strNode);// After this i have to add another node as a child to that added node and also if a node with particular name exists i would like to write the text with a count value appended
}
}
}
So that my treeview should be as follows
ACH
|->Some.txt
|->Fileheader
|->BatchHeader
|->Batch1
|->Entry1
|->Entry2 and so on // These two should be added dynamically after that Batch1

Use this instead :
public void loadFromForm(string strNode, bool bResult, string strStandardClsCode)
{
if (Append.oldbatchcontrol != strNode)
{
if (tvwACH.SelectedNode.Text == "FileHeader")
{
tvwACH.SelectedNode.Nodes.Add(strNode);
}
if (tvwACH.SelectedNode.Text == "BatchHeader")
{
TreeNode node = tvwACH.SelectedNode.Nodes.Add(strNode,strNode);// After this i have to add another node as a child to that added node and also if a node with particular name exists i would like to write the text with a count value appended
node.Nodes.Add(...);
}
}
}

You usually need a recursive function to build a tree. For example:
private void AddNode(NodeParent, Data)
{
Node oNode;
//Check if this is the first node
if (NodeParent ==null)
{
oNode = new Node(Data.Name);
}
//Step though each child item in the data
foreach(DataItem in Data)
{
//Add the node
this.AddNode(oNode, DataItem);
}
oNode.Nodes.Add(new Node(Data));
}
This code is a rough guide, but it should give you an idea.

Related

C# - XML Validation with XSD - Presenting results in Listbox and Treeview

Hello all!
I have the following use case:
My Winform-App is validating a prarticular XML against the XSD and displays the errors (if any) in a listbox (this works fine). In addition to that I load the validated XML into a treeview.
Now, what I would like to achieve is to give the user the ability to doubleklick the error in the listbox to have then the treeview selecting the relevant element which caused the error.
I'm a little stuck with this actually. I now the row number of the error, but I can't select the relevant node in the treeview by using the row number.
Does anybody have an idea how I can achieve this?
Any hint is very much appreciated :)
kind regards
UPDATE:
Code filling the treeview:
doc.Load(XMLDocPath);
XmlNodeTree root = new XmlNodeTree(0, doc.LastChild);
treeDGUXml.Nodes.Add(root);
FillTreeView(root.Nodes, doc.LastChild.ChildNodes);
And the method:
private void FillTreeView(TreeNodeCollection c, XmlNodeList l)
{
if (l == null)
{
return;
}
foreach (XmlNode e in l)
{
XmlNodeTree n = new XmlNodeTree(nRow, e);
c.Add(n);
FillTreeView(n.Nodes, e.ChildNodes);
}
And the Class:
public class XmlNodeTree : TreeNode
{
private XmlNode mNode;
public XmlNode Node
{
get { return mNode; }
}
public XmlNodeTree(int rownumber, XmlNode node)
{
mNode = node;
if (node.NodeType == XmlNodeType.Text)
{
Text = node.InnerText;
}
else
{
Text = rownumber.ToString() + " - " + node.Name;
nRow++;
}
if (node.Attributes != null)
{
foreach (XmlAttribute a in node.Attributes)
{
Text += " " + a.OuterXml;
}
}
}
}
Thank you very much for the hints. I decided to have another approach without treeview. I load the XML into a richtext box with appropriate coloring. This way I can select the relevant text. The user cannot collapse the xml structure, but this now is better than nothing ;) Thank you anyway for your suggestions! –

how to change my Node-Text

i created some symbol without Labels, after dropping my Symbols from Palette, my symbol will automatic be labeled with Text. my problem is that the first Node-Drop from every symbol i´ve created is not labeled, after the second, third, fourth, etc. Node-Drop that node will automatic assigned with Label.
Second requirement i would to know, after dropping my Node, how can i edit my nodeText. by clicking or double-clicking the node.
Here is my Code:
protected void DiagramWebControl1_NodeDropFromPalette(object sender, Syncfusion.Web.UI.WebControls.Diagram.NodeDropFromPaletteEventArgs e)
{
if (e.Node is PathNode || e.Node is Group)
{
PathNode node = e.Node as PathNode;
if (node != null)
{
if (node.FullName == "Prozess Start")
{
node.Name = "Prozess Start";
node.Labels.Add(new Syncfusion.Windows.Forms.Diagram.Label(node, node.Name));
}
else if (node.FullName == "Prozess")
{
node.Name = "Prozess";
node.Labels.Add(new Syncfusion.Windows.Forms.Diagram.Label(node, node.Name));
}
}
else
{
Group gnode = e.Node as Group;
if (gnode.FullName == "Organisationseinheit")
{
gnode.Name = "Organisationseinheit";
gnode.Labels.Add(new Syncfusion.Windows.Forms.Diagram.Label(gnode, gnode.Name));
}
else if (gnode.FullName == "Rolle")
{
gnode.Name = "Rolle";
gnode.Labels.Add(new Syncfusion.Windows.Forms.Diagram.Label(gnode, gnode.Name));
}
else if (gnode.FullName == "Externe Rolle")
{
gnode.Name = "Externe Rolle";
gnode.Labels.Add(new Syncfusion.Windows.Forms.Diagram.Label(gnode, gnode.Name));
}
else if (gnode.FullName == "IT-System")
{
TextNode rtxNode = new TextNode("");
rtxNode.Text = "IT-System";
gnode.Labels.Add(new Syncfusion.Windows.Forms.Diagram.Label(gnode, rtxNode.Text));
}
}
}
Since the node’s FullName is generated uniquely by appending the ‘Model’ to the node’s name by the DiagramWebControl, check whether the dropped node’s FullName and the name given in your code are the same one. If you want to add ‘Labels’ to the node based on their names, then use the node’s ‘Name’ property instead of using FullName.
Refer the Syncfusion’s public forum regarding your requirement of editing nodeText in double-clicking the node.
Here's a link.

Filter a Treeview with a Textbox in a C# winforms app

I have a TreeView in my a C# winform. I would like to be able to add a search functionality through a search box.
Basically as the user types in letters (I'm guessing on the _TextChanged event), I show only the nodes that contain childnodes with the inputed letters...
My TreeView contains 53 parent nodes for a total of over 15000 Nodes so I need something a bit performant. I build my TreeView from a csv that I load into a DataTable and then make queries on to get the Parent nodes with associated child nodes...
UPDATE
I have an idea.
The final aim is that when a user doubleclicks on a child node it gets added to a listView.
I had first implemented this search function in a simple list view where I didn't separate my data into categories.
My idea is that once the user starts typing in things, I turn off my Tree view and show the list view instead...
I'll try and implement and see what it gives performance wise... Any critics on this idea are welcome.
Finally this is what I did, it suits my requirements.
I first make a copy of my TreeView and store into fieldsTreeCache. I then clear the fieldsTree. I then search through the cache and add any node containing my search parameter to the fieldsTree. Note here that once you search, you no longer have the parent nodes that show. You just get all of the end nodes. I did this because if not I had 2 choices:
Expand all the parent nodes containing childs that match but then it was slow and one parent might have 50 children which isn't great visually.
Not expand the parent nodes but then you just get the categories and not the children nodes that you're searching for.
void fieldFilterTxtBx_TextChanged(object sender, EventArgs e)
{
//blocks repainting tree till all objects loaded
this.fieldsTree.BeginUpdate();
this.fieldsTree.Nodes.Clear();
if (this.fieldFilterTxtBx.Text != string.Empty)
{
foreach (TreeNode _parentNode in _fieldsTreeCache.Nodes)
{
foreach (TreeNode _childNode in _parentNode.Nodes)
{
if (_childNode.Text.StartsWith(this.fieldFilterTxtBx.Text))
{
this.fieldsTree.Nodes.Add((TreeNode)_childNode.Clone());
}
}
}
}
else
{
foreach (TreeNode _node in this._fieldsTreeCache.Nodes)
{
fieldsTree.Nodes.Add((TreeNode)_node.Clone());
}
}
//enables redrawing tree after all objects have been added
this.fieldsTree.EndUpdate();
}
Here's a small simple example (with code from msdn) is that a very simple way to filter out the TreeView node displays.
winforms in a tree view you can only add or remove TreeNode.
The search for the nodes can still be improved if the nodes are stored with their data into a dictionary (with a unique key).
using System.Collections;
using System.Windows.Forms;
namespace FilterWinFormsTreeview
{
// The basic Customer class.
public class Customer : System.Object
{
private string custName = "";
protected ArrayList custOrders = new ArrayList();
public Customer(string customername) {
this.custName = customername;
}
public string CustomerName {
get { return this.custName; }
set { this.custName = value; }
}
public ArrayList CustomerOrders {
get { return this.custOrders; }
}
}
// End Customer class
// The basic customer Order class.
public class Order : System.Object
{
private string ordID = "";
public Order(string orderid) {
this.ordID = orderid;
}
public string OrderID {
get { return this.ordID; }
set { this.ordID = value; }
}
}
// End Order class
public static class TreeViewHelper
{
// Create a new ArrayList to hold the Customer objects.
private static ArrayList customerArray = new ArrayList();
public static void FilterTreeView(TreeView treeView1, string orderText) {
if (string.IsNullOrEmpty(orderText)) {
FillMyTreeView(treeView1);
} else {
// Display a wait cursor while the TreeNodes are being created.
Cursor.Current = Cursors.WaitCursor;
// Suppress repainting the TreeView until all the objects have been created.
treeView1.BeginUpdate();
foreach (TreeNode customerNode in treeView1.Nodes) {
var customer = customerNode.Tag as Customer;
if (customer != null) {
customerNode.Nodes.Clear();
// Add a child treenode for each Order object in the current Customer object.
foreach (Order order in customer.CustomerOrders) {
if (order.OrderID.Contains(orderText)) {
var orderNode = new TreeNode(customer.CustomerName + "." + order.OrderID);
customerNode.Nodes.Add(orderNode);
}
}
}
}
// Reset the cursor to the default for all controls.
Cursor.Current = Cursors.Default;
// Begin repainting the TreeView.
treeView1.EndUpdate();
}
}
public static void FillMyTreeView(TreeView treeView1) {
// Add customers to the ArrayList of Customer objects.
if (customerArray.Count <= 0) {
for (int x = 0; x < 1000; x++) {
customerArray.Add(new Customer("Customer" + x.ToString()));
}
// Add orders to each Customer object in the ArrayList.
foreach (Customer customer1 in customerArray) {
for (int y = 0; y < 15; y++) {
customer1.CustomerOrders.Add(new Order("Order" + y.ToString()));
}
}
}
// Display a wait cursor while the TreeNodes are being created.
Cursor.Current = Cursors.WaitCursor;
// Suppress repainting the TreeView until all the objects have been created.
treeView1.BeginUpdate();
// Clear the TreeView each time the method is called.
treeView1.Nodes.Clear();
// Add a root TreeNode for each Customer object in the ArrayList.
foreach (Customer customer2 in customerArray) {
var customerNode = new TreeNode(customer2.CustomerName);
customerNode.Tag = customer2;
treeView1.Nodes.Add(customerNode);
// Add a child treenode for each Order object in the current Customer object.
foreach (Order order1 in customer2.CustomerOrders) {
var orderNode = new TreeNode(customer2.CustomerName + "." + order1.OrderID);
customerNode.Nodes.Add(orderNode);
}
}
// Reset the cursor to the default for all controls.
Cursor.Current = Cursors.Default;
// Begin repainting the TreeView.
treeView1.EndUpdate();
}
}
}
Every node in TreeView has Expanded and IsVisible properties. The number of items which are visible at the same time is limited (TreeView.VisibleCount). Based on this information you can reduce the number of nodes to probe dramatically.
When scanning the node and it's child nodes you can abort recursion as you find the first match inside collapsed node, thus you already know it has at least one child and will be visible anyway.
Perform filtering asynchronously. (use new Task() for instance) Start the first task after minimal number of chars was typed (let's say 3). Every next typed char must cancel the running task and start the new one.

How can I determine if the selected node is a child or parent node in TreeView?

How can I find out if the selected node is a child node or a parent node in the TreeView control?
Exactly how you implement such a check depends on how you define "child" and "parent" nodes. But there are two properties exposed by each TreeNode object that provide important information:
The Nodes property returns the collection of TreeNode objects contained by that particular node. So, by simply checking to see how many child nodes the selected node contains, you can determine whether or not it is a parent node:
if (selectedNode.Nodes.Count == 0)
{
MessageBox.Show("The node does not have any children.");
}
else
{
MessageBox.Show("The node has children, so it must be a parent.");
}
To obtain more information, you can also examine the value of the Parent property. If this value is null, then the node is at the root level of the TreeView (it does not have a parent):
if (selectedNode.Parent == null)
{
MessageBox.Show("The node does not have a parent.");
}
else
{
MessageBox.Show("The node has a parent, so it must be a child.");
}
You can use the TreeNode.Parent property for this.
If its value is a null-reference, the node is at the root level.
TreeView treeView = ...
var selectedNode = treeView.SelectedNode;
if(selectedNode ! = null)
{
if(selectedNode.Parent == null)
{
// Root-level node
}
else
{
// Child node
}
}
else
{
// A node hasn't been selected.
}
Try this
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
Label1.Text = "";
if(e.Node.Parent!= null &&
e.Node.Parent.GetType() == typeof(TreeNode) )
{
Label1.Text = "Parent: " + e.Node.Parent.Text + "\n"
+ "Index Position: " + e.Node.Parent.Index.ToString();
}
else
{
Label1.Text = "This is parent node.";
}
}
For root node is the parent TreeView .. it is possible to check if we compare the types of ->
if (currentNode.Parent.GetType() == typeof(TreeView))
{
// root node
}
treeview.SelectedNode == null
is the best to choose.

Move Node in Tree up or Down

What is the most accurate way to move a node up and down in a treeview. I got a context menu on each node and the selected node should be moved with all its subnodes.
I'm using C# .Net 3.5 WinForms
You can use the following extensions :
public static class Extensions
{
public static void MoveUp(this TreeNode node)
{
TreeNode parent = node.Parent;
TreeView view = node.TreeView;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index > 0)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index - 1, node);
}
}
else if (node.TreeView.Nodes.Contains(node)) //root node
{
int index = view.Nodes.IndexOf(node);
if (index > 0)
{
view.Nodes.RemoveAt(index);
view.Nodes.Insert(index - 1, node);
}
}
}
public static void MoveDown(this TreeNode node)
{
TreeNode parent = node.Parent;
TreeView view = node.TreeView;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index < parent.Nodes.Count -1)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index + 1, node);
}
}
else if (view != null && view.Nodes.Contains(node)) //root node
{
int index = view.Nodes.IndexOf(node);
if (index < view.Nodes.Count - 1)
{
view.Nodes.RemoveAt(index);
view.Nodes.Insert(index + 1, node);
}
}
}
}
Child nodes will follow their parents.
EDIT: Added case that node to move is a root in the TreeView.
While I feel writing this code is a waste of time, given the lack of response to comments by the OP, the least I can do is show how the code example by Le-Savard can be fixed so that muliple clicks of the up or down choice on the context menu ... assuming the context menu is not auto-closed each time and the user is forced to select the same node over and over again ... will do the right thing with the orignally selected node, and not create un-intended side effects :
public static class Extensions
{
public static void MoveUp(this TreeNode node)
{
TreeNode parent = node.Parent;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index > 0)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index - 1, node);
// bw : add this line to restore the originally selected node as selected
node.TreeView.SelectedNode = node;
}
}
}
public static void MoveDown(this TreeNode node)
{
TreeNode parent = node.Parent;
if (parent != null)
{
int index = parent.Nodes.IndexOf(node);
if (index < parent.Nodes.Count - 1)
{
parent.Nodes.RemoveAt(index);
parent.Nodes.Insert(index + 1, node);
// bw : add this line to restore the originally selected node as selected
node.TreeView.SelectedNode = node;
}
}
}
}
Of course this fix, still does not address the fact that in the example code that multiple root nodes cannot be moved (since they are 'parentless) : that's easiliy fixable.
Nor does it address the more interesting case where moving up a top child-node means you make some interpretation of where that "promoted" child code should go : exactly the same "strategic choice" is involved where you "move down" the last child node of a parent node and are thus required to decide where it should go. In Dynami Le-Savard's code : these cases are just ignored.
However, it is a design-choice to restrict child node from only being moved within their parent nodes Nodes collection : a design choice that may be perfectly suitable for one solution.
Similarly, it is a design choice to force a user to select a node and context-click to get a context menu that allows a choice of moving up or down every single time they want to move it : that's not a design choice I'd make : I'd be using drag-and-drop here or buttons that allow repeated rapid-fire relocation of any selected node anywhere in the tree.
By the way I like Dynami Le-Savard's use of extensions here.
Here's a solution that allows you to drag & drop nodes to wherever you want. To move a node to the same level as another node, just hold down shift when dropping the node. This is a really easy way to go compared to the alternatives and their potential problems. Example was written with a more recent version of .Net (4.5).
Note: Be sure and AllowDrop=true on the treeview control otherwise you can't drop nodes.
/// <summary>
/// Handle user dragging nodes in treeview
/// </summary>
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
DoDragDrop(e.Item, DragDropEffects.Move);
}
/// <summary>
/// Handle user dragging node into another node
/// </summary>
private void treeView1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
/// <summary>
/// Handle user dropping a dragged node onto another node
/// </summary>
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
// Retrieve the client coordinates of the drop location.
Point targetPoint = treeView1.PointToClient(new Point(e.X, e.Y));
// Retrieve the node that was dragged.
TreeNode draggedNode = e.Data.GetData(typeof(TreeNode));
// Sanity check
if (draggedNode == null)
{
return;
}
// Retrieve the node at the drop location.
TreeNode targetNode = treeView1.GetNodeAt(targetPoint);
// Did the user drop the node
if (targetNode == null)
{
draggedNode.Remove();
treeView1.Nodes.Add(draggedNode);
draggedNode.Expand();
}
else
{
TreeNode parentNode = targetNode;
// Confirm that the node at the drop location is not
// the dragged node and that target node isn't null
// (for example if you drag outside the control)
if (!draggedNode.Equals(targetNode) && targetNode != null)
{
bool canDrop = true;
while (canDrop && (parentNode != null))
{
canDrop = !Object.ReferenceEquals(draggedNode, parentNode);
parentNode = parentNode.Parent;
}
if (canDrop)
{
// Have to remove nodes before you can move them.
draggedNode.Remove();
// Is the user holding down shift?
if (e.KeyState == 4)
{
// Is the targets parent node null?
if (targetNode.Parent == null)
{
// The target node has no parent. That means
// the target node is at the root level. We'll
// insert the node at the root level below the
// target node.
treeView1.Nodes.Insert(targetNode.Index + 1, draggedNode);
}
else
{
// The target node has a valid parent so we'll
// drop the node into it's index.
targetNode.Parent.Nodes.Insert(targetNode.Index + 1, draggedNode);
}
}
else
{
targetNode.Nodes.Add(draggedNode);
}
targetNode.Expand();
}
}
}
// Optional: The following lines are an example of how you might
// provide a better experience by highlighting and displaying the
// content of the dropped node.
// treeView1.SelectedNode = draggedNode;
// NavigateToNodeContent(draggedNode.Tag);
}

Categories