Tuesday 3 January 2012

Server Side Dynamic TreeView in Asp.Net

 

In most cases loading large TreeView in one step can be a good performance killer. The generated html is really large and our page is loading so slow at the client and the average user don’t want to see the full tree together.

Let see, what needs for loading dynamically an asp.net server control on the server side.

  • We need some data (In that case that’s will the ProductCategory table in the AdventureWorks sample database).
  • We need a method to determine if the given node has childs or not.
  • We need a TreeView Mosolygó arc.
  • First step:
    • We have to load the first level nodes of the TreeView on the first page load.
    • Handle the OnTreeNodePopulate event if the childnode has more childs on the next level.
    • Set the nodes expanded property to false. The TreeNodePopulate event will be fired when we click on a node. The default value is true and the tree is expanded.
  • Repeat the previous step on every TreeNodePopulate event.

 

The ProductCategory table contains the following records: ProductCategoriesTable
The value of ParentProductCategoryID is null at the root elements and the ProductCategoryID of the parent element at the others.

 

We need a method that queries the list of the child nodes for a given node (DAO\CategoryDAO.cs):

public static List<ProductCategory> GetCategoriesByParentID(int? parentID)
{
    using (AdventureWorksLT2008Entities ctx = new AdventureWorksLT2008Entities())
    {
        return ctx.ProductCategory.Where(cat => cat.ParentProductCategoryID == parentID || (null == parentID && cat.ParentProductCategoryID == null)).ToList();
    }
}

 

Add a TreeView for the page (Default.aspx):

<asp:TreeView runat="server" ID="tvCategories"
    OnTreeNodePopulate="tvCategoris_TreeNodePopulate"></asp:TreeView>

 

Make an AddChildNodes method for populate the child nodes of the given node (Default.aspx.cs):

protected void AddChildNodes(TreeNodeCollection nodes, TreeNode node)
{
    List<ProductCategory> categories = null;
    int parentID = -1;
    
    if (null != node && int.TryParse(node.Value, out parentID))
        categories = CategoryDAO.GetCategoriesByParentID(parentID);
    else
        categories = CategoryDAO.GetCategoriesByParentID(null);

    foreach (var cat in categories)
    {
        TreeNode newNode = new TreeNode();
        newNode.Value = cat.ProductCategoryID.ToString();
        newNode.Text = cat.Name;
        newNode.PopulateOnDemand = null == node;
        newNode.Expanded = false;

        nodes.Add(newNode);
    }
}

If the new node is leaf node, we have to set the value of the PopulateOnDemand property to false.

 

Load the root elements on the first page load (Default.aspx.cs):

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
        AddChildNodes(tvCategories.Nodes, null);
}

 

Create an event handler for the TreeNodePopulate event (Default.aspx.cs):

protected void tvCategoris_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
    if (e.Node.ChildNodes.Count == 0)
    {
        AddChildNodes(e.Node.ChildNodes, e.Node);
    }
}

 

The full project is downloadable from my Skydrive public folder.

 

Happy and Bug free coding!

Morzel

1 comment: