Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / Windows Forms
Article

Building a dynamic Tree

Rate me:
Please Sign up or sign in to vote.
2.09/5 (4 votes)
22 Sep 2007CPOL2 min read 35.1K   877   13   1
You want to buid a dynamic menu!? You can use recursive algorithm to solve this.
Screenshot - tree.jpg

Introduction

When you build a application or website, you want to build a dynamic menu with many level depend on your categoris, sub-categories, products but you have never ever known exactly the number of level of your menu. Now, I make this one to show you the way to solve this problem.

Background

When you have to make a website of the shop. This shop have many product and they want to arrange their product to category, sub-category, product to many many level. They want to make it dynamic, they can make a new level (sub-sub-category,..) and you have to let them do that. When you develope, you don't know that how many level of menu could be builded.

To slove this problem, you should use resursive algorithm.

Here, I use TreeView in WinForm to demo this. I will read data in a Datatable to build a dynamic tree. This code can be used in ASP.NET. I use Visual Studio 2005 to develope it.

Using the code

First, I will define a DataTable to store the ID, PID(parent ID), Info of the menus...
C#
//
//  
C#
DataTable tbl;
DataColumn col;
private void InitTable()
    {
        tbl = new DataTable();

        col = new DataColumn("ID");
        tbl.Columns.Add(col);
        col = new DataColumn("PID");
        tbl.Columns.Add(col);
        col = new DataColumn("Info");
        tbl.Columns.Add(col);

        tbl.AcceptChanges();
    }

Then, I will make the data for this table. This table is store the information of menus.

C#
//
    private void initTableData()
        {
            DataRow r;

            r = tbl.NewRow();
            r["ID"] = "0";
            r["PID"] = "-1";
            r["Info"] = "Root";
            tbl.Rows.Add(r);

    
            r = tbl.NewRow();
            r["ID"] = "1";
            r["PID"] = "0";
            r["Info"] = "Menu1";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "10";
            r["PID"] = "0";
            r["Info"] = "Menu10";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "2";
            r["PID"] = "0";
            r["Info"] = "Menu2";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "3";
            r["PID"] = "0";
            r["Info"] = "Menu3";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "4";
            r["PID"] = "1";
            r["Info"] = "Menu4";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "5";
            r["PID"] = "4";
            r["Info"] = "Menu5";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "6";
            r["PID"] = "5";
            r["Info"] = "Menu6";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "7";
            r["PID"] = "2";
            r["Info"] = "Menu7";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "11";
            r["PID"] = "6";
            r["Info"] = "Menu11";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "8";
            r["PID"] = "10";
            r["Info"] = "Menu8";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "9";
            r["PID"] = "3";
            r["Info"] = "Menu9";
            tbl.Rows.Add(r);

            r = tbl.NewRow();
            r["ID"] = "12";
            r["PID"] = "7";
            r["Info"] = "Menu12";
            tbl.Rows.Add(r);
        }
// 

Let's start to build the tree!

I make a method to build this tree. This tree has a "Root" with ID=0 and PID=-1. So that, any menu has PID=0 is a child of this menu and this "Root" with PID=-1 has no parent.

We will add this "Root" to the tree and call the method initTreeView(TreeNode N). We consider that all sub menu is a TreeNode and we will add this TreeNode to "Root". With another Node, we continue to consider it a "mini root" and another menu which are children of this node is a "mini node" so we will add to this "mini root" then, too.

private void initTreeView(TreeNode N)
    {
        DataTable temp = new DataTable();
        col = new DataColumn("ID");
        temp.Columns.Add(col);
        col = new DataColumn("PID");
        temp.Columns.Add(col);
        col = new DataColumn("Info");
        temp.Columns.Add(col);
        temp.AcceptChanges();


        string id = getID(N);
        foreach (DataRow r1 in tbl.Rows)
        {
            if (r1["PID"].ToString() == id)
            {
                DataRow r2 = temp.NewRow();
                r2["ID"] = r1["ID"].ToString();
                r2["PID"] = r1["PID"].ToString();
                r2["Info"] = r1["Info"].ToString();
                temp.Rows.Add(r2);
                temp.AcceptChanges();
            }
        }

        foreach(DataRow r3 in temp.Rows)
        {
            TreeNode tn = new TreeNode();
            tn.Text = r3["Info"].ToString();
            initTreeView(tn);
            N.Nodes.Add(tn);
        }
    }

