Display Hierarchical Data with TreeView in ASP.NET 2.0


I’m going to provide a simple example how to display hierarchical data from SQL Server database in the TreeView. A requirement is that the implementation should not be dependant on the hierarchy level in the database. It means that the TreeView implementation should be capable of displaying data from any level, no matter how deep.

Listing #1 : TreeviewEx.aspx

 <asp:TreeView ID="tvCategoryList" runat="server" ImageSet="BulletedList3" Width="100%"
        ShowExpandCollapse="True" NodeWrap="True" OnTreeNodePopulate="tvCategoryList_TreeNodePopulate"
        ExpandDepth="2" PopulateNodesFromClient="False">
        <ParentNodeStyle Font-Bold="True" />
        <RootNodeStyle Font-Bold="True" CssClass="Table_Title_Label_Black12" />
        <HoverNodeStyle Font-Underline="True" ForeColor="#5555DD" />
        <SelectedNodeStyle Font-Underline="True" HorizontalPadding="0px" VerticalPadding="0px"
            ForeColor="#5555DD" />
        <NodeStyle Font-Names="Verdana" Font-Size="8pt" ForeColor="Black" HorizontalPadding="0px"
            NodeSpacing="0px" VerticalPadding="0px" />
    </asp:TreeView>

Next, we start looking at the code in the TreeviewEx.aspx,cs file. We want to populate the root level. Here’s the code.

Listing #2

 protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            PopulateRootLevel();
        }
    }

This happens by connecting to the database, querying the first set of nodes (having null as the parent id), and creating TreeNode objects with the PopulateNodes routine, which follows next.

Listing #3

 private void PopulateRootLevel()
    {
        DataTable dt = BAL_Category.GetParentCategory();// Get Parent CategoryList From Database
        PopulateNodes(dt, tvCategoryList.Nodes);
    }

Next, we want to create the routine to populate the child nodes of a given node. This happens with the PopulateSubLevel method.

Listing #4

 private void PopulateSubLevel(int parentid, TreeNode parentNode)
    {
        // Get CategoryList by ParentID From Database
        DataTable dt = BAL_Category.GetChildCategory(parentid);
        PopulateNodes(dt, parentNode.ChildNodes);
    }

Here, the idea is the same as with the root level, but with the distinction that only child nodes of the given node are queried and populated with the PopulateNodes method (described earlier). The trick to triggering the populating of the child nodes is as follows.

Listing #5

protected void tvCategoryList_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
    PopulateSubLevel(Int32.Parse(e.Node.Value), e.Node);
}

TreeNodePopulate is raised for a TreeNode which is expanded by the user for the first time. Due to PopulateNodesFromClient (TreeView) and PopulateOnDemand (TreeNode) settings, this happens with the client-side callback mechanism which is handled by the ASP.NET Page framework. This means that populating does not involve a postback. And, due to better cross-browser support in ASP.NET 2.0, this also works for other browsers such as Firefox. Note that clicking on the node does cause a postback because I haven’t modified the select action of the populated tree nodes from the defaults.

Listing #6

private void PopulateNodes(DataTable dt, TreeNodeCollection nodes)
    {
        foreach (DataRow dr in dt.Rows)
        {
            TreeNode tn = new TreeNode();
            tn.Text = dr["Category"].ToString();
            tn.Value = dr["CategoryID"].ToString();
            int NoofChild = Convert.ToInt32(dr["childnodecount"].ToString());
            if (NoofChild != 0)
            {
                tn.PopulateOnDemand = true;
                tn.SelectAction = TreeNodeSelectAction.None;
            }
            else
            {
                tn.PopulateOnDemand = false;
                if (dr["TotalDoc"].ToString().Equals("0") == false)
                {
                    tn.NavigateUrl = "~/CategoryWiseProductList.aspx?ID=" + dr["CategoryID"].ToString();
                    tn.Text = tn.Text + " (" + dr["TotalProduct"].ToString() + ")";
                }
                else
                {
                    tn.NavigateUrl = "javascript:alert('Product is not Available Under this Category.')";
                }
            }
            nodes.Add(tn);
        }
    }

