Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a list for a Treenode

I know this must be real easy but I just can't get it to work... I am trying to make a List for extjs Tree by comparing two columns from differnt rows and putting them as a Node or a leaf accordingly. this is my sample data

ListA  ListB  labelName
 NY           Parent1
        NY    Leaf1
 HI           Parent2
 AK           Parent3

and this is my c# end... so when I match NY, I am supposed to have Parent1 as node and Leaf1 as its leaf and not for HI or AK... but doing this throws me all data as Parent.. even the leaf.

            SqlCommand cmd = con.CreateCommand();

            comd.CommandText = "SELECT * FROM myTable";
            con.Open();
            SqlDataReader reader = comd.ExecuteReader();
            while (reader.Read())
            {
                City MyData = new City();

                MyData.ListA = reader["ListA"].ToString().Trim();
                MyData.ListB = reader["ListB"].ToString().Trim();
                MyData.labelName = reader["labelName"].ToString().Trim();
                giveData.Add(MyData);
            }

            int count = 1;

            List<TreeNode> myNode = new List<TreeNode>();
            foreach (City MyData in giveData)
            {
                // 1st foreach
                    if (MyData.ListA != "")
                    {

                        TreeNode treeNode = new TreeNode();
                        treeNode.id = count++;
                        treeNode.name = MyData.labelName;
                        treeNode.leaf = false;

                        List<TreeNode> Level1 = new List<TreeNode>();
                        foreach (City labelName  in giveData)
                        {
                            if (labelName.ListA == labelName.ListB)
                            {// 2nd foreach
                                TreeNode node1 = new TreeNode();
                                node1.id = count++;
                                node1.name = labelName.labelName;
                                node1.leaf = true;

                                Level1.Add(node1);
                            }
                        }

                        treeNode.children = Level1;
                        myNode.Add(treeNode);
                }
            }
            return JsonConvert.SerializeObject(myNode);

Should I use array to store each record and compare them instead... I am out of ideas... I am sure there is a better way to accomplish this... Please help

like image 890
EagleFox Avatar asked Dec 26 '12 21:12

EagleFox


People also ask

How is TreeNode defined?

Interface TreeNode. Defines the requirements for an object that can be used as a tree node in a JTree. Implementations of TreeNode that override equals will typically need to override hashCode as well.

What is TreeNode C#?

The TreeNode label is set by setting the Text property explicitly. The alternative is to create the tree node using one of the TreeNode constructors that has a string parameter that represents the Text property. The label is displayed next to the TreeNode image, if one is displayed.

How do I know if TreeView node is selected?

Solution 1Use TreeView. SelectedNode[^] property, which get or set selected node for currently selected Treeview. If no TreeNode is currently selected, the SelectedNode property is a null reference (Nothing in Visual Basic).

Which method is used to add child node in TreeView control?

To add nodes programmatically Use the Add method of the tree view's Nodes property.


2 Answers

Assuming the data is the way you state and the "parents" will come before any leaves, here's a single pass way I came up with to create the tree:

[Irrelevant Code Snipped]

Update: LINQ using Dictionary<string, List<TreeNode>>

I created a new class TreeNode and some sample data for testing:

var MyData = new List<City>
                  {
                     new City {ListA = "AK", ListB = "", labelName = "Alaska"},
                     new City {ListA = "HI", ListB = "", labelName = "Hawaii"},
                     new City {ListA = "", ListB = "HI", labelName = "Hawaii Leaf 1"},
                     new City {ListA = "", ListB = "HI", labelName = "Hawaii Leaf 2"},
                     new City {ListA = "NY", ListB = "", labelName = "New York"},
                     new City {ListA = "", ListB = "NY", labelName = "New York Leaf 1"},
                     new City {ListA = "", ListB = "NY", labelName = "New York Leaf 2"}
                  };

Here's the new method that basically creates 2 lists, 1 for the parents and 1 for the leaves. I then loop through the leaves to find any matching parents and add the leaves to it:

var index = 0;
var parents = (from p in MyData
               where p.ListB == ""
               select p).ToDictionary(p => p.ListA, p => new TreeNode { id = index++, name = p.labelName, leaf = false });

var leaves = (from l in MyData
              where l.ListA == ""
              group l by l.ListB into stateGroup
              select stateGroup).ToDictionary(g => g.Key, g => g.ToList());

foreach (var leaf in leaves.Where(leaf => parents.ContainsKey(leaf.Key)))
{
    parents[leaf.Key].children =
        leaf.Value.Select(l => new TreeNode {id = index++, name = l.labelName, leaf = true}).ToList();
}

var myNode = parents.Select(p => p.Value).ToList();

return JsonConvert.SerializeObject(myNode);

I think this should be more efficient than using lists and the List.Find()

like image 91
CAbbott Avatar answered Sep 30 '22 13:09

CAbbott


Your best bet would probably be Linq - I created a quick and dirty VB.Net solution to move you in the right direction - The main part being the SECOND Linq statement...

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim x As New List(Of City)

    x.Add(New City With {.ListA = "NY", .ListB = "", .Leaf = "Parent1"})
    x.Add(New City With {.ListA = "", .ListB = "NY", .Leaf = "Leaf1"})
    x.Add(New City With {.ListA = "HI", .ListB = "", .Leaf = "Parent2"})
    x.Add(New City With {.ListA = "AK", .ListB = "", .Leaf = "Parent3"})

    tv1.Nodes.AddRange((From y In x Where y.ListA <> "" Select New TreeNode With {
                                                                    .Name = y.ListA,
                                                                    .Text = y.Leaf}).ToArray)

    For Each nd As TreeNode In tv1.Nodes
        Dim Nm As String = nd.Name
        nd.Nodes.AddRange((From y In x Where y.ListB = Nm Select New TreeNode(y.Leaf)).ToArray)
    Next
End Sub

Simply put, you populate the first ste of parent nodes, then you just loop through all the nodes and populate them with any nodes where ListB = Node's name.

Hope this helps move you in the right direction

like image 33
John Bustos Avatar answered Sep 30 '22 13:09

John Bustos