Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically populate treeview (C#)

I have a table with 3 columns, ID, Name and ParentID. The ID column contains running number which also serves as the primary key. ID will also be the node's Name properties. Name column contain string that will be the treenode's Text attribute, while ParentID is a column contains the node's parent ID.

This is how my table looks like:

ID     Name   ParentID
======================
1      A      0
2      A1     1
3      B      0
4      C      0
5      A2     1
6      B1     3

This table shows that node A is the parent node for node A1 and A2. ParentID equals to "0" means that the node's parent is the root node (hardcoded). E.g., Node A, B and C are root node's children.

I sort the rows by ParentID prior to populating the treeview. I populate the tree view using these two methods (TreeNode node here is the childnode that is being populated into the tree):

    private void SearchParent(TreeView tree, String parentID, TreeNode node)
    {
        // Post: call TraverseParent method to search parent

        TreeNodeCollection collection = tree.Nodes;

        // Search parent recursively
        foreach (TreeNode n in collection)
        {
            TraverseParent(n, parentID, node);
        }
    }

    private void TraverseParent(TreeNode potentialParent, String parentID, TreeNode node)
    {
        // Post: search for parent. When parent is found add child to parent

        // am i the parent that you're looking for?
        if (parentID.CompareTo(potentialParent.Name) == 0)
        {
            // found me! i'm your parent!

            // add child to parent
            potentialParent.Nodes.Add(node);

            // update that the parent for child has been found
            parentFound = true;
        }
        else
        {
            // i'm not your parent

            // continue to look for parent recursively
            foreach (TreeNode n in potentialParent.Nodes)
            {
                TraverseParent(n, parentID, node);
            }
        }
    }

All is well until I drag-and-drop the nodes by making node A the child of node C and commit the changes to the database.

Now my database table looks like this:

ID     Name   ParentID
======================
1      A      4
2      A1     1
3      B      0
4      C      0
5      A2     1
6      B1     3

The next time I run the application, it fails to populate node A1 and A2 into the tree because it could not find their parents. This is because when I sort the rows based on ParentID prior to populating the treeview, the rows are sorted like this:

ID     Name   ParentID
======================
3      B      0
4      C      0
2      A1     1
5      A2     1
6      B1     3
1      A      4

This way, my application will try to populate A1 and A2 nodes into the tree even before node A is created. Therefore the application could not find the parent for node A1 and A2.

Hence, can anyone tell me a way to fix this bug or is there a better way to dynamically populate a treeview?

Thanks.

like image 749
ixora Avatar asked May 30 '12 10:05

ixora


1 Answers

You should use recursion to fill it.

The promised example:

public partial class Form1 : Form
    {
        private class ItemInfo
        {
            public int ID;
            public int ParentID;
            public string Name;
        }

        public Form1()
        {
            InitializeComponent();
            FillTreeView();
        }

        private void FillTreeView()
        {
            var items = new List<ItemInfo>()
            {
                new ItemInfo(){ID = 1, ParentID = 4, Name = "A"},
                new ItemInfo(){ID = 2, ParentID = 1, Name = "A1"},
                new ItemInfo(){ID = 3, ParentID = 0, Name = "B"},
                new ItemInfo(){ID = 4, ParentID = 0, Name = "C"},
                new ItemInfo(){ID = 5, ParentID = 1, Name = "A2"},
                new ItemInfo(){ID = 6, ParentID = 3, Name = "B1"},
            };

            FillNode(items, null);
        }

        private void FillNode(List<ItemInfo> items, TreeNode node)
        {
            var parentID = node != null
                ? (int)node.Tag
                : 0;

            var nodesCollection = node != null
                ? node.Nodes
                : treeView1.Nodes;

            foreach (var item in items.Where(i => i.ParentID == parentID))
            {
                var newNode = nodesCollection.Add(item.Name, item.Name);
                newNode.Tag = item.ID;

                FillNode(items, newNode);
            }
        }
    }
like image 116
Viacheslav Smityukh Avatar answered Nov 17 '22 00:11

Viacheslav Smityukh