Hope this will Help you !!!

Happy Programming

Advertisements

29 thoughts on “Display Hierarchical Data with TreeView in ASP.NET 2.0

    1. hi aneesh, i have already explained the example with code & i have also stated all the things that are required but still if u need any clarification than please specify at which area you got problem so that i can give solution regarding that.

      1. Thanks Sandeep.

        Let me explain you mu issue. I have a project where users can subscribe to specific subjects so that the application can send newsletters to them on that specific subject.

        So I have to make an userinterface as simple as possible but displaying all the categories and its n level subcategories.

        After some R&D i believe Tree view is the only way ahead.[Please guide me If i am wrong].

        I asked you the entire sample because

        1) I wanted to know how the styles and skins will work Treeview which needed the CSS you have used.

        2) I wantd to know the definition for

        BAL_Category.GetChildCategory(parentid); and
        BAL_Category.GetChildCategory(parentid);

        since I would like to see the SQL queries used .

        3) I am interested to see how the database table is designed and how the relation is set.

        Thanks for your Time!

      2. Hi Aneesh ,

        1 ) Css :

        .Table_Title_Label_Black12
        {
        font-size: 10pt;
        font-family: ‘Verdana’;
        color: Black;
        font-weight: bold;

        text-decoration: none;
        }

        2 )

        BAL_LegalDocList.GetParentCategory() & BAL_Category.GetChildCategory(parentid)
        ——————————————————————————-

        using System;
        using System.Data.Common;
        using System.Data;

        public class BAL_LegalDocList
        {
        public BAL_LegalDocList()
        {

        }

        public static DataTable GetParentCategory()
        {
        // get a configured DbCommand object
        GenericDataAccess gda = new GenericDataAccess();

        DbCommand comm = gda.CreateCommand();

        // set the stored procedure name
        comm.CommandText = “GetParentCategory”;

        // return the result table
        DataTable table = gda.ExecuteSelectCommand(comm);
        return table;
        }
        public static DataTable GetChildCategory(int ParentID)
        {
        // get a configured DbCommand object
        GenericDataAccess gda = new GenericDataAccess();

        DbCommand comm = gda.CreateCommand();

        // set the stored procedure name
        comm.CommandText = “GetChildCategory”;

        // create a new parameter
        DbParameter param = comm.CreateParameter();
        param.ParameterName = “@ParentID”;
        param.Value = ParentID;
        param.DbType = DbType.Int32;
        comm.Parameters.Add(param);

        // return the result table
        DataTable table = gda.ExecuteSelectCommand(comm);
        return table;
        }

        }

        3 ) Database :
        ———————-

        Stored Procedure 1:
        ——————-

        CREATE PROCEDURE [dbo].[GetParentCategory]

        AS
        BEGIN
        SELECT
        CategoryID,
        Category,
        (SELECT count(*) FROM Category WHERE ParentID=C.CategoryID AND SoftStatus=1) as childnodecount ,
        (SELECT count(*) FROM LegalDocument WHERE CategoryID = C.CategoryID AND Status=0) as TotalDoc
        FROM
        Category C
        WHERE
        ParentID =0 AND
        SoftStatus = 1
        ORDER BY Category
        END

        Stored Procedure 2:
        ——————–

        CREATE PROCEDURE [dbo].[GetChildCategory]
        @ParentID int
        AS
        BEGIN
        SELECT
        CategoryID,
        Category,
        (SELECT count(*) FROM Category WHERE ParentID=C.CategoryID AND SoftStatus=1) as childnodecount ,
        (SELECT count(*) FROM LegalDocument WHERE CategoryID = C.CategoryID AND Status=0) as TotalDoc
        FROM
        Category C
        WHERE
        ParentID = @ParentID AND
        SoftStatus=1
        ORDER BY Category
        END

        Table :
        ————

        CREATE TABLE [dbo].[Category](
        [CategoryID] [int] IDENTITY(1,1) NOT NULL,
        [Category] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
        [ParentID] [int] NULL,
        [SoftStatus] [bit] NULL,
        CONSTRAINT [PK_Category_1] PRIMARY KEY CLUSTERED
        (
        [CategoryID] ASC
        )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
        ) ON [PRIMARY]

        Hope this will help you

  1. Hi , Sandeep

    Thank you very much for your help.
    I really appreciate your gesture and the time you spent to do this.

    Thank you very much !

  2. Hi ,

    I could successfully populate treeview from database. i have added checkboxes to all the nodes so that user can select and unselect.Those values is updated on the DB , using

    TreeNodeCollection checkedNodes = TreeView1.CheckedNodes;

    This make sure the DB is updated with the values selected by users.
    But when I repopulate the tree view for the second time how can we show the checkboxes with CHECKED state those have selected by the user already?

  3. Well , I could solve it.
    The code used to given below.Hope this helps someone who reaches Mr.Sandeep`s post till this end.

    We need to call this function twice.
    First) after populating the Main categories Second) After populating the Sublevels.

    private void DisplaySelected(TreeNodeCollection treeNodeCollection)
    {
    if (treeNodeCollection == null)
    return;

    foreach (TreeNode tn in treeNodeCollection)
    {
    // Assumes that you have the Userselection as a Arraylist here which was stored in a / //ViewState during PageLoad.

    ArrayList categoryList=(ArrayList) ViewState[“categories”];
    if (categoryList.Contains(tn.Text))
    {
    tn.Checked=true;

    }

    }
    }

    THAnks again Sandeep…

  4. Hey, I found this article while looking for help with Microsoft Silverlight. I’ve recently changed internet browser from Google Chrome to IE. Just recently I seem to have a problem with loading websites that use Microsoft Silverlight. Every time I browse website that needs Microsoft Silverlight, my computer freezes and I get a “npctrl.dll” error. I cannot seem to find out how to fix the problem. Any help getting Microsoft Silverlight to function is greatly appreciated! Thanks

  5. I want to fill TreeView using List for binary tree.
    Root node is first item of List.
    Then following the formula
    Left child index : n * 2
    Right child index: (n * 2) +1

    But I could find any solution:
    I tried:

    Listmembers=getmembers();

    TreeNode root=new TreeNode();

    root.Text=members.First();

    But don’t get any logic to go further to fill left and right sub trees for binary tree.

    Anybody, Please help

    1. There are 2 things you have to consider. If your requirement is to display a exact binary tree then

      1. Create a grphical look of the Binary Tree ( Yet I have not seen any such control in .Net)

      (So, if you want to display the B-Tree, you have to create yourself somehow)

      2. Getting required data from Database (This is quite simple)

      (For this you have to traverse all the child nodes following the parent node, now here 1 question comes that is what kind of traversal

      you need. It may be 1. Depth First Traversal, 2. Breath First Traversal. 3. Right-in Threaded B-Tree and so). For this to know about how

      to implement a specific type of traversal you may refer to a book :

      Data Structures Using C and C++ (2nd Edition) (Paperback) by Aaron M. Tenenbaum

      That will give you a complete look of how to implement those, if you want to create your own. Else you have to find whether similar algorithm is availabel in .Net Library or not. Getting a ready solution may not be possible I guess. So you can start with the book I mentioned if you want tp create your own.

    1. Hi Ritesh full source code is no more available with me now..because i have done it somewhere else & published code here with some notes.. now i dont have any code with me ..but u can achieve the same by taking code available here …it will also help with few things to do yourself only..

  6. Dear,

    I have successfully loaded the Treeview based on the values from sql database. but i want to show the roots checked by comparing the value from the database. i m using the below mentioned code. Kindly help me out as the Parent node is getting checked, but when im trying to show the checked values of the child nodes, is it not showing. The Child nodes get displayed but it’s not showing checked.

    private void PopulateNodes(DataTable dt, TreeNodeCollection nodes)
    {
    string grpid = “”;
    string temp_var = “”;
    int i = 0;
    conn.Open();
    SqlCommand com_chck = new SqlCommand(“sp_contactgroupmap ‘” + id_contact + “‘,”,’view’,””, conn);
    SqlDataReader sdr_chck = com_chck.ExecuteReader();
    if (sdr_chck.HasRows)
    {

    while (sdr_chck.Read())
    {
    grpid = sdr_chck.GetValue(2).ToString();

    foreach (DataRow dr in dt.Rows)
    {
    TreeNode tn = new TreeNode();
    tn.Text = dr[“groupname”].ToString();
    tn.Value = dr[“groupid”].ToString();
    if (i == 0)
    {

    if (grpid == tn.Value)
    {
    tn.Checked = true;
    tn.NavigateUrl = “#”;
    nodes.Add(tn);
    tn.PopulateOnDemand = (Convert.ToInt32(dr[“childcnt”]) > 0);
    }
    else
    {
    if (tn.Checked)
    {

    }
    else
    {
    tn.Checked = false;
    }
    tn.NavigateUrl = “#”;
    nodes.Add(tn);
    tn.PopulateOnDemand = (Convert.ToInt32(dr[“childcnt”]) > 0);
    }
    }
    else
    {
    //FIRST ROUND OF POPULATING THE ITEMS IN TREEVIEW IS FINISHED
    if (grpid == tn.Value)
    {
    tn.Checked = true;
    tn.NavigateUrl = “#”;
    //nodes.Add(tn);
    //tn.PopulateOnDemand = (Convert.ToInt32(dr[“childcnt”]) > 0);
    }
    else
    {
    if (tn.Checked)
    {
    tn.Checked = true;
    }
    else
    {
    tn.Checked = false;
    tn.NavigateUrl = “#”;
    }
    //nodes.Add(tn);
    //tn.PopulateOnDemand = (Convert.ToInt32(dr[“childcnt”]) > 0);
    }
    }

    //if (grpid == tn.Value)
    //{
    // temp_var = tn.Value;
    // tn.Checked = true;
    // tn.NavigateUrl = “#”;
    // nodes.Add(tn);
    // //If node has child nodes, then enable on-demand populating
    // tn.PopulateOnDemand = (Convert.ToInt32(dr[“childcnt”]) > 0);
    // break;
    //}

    //else
    //{
    // if (temp_var == tn.Value)
    // {
    // //break;
    // tn.Checked = true;
    // tn.NavigateUrl = “#”;
    // //break;
    // //nodes.Add(tn);
    // //If node has child nodes, then enable on-demand populating
    // //tn.PopulateOnDemand = (Convert.ToInt32(dr[“childcnt”]) > 0);
    // }
    // else
    // {

    // tn.Checked = false;
    // nodes.Add(tn);
    // tn.PopulateOnDemand = (Convert.ToInt32(dr[“childcnt”]) > 0);
    // //break;
    // }
    // temp_var = tn.Value;
    //}
    }
    i = i + 1;
    }
    }
    else
    {
    foreach (DataRow dr in dt.Rows)
    {
    TreeNode tn = new TreeNode();

    tn.Text = dr[“groupname”].ToString();
    tn.Value = dr[“groupid”].ToString();
    tn.NavigateUrl = “#”;
    nodes.Add(tn);

    //If node has child nodes, then enable on-demand populating
    tn.PopulateOnDemand = (Convert.ToInt32(dr[“childcnt”]) > 0);

    }
    }
    sdr_chck.Close();
    com_chck.Dispose();
    conn.Close();

    //Label2.Text = “”;
    }

  7. although this post is very much useful,
    what is ‘GenericDataAccess’ n ‘BAL_LegalDocList’ or ‘BAL_Category’ this class.?please explain me.
    Please give me any idea about making custom binary tree in asp.net4.0 and mssql server2008.

    i m waiting for ur quick n positive reply.
    thanks again

  8. nice code but it is possible that you can send me a code for GenericDataAccess(). i am new so don’t know how to write

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s