# Client-side Binding

Loading on-demand, client-side is similar to [server-side load-on-demand](https://www.telerik.com/products/aspnet-ajax/documentation/controls/treeview/load-on-demand/server-side-binding). The difference is in setting the **ExpandMode** property of each node to **ServerSideCallback** instead to **ServerSide**. When a node is clicked, an asynchronous callback is performed automatically to retrieve the data for just that node. Minimally, you must set the **ExpandMode** to **ServerSideCallback** and handle the **NodeExpand** event as shown in the example below. The example has a single root element and only one child element that is loaded on demand.

> caption

![RadTreeView Client-Side Load on Demand](https://www.telerik.com/products/aspnet-ajax/documentation/assets/168926febc4030ecfbb731c9a62c339e/treeview_loadondemandclient.png)

```C#
using System;
using Telerik.Web.UI;
namespace RadTreeView_Templates1
{
   public partial class _Default : System.Web.UI.Page
   {
       protected void Page_Load(object sender, EventArgs e)
       {
           if (!Page.IsPostBack)
           {
               RadTreeNode node = new RadTreeNode("Root");
               node.ExpandMode = TreeNodeExpandMode.ServerSideCallBack;
               RadTreeView1.Nodes.Add(node);
           }
       }
       protected void RadTreeView1_NodeExpand(object sender, RadTreeNodeEventArgs e)
       {
           e.Node.Nodes.Add(new RadTreeNode("Child"));
       }
   }
} 
```

```VB.NET
Imports System
Imports Telerik.Web.UI
Namespace RadTreeView_Templates1
    Partial Public Class _Default
        Inherits System.Web.UI.Page
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
            If Not Page.IsPostBack Then
                Dim node As New RadTreeNode("Root")
                node.ExpandMode = TreeNodeExpandMode.ServerSideCallBack
                RadTreeView1.Nodes.Add(node)
            End If
        End Sub
        Protected Sub RadTreeView1_NodeExpand(ByVal sender As Object, ByVal e As RadTreeNodeEventArgs)
            e.Node.Nodes.Add(New RadTreeNode("Child"))
        End Sub
    End Class
End Namespace
```

To load an arbitrary number of levels on-demand client-side, the general steps are:

* Query the root node data, i.e. for the nodes that the user will see first. When using self-referential hierarchical databases this can be done by querying for nodes where the "parent id" is null. Querying may involve a literal SQL query, but could also be any extraction of data using the root node.

* Iterate through the root node data and add new node objects for each record. Assign to the **Text** property the data column representing readable text and assign the column containing unique identifiers to the **Value** property of each node. The Value property will be used later as a parent id when opening a node. Set the Node **ExpandMode** property to **ServerSideCallback;** expanding a node will cause an asynchronous callback. During the callback, the server **NodeExpand** event handler will fire.

* Create a **NodeExpand** event handler. This event will pass a reference to the clicked-on node as a parameter. Use the node **Value** property to query for all child nodes of this parent node.

* Iterate through the child nodes, again populating the **Text** and **Value** properties of each node. Set each child node's **ExpandMode** property to **ServerSideCallback.** You do not need to set the **ExpandNode** for the clicked-on, parent node to **ClientSide;** the **ServerSideCallback** expand mode automatically handles the case so that the server is not queried twice. Also set the **Expanded** property of the parent node to **True**.

The example below loads data from the Access Database.mdb database. This database can be found in the RadControls installation directory under Live Demos\App_Data. Any data that has ID, Parent ID and text column data would work in this scenario. In this example the LoadRootNodes() method loads only the node called "Root". When the user clicks that node the first time, the **NodeExpand** event is fired:

* The data for the child nodes of the parent "Root" are retrieved.

* Nodes are created for each record and attached as child nodes to the parent node. The **ExpandMode** property of each child node is set to **ServerSideCallback**.

* The parent "Root" node's **Expanded** property is set to **True**, opening the node to display the child nodes.

The same general pattern for NodeExpand is repeated when the user clicks a node that has not yet been expanded.

> caption

![RadTreeView Load On Demand Overview](https://www.telerik.com/products/aspnet-ajax/documentation/assets/bb6d669402ae5265f172a72bbdc38020/treeview_loadondemandoverview.png)

```C#
using System;
using System.Data;
using System.Data.OleDb;
using Telerik.Web.UI;
namespace RadTreeView_DataBindDataTable
{
   public partial class _Default : System.Web.UI.Page
   {
       protected void Page_Load(object sender, EventArgs e)
       {
           if (!IsPostBack)
           {
               LoadRootNodes(RadTreeView1);
           }
       }
       private void LoadRootNodes(RadTreeView treeView)
       {
           const string sql = "Select Name, ItemID from Items where ParentID IS NULL";
           OleDbConnection connection = new OleDbConnection(Properties.Settings.Default.AccessConnection);
           OleDbDataAdapter adapter = new OleDbDataAdapter(sql, connection);
           DataTable dataTable = new DataTable();
           adapter.Fill(dataTable);
           foreach (DataRow row in dataTable.Rows)
           {
               RadTreeNode node = new RadTreeNode();
               node.Text = row["Name"].ToString();
               node.Value = row["ItemID"].ToString();
               node.ExpandMode = TreeNodeExpandMode.ServerSideCallBack;
               RadTreeView1.Nodes.Add(node);
           }
       }
       protected void RadTreeView1_NodeExpand(object sender, RadTreeNodeEventArgs e)
       {
           const string sql =
           @"
               SELECT Items.ItemID AS NodeId, Items.Name AS NodeText, COUNT(Children.ItemID) AS ChildCount
               FROM Items LEFT JOIN Items As Children
               ON Items.ItemID = Children.ParentId
               WHERE Items.ParentId = @parentId
               GROUP BY Items.ItemID, Items.Name
           ";
           OleDbConnection connection = new OleDbConnection(Properties.Settings.Default.AccessConnection);
           OleDbDataAdapter adapter = new OleDbDataAdapter(sql, connection);
           adapter.SelectCommand.Parameters.AddWithValue("parentId", e.Node.Value);
           DataTable dataTable = new DataTable();
           adapter.Fill(dataTable);
           foreach (DataRow row in dataTable.Rows)
           {
               RadTreeNode node = new RadTreeNode();
               node.Text = row["NodeText"].ToString();
               node.Value = row["NodeId"].ToString();
               if (Convert.ToInt32(row["ChildCount"]) > 0)
               {
                   node.ExpandMode = TreeNodeExpandMode.ServerSideCallBack;
               }
               e.Node.Nodes.Add(node);
           }
           e.Node.Expanded = true;
           //e.Node.ExpandMode = TreeNodeExpandMode.ClientSide;
       }
   }
}
```

```VB.NET
Imports System
Imports System.Data
Imports System.Data.OleDb
Imports Telerik.Web.UI
Namespace RadTreeView_DataBindDataTable
    Partial Public Class _Default
        Inherits System.Web.UI.Page
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
            If Not IsPostBack Then
                LoadRootNodes(RadTreeView1)
            End If
        End Sub
        Private Sub LoadRootNodes(ByVal treeView As RadTreeView)
            Const sql As String = "Select Name, ItemID from Items where ParentID IS NULL"
            Dim connection As New OleDbConnection(Properties.Settings.[Default].AccessConnection)
            Dim adapter As New OleDbDataAdapter(sql, connection)
            Dim dataTable As New DataTable()
            adapter.Fill(dataTable)
            For Each row As DataRow In dataTable.Rows
                Dim node As New RadTreeNode()
                node.Text = row("Name").ToString()
                node.Value = row("ItemID").ToString()
                node.ExpandMode = TreeNodeExpandMode.ServerSideCallBack
                RadTreeView1.Nodes.Add(node)
            Next
        End Sub
        Protected Sub RadTreeView1_NodeExpand(ByVal sender As Object, ByVal e As RadTreeNodeEventArgs)
            Const sql As String = "" & Chr(13) & "" & Chr(10) & " SELECT Items.ItemID AS NodeId, Items.Name AS NodeText, COUNT(Children.ItemID) AS ChildCount " & Chr(13) & "" & Chr(10) & " FROM Items LEFT JOIN Items As Children " & Chr(13) & "" & Chr(10) & " ON Items.ItemID = Children.ParentId " & Chr(13) & "" & Chr(10) & " WHERE Items.ParentId = @parentId " & Chr(13) & "" & Chr(10) & " GROUP BY Items.ItemID, Items.Name" & Chr(13) & "" & Chr(10) & " "
            Dim connection As New OleDbConnection(Properties.Settings.[Default].AccessConnection)
            Dim adapter As New OleDbDataAdapter(sql, connection)
            adapter.SelectCommand.Parameters.AddWithValue("parentId", e.Node.Value)
            Dim dataTable As New DataTable()
            adapter.Fill(dataTable)
            For Each row As DataRow In dataTable.Rows
                Dim node As New RadTreeNode()
                node.Text = row("NodeText").ToString()
                node.Value = row("NodeId").ToString()
                If Convert.ToInt32(row("ChildCount")) > 0 Then
                    node.ExpandMode = TreeNodeExpandMode.ServerSideCallBack
                End If
                e.Node.Nodes.Add(node)
            Next
            e.Node.Expanded = True
            'e.Node.ExpandMode = TreeNodeExpandMode.ClientSide;
        End Sub
    End Class
End Namespace
```