With any node, we will find all of its children (I define a new DataTable: temp to store those children), with each children will continue to call the method initTreeView() to build it. So on, so on, we will find the smallest menu and add it to its parent.

Points of Interest

With a short of code, we have builded a dynamic menu. It is simple to make, easy to remember and can be apply to WinForm or WebForm.
This algorithm could be use to any language.

Enjoy with my code! Thanks for reading!
Any problem or complain, please contact me at:

Name: Nguyen Anh Vu
Email: nguyenanhvu.aiti@gmail.com
or spiderman_anhvu@yahoo.com

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Vietnam Vietnam
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralNice try but... Pin
ESTAN25-Sep-07 1:20
ESTAN25-Sep-07 1:20 
Something is not quiet right in your application.
When you have 2 menuitems with the same name, it will go wrong

I think that the problem is when you call the following:

private string getID(TreeNode N)
{
foreach (DataRow r in tbl.Rows)
{
if (r["Info"].ToString() == N.Text)
return r["ID"].ToString();
}
return "";
}


What I do is use the Node.Tag to store the ID, so you can run through your whole tree to find the node.tag = pid


My get parent node is here (in VB, but it should be easy to convert it to C#)
Private Function GetParentNode(ByVal pid As String, ByVal pn As TreeNode) As TreeNode<br />
<br />
        If (pn.Tag.Equals(pid)) Then<br />
            Return pn<br />
        End If<br />
<br />
        For Each node As TreeNode In pn.Nodes<br />
            Dim n As TreeNode = GetParentNode(pid, node)<br />
            If (Not n Is Nothing) Then<br />
                Return n<br />
            End If<br />
        Next<br />
<br />
    End Function


My part of the function to populate the treeview: (i have 4 columns, a type column that can be used to distinguish different node types, like folder, root, profile... And it is stored in an DB)


For Each r As DataRow In dt.Rows<br />
            ' r(0) = id<br />
            ' r(1) = pid<br />
            ' r(2) = name<br />
            ' r(3) = type: Folder, Root, Profile<br />
            ' ImageIndex Root = 0<br />
            ' ImageIndex Folder = 1<br />
            ' ImageIndex Profile = 2<br />
<br />
            If (r(1).ToString = "0") Then<br />
                ' Add Root node<br />
                Dim node As New TreeNode<br />
                node.Text = r(2).ToString<br />
                node.Tag = r(0).ToString<br />
<br />
                Me.TreeView1.Nodes.Add(node)<br />
            Else<br />
                ' Find the parent node<br />
                For Each root As TreeNode In TreeView1.Nodes<br />
<br />
                    Dim node As TreeNode = GetParentNode(r(1).ToString, root)<br />
<br />
                    If (Not node Is Nothing) Then<br />
                        Dim n As New TreeNode<br />
                        n.Text = r(2).ToString<br />
                        n.Tag = r(0).ToString<br />
                        If (r(3).ToString.Equals("Root")) Then<br />
                            n.ImageIndex = 0<br />
                        ElseIf (r(3).ToString.Equals("Folder")) Then<br />
                            n.ImageIndex = 1<br />
                        ElseIf (r(3).ToString.Equals("Profile")) Then<br />
                            n.ImageIndex = 2<br />
                        End If<br />
<br />
                        node.Nodes.Add(n)<br />
                        node = Nothing<br />
                        Exit For<br />
                    End If<br />
                Next<br />
            End If<br />
       Next


Good luck!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.