This is a migrated thread and some comments may be shown as answers.

OnItemDataBound does not fire for nested grid items

1 Answer 226 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Dan
Top achievements
Rank 1
Dan asked on 19 Aug 2020, 02:08 PM
Hi Telerik,

I'm having trouble getting data binding to work on a nested grid.  What I want to do is present a summary list of data in an outer grid and load some record-specific detail data and insert it into the nested grid when the user expands the nested grid.

I've tried to follow a couple of different examples from these forums and the documentation, but I haven't found an example that addresses my desire to load and bind new data in response to expanding the outer grid.

See my inline comments below for details about how this code currently behaves when I'm debugging.

Thanks for any help or suggestions for making this work.

Here is my markup (Note that MyDataGridImplementation extends RadGrid):

<mynamespace:MyDataGridImplementation ID="ItemSummaryGrid" runat="server"
        AllowSorting="true" AllowPaging="true" PageSize="10"
        OnNeedDataSource="OuterGridNeedDataSource" OnItemDataBound="OuterGridItemDataBound" OnItemCommand="OuterGrid_ItemCommand">
        <PagerStyle Mode="NextPrevAndNumeric"/>
        <MasterTableView AutoGenerateColumns="false" EnableNoRecordsTemplate="true" DataKeyNames="OuterGridItemId"
            NoMasterRecordsText='<%# ResourceManager.GetPhrase("NoRecords", "There are no records.") %>'>         
            <Columns>
                <telerik:GridBoundColumn
                    AllowSorting="true"
                    DataField="ItemSummaryDateTime"
                    DataType="System.DateTime"
                    DataFormatString="{0:d}"
                    HeaderText="Date"
                    UniqueName="ItemSummaryDateTime" />
                <telerik:GridBoundColumn
                    AllowSorting="true"
                    DataField="ItemSummaryItemType"
                    DataType="System.String"
                    HeaderText="Type"
                    UniqueName="ItemSummaryItemType" />
                <telerik:GridBoundColumn
                    AllowSorting="true"
                    DataField="ItemSummaryItemSubject"
                    DataType="System.String"
                    HeaderText="Subject"
                    UniqueName="ItemSummaryItemSubject" />
                <telerik:GridBoundColumn
                    AllowSorting="true"
                    DataField="ItemSummaryName"
                    DataType="System.String"
                    HeaderText="Name"
                    UniqueName="ItemSummaryName" />
            </Columns>
            <NestedViewTemplate>
                <asp:Panel ID="Panel1" runat="server" CssClass="ChildGridWrapper">
                    <mynamespace:MyDataGridImplementation ID="ItemDetailsLinesGrid" runat="server" AllowSorting="false"                       
                         OnNeedDataSource="NestedGridNeedDataSource" OnItemDataBound="NestedGridItemDataBound" EnableShowAllButton="False" >
                        <MasterTableView AutoGenerateColumns="false" DataKeyNames="NestedGridItemEventId" ShowHeader="true" ShowFooter="false">
                            <Columns>
                                <telerik:GridBoundColumn
                                    AllowSorting="false"
                                    DataField="DetailItemDateTime"
                                    DataType="System.DateTime"
                                    DataFormatString="{0:d}"
                                    HeaderText="Date"
                                    UniqueName="DetailItemDateTime" />
                                <telerik:GridBoundColumn
                                    AllowSorting="false"
                                    DataField="DetailItemTypeCode"
                                    DataType="System.String"
                                    HeaderText="Type"
                                    UniqueName="DetailItemTypeCode" />                             
                                <telerik:GridBoundColumn
                                    AllowSorting="false"
                                    DataField="DetailItemMessage"
                                    DataType="System.String"
                                    HeaderText="Details"
                                    UniqueName="DetailItemMessage" />
                            </Columns>
                        </MasterTableView>
                    </mynamespace:MyDataGridImplementation>
                </asp:Panel>
            </NestedViewTemplate>
        </MasterTableView>
        <ClientSettings AllowGroupExpandCollapse="false" EnablePostBackOnRowClick="false">
            <Selecting AllowRowSelect="false" />                                
        </ClientSettings>
    </mynamespace:MyDataGridImplementation>


And code behind:

protected void OuterGridNeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
    // ItemSummaryList is populated during OnLoad.  Outer grid populates correctly with summary data.
    ItemSummaryGrid.DataSource = null;
    if (!IsContentDesignMode)
        ItemSummaryGrid.DataSource = ItemSummaryList;
}
 
