New to Telerik UI for ASP.NET AJAX? Download free 30-day trial

Hierarchical data-binding using DetailTableDataBind event

To display hierarchical data, RadGrid renders one or more detail tables for each item (row) in the MasterTableView. In a multi-level hierarchy, each item of every detail table can have one or more detail tables as well. The level of the grid hierarchy can be arbitrarily deep.

When binding each detail table view, RadGrid fires the DetailTableDataBind event. The argument for a DetailTableDataBind event handler carries all the information you need for binding the detail table, including the table view that should be bound, its parent item, and so on.

When the DetailTableDataBind event occurs depends on the HierarchyLoadMode of the corresponding GridTableView.

  • If HierarchyLoadMode is set to ServerBind, then the DetailTableDataBind event fires immediately after the corresponding parent item is bound.

  • If HierarchyLoadMode is set to ServerOnDemand, the DetailTableDataBind event does not occur until the detail table's parent item is expanded.

Using DetailTableDataBind

The main steps when binding a hierarchical grid using the DetailTableDataBind event are as follows:

  1. Create the grid, either statically or dynamically. Set the properties of the grid to provide the appearance and functionality you want. You must create and add GridTableView objects to the DetailTables collection of the MasterTableView and any detail tables that have their own nested details.

  2. Bind the master table view of the grid either declaratively or by assigning a NeedDataSource event handler to the grid. Optionally, you can assign data sources to the detail tables, which can subsequently be configured in the DetailTableDataBind event handler.

  3. Assign the DetailTableDataBind event handler to the grid.

  4. In the DetailTableDataBind event handler, assign or configure the data sources for the detail tables in the grid. You can determine which datasource should be related to the parent GridTableView by checking the Name property, DataSourceID property (when using data source controls) or DataMember property (when not using data source controls). If the DetailTableDataBind event is not handled, each detail table will be bound to the same datasource as the master table without any filtering applied on the records.

When binding RadGrid in DetailTableDataBind, you must not use declarative relations (ParentTableRelations) in markup.

For a live example that demonstrates binding a hierarchical grid using the DetailTableDataBind event, see Hierarchy with DetailTableDataBind event.

You can use the DetailTableDataBind event handler to assign a NoRecordsTemplate for the GridTableView . This is a template that is displayed if there are no records in the assigned DataSource (seeUsing NoRecordsTemplate).

When implementing a DetailTableDataBind event handler, you should construct a detail data source (list of objects) that the detail table view displays. This data source should be filtered in the appropriate manner: it should contain only detail table records that correspond to the particular parent item in which the table is nested.

The following examples show some possible ways to filter the detail data source. These examples all assume the approach where the DataSource and DataMember properties of the detail tables are assigned in the NeedDataSource event handler, and DetailTableDataBind is used to configure the data source:

Binding detail tables using database select

private void RadGrid1_DetailTableDataBind(object source, Telerik.Web.UI.GridDetailTableDataBindEventArgs e)
{
    GridDataItem parentItem = e.DetailTableView.ParentItem as GridDataItem;
    if (parentItem.Edit)
    {
        return;
    }
    if (e.DetailTableView.DataMember == "OrderDetails")
    {
        dsNWind1.OrderDetails.Clear();
        daOrderDetails.SelectCommand.CommandText = "Select * from [Order Details] where OrderID = " + parentItem["OrderID"].Text;
        daOrderDetails.Fill(dsNWind1.OrderDetails);
    }
}
Private Sub RadGrid1_DetailTableDataBind(ByVal source As Object, ByVal e As GridDetailTableDataBindEventArgs) Handles RadGrid1.DetailTableDataBind
    Dim parentItem As GridDataItem = CType(e.DetailTableView.ParentItem, GridDataItem)
    If parentItem.Edit Then
        Return
    End If
    If (e.DetailTableView.DataMember = "OrderDetails") Then
        dsNWind1.OrderDetails.Clear()
        daOrderDetails.SelectCommand.CommandText = "Select * from [Order Details] where OrderID = " + parentItem("OrderID").Text
        daOrderDetails.Fill(dsNWind1.OrderDetails)
    End If
End Sub

Binding detail tables using DataTable.Select

private void RadGrid1_DetailTableDataBind(object source, Telerik.Web.UI.GridDetailTableDataBindEventArgs e)
{
    GridDataItem parentItem = e.DetailTableView.ParentItem as GridDataItem;
    if (parentItem.Edit)
    {
        return;
    }
    if (e.DetailTableView.DataMember == "OrderDetails")
    {
        DataSet ds = (DataSet)e.DetailTableView.DataSource;
        e.DetailTableView.DataSource = ds.Tables["OrderDetails"].Select("CustomerID = '" + parentItem["CustomerID"].Text + "'");
    }
}
Private Sub RadGrid1_DetailTableDataBind(ByVal source As Object, ByVal e As GridDetailTableDataBindEventArgs) Handles RadGrid1.DetailTableDataBind
    Dim parentItem As GridDataItem = CType(e.DetailTableView.ParentItem, GridDataItem)
    If parentItem.Edit Then
        Return
    End If
    If (e.DetailTableView.DataMember = "OrderDetails") Then
        Dim ds As DataSet = CType(e.DetailTableView.DataSource, DataSet)
        e.DetailTableView.DataSource = ds.Tables("OrderDetails").Select("CustomerID = '" + parentItem("CustomerID").Text + "'")
    End If
End Sub

Binding detail tables using a filtered DataView

private void RadGrid1_DetailTableDataBind(object source, Telerik.Web.UI.GridDetailTableDataBindEventArgs e)
{
    GridDataItem parentItem = e.DetailTableView.ParentItem as GridDataItem;
    if (parentItem.Edit)
    {
        return;
    }
    if (e.DetailTableView.DataMember == "OrderDetails")
    {
        DataSet ds = (DataSet)e.DetailTableView.DataSource;
        DataView dv = ds.Tables["OrderDetails"].DefaultView;
        dv.RowFilter = "CustomerID = '" + parentItem["CustomerID"].Text + "'";
        e.DetailTableView.DataSource = dv;
    }
}
Private Sub RadGrid1_DetailTableDataBind(ByVal source As Object, ByVal e As GridDetailTableDataBindEventArgs) Handles RadGrid1.DetailTableDataBind
    Dim parentItem As GridDataItem = CType(e.DetailTableView.ParentItem, GridDataItem)
    If parentItem.Edit Then
        Return
    End If
    If (e.DetailTableView.DataMember = "OrderDetails") Then
        Dim ds As DataSet = CType(e.DetailTableView.DataSource, DataSet)
        Dim dv As DataView = ds.Tables("OrderDetails").DefaultView
        dv.RowFilter = "CustomerID = '" + parentItem("CustomerID").Text + "'"
        e.DetailTableView.DataSource = dv
    End If
End Sub
In this article