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):
And code behind:
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;}