protected void OuterGridItemDataBound(object sender, GridItemEventArgs e)
{
    if (e == null) throw new ArgumentNullException("e");
 
    // format and set outer summary grid column values.
}
 
protected void OuterGrid_ItemCommand(object sender, GridCommandEventArgs e)
{
    if (e.CommandName == RadGrid.ExpandCollapseCommandName)
    {
        var gridItem = e.Item as GridDataItem;
        if (gridItem != null)
        {
            var nestedGrid = (RadGrid)gridItem.ChildItem.FindControl("ItemDetailsLinesGrid");
            nestedGrid.Rebind();
        }
    }
}
 
protected void NestedGridNeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
    // NestedGridNeedDataSource is fired successfully from OuterGrid_ItemCommand when the outer grid row is expanded
     
    var control = ((Control)sender);
    var nestedGridItem = control?.BindingContainer as GridNestedViewItem;
    if (nestedGridItem != null)
    {
        var nestedGrid = (RadGrid)nestedGridItem.FindControl("CommunicationLogEventLinesGrid");
        // here we set the DataSource for the nested grid.  I have verified during debugging that
        // nestedGrid.DataSource is null when the nested grid is initially expanded and this event is fired.
        nestedGrid.DataSource = FakeData();
        // not sure if an explicit call to DataBind is necessary here...
        //nestedGrid.DataBind();
    }
}
 
protected void NestedGridItemDataBound(object sender, GridItemEventArgs e)
{
    // NestedGridItemDataBound is never fired. 
    // A breakpoint set here is never reached when the nested grid is expanded from the UI.
    if (e == null) throw new ArgumentNullException("e");
 
    var gridDataItem = e.Item as GridDataItem;
     
    // format and set nested detail grid column values.
}
 
public IEnumerable<FakeItemDetailData> FakeData()
{
    return Enumerable.Range(1, 5).Select(i => new FakeItemDetailData
    {
        NestedGridItemEventId = Convert.ToString(i),
        DetailItemDateTime = DateTime.Now,
        DetailItemTypeCode = "HIHI",
        DetailItemMessage = $"HI! {i}"
    });
}
 
public class FakeItemDetailData
{
    public string NestedGridItemEventId;
    public DateTime DetailItemDateTime;
    public string DetailItemTypeCode;
    public string DetailItemMessage;
}

1 Answer, 1 is accepted

Sort by
0
Attila Antal
Telerik team
answered on 24 Aug 2020, 12:13 PM

Hi Dan,

I've looked at the code you shared and it all seems valid. There is no obvious/visible cause for the behavior. I've made a quick test using my code and the event fires without a problem.

The only thing I could point out is the line "var nestedGrid = (RadGrid)nestedGridItem.FindControl("CommunicationLogEventLinesGrid");". There is no such control anywhere in the Markup that yields the ID="CommunicationLogEventLinesGrid" hence the "nestedGrid.DataSource = FakeData();" line was throwing Null reference exception. If you haven't noticed this behavior, probably AJAX is enabled. Turn AJAX off temporarily and test the application without that. See Get more descriptive errors by disabling AJAX.

The NeedDataSource event is for the control that fires it and not for others, therefore, the data must be bound to the owner control.

protected void NestedGridNeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
    // NestedGridNeedDataSource is fired successfully from OuterGrid_ItemCommand when the outer grid row is expanded


    //var control = ((Control)sender);

    //    var nestedGridItem = control.BindingContainer as GridNestedViewItem;
    //if (nestedGridItem != null)
    //{
    //    var nestedGrid = (RadGrid)nestedGridItem.FindControl("CommunicationLogEventLinesGrid");
    //    // here we set the DataSource for the nested grid.  I have verified during debugging that
    //    // nestedGrid.DataSource is null when the nested grid is initially expanded and this event is fired.
    //    nestedGrid.DataSource = FakeData();
    //    // not sure if an explicit call to DataBind is necessary here...
    //    //nestedGrid.DataBind();
    //}

    var nestedGrid = sender as RadGrid; // ID="ItemDetailsLinesGrid" is the one fired this event

    nestedGrid.DataSource = FakeData();

    // DataBind() must never be called in the ItemDataBound event as it will cause the Grid to call the ItemDabound event again, which will call the DataBind() again resulting in an endless loop;
}

Kind regards,
Attila Antal
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Tags
Grid
Asked by
Dan
Top achievements
Rank 1
Answers by
Attila Antal
Telerik team
Share this question
or