
What would be the proper or recommended way to do this? Will it be too slow if I do it in the PageLoad since the nested Radgrid will all be generated and databinded every time I access the page or do a postback??
I am out of ideas here, help would be greatly appreciated.
-Manuel
23 Answers, 1 is accepted
It would be best advisable to initialize the inner RadGrid in your upper RadGrid's ItemCreated event:
void RadGrid1_ItemCreated(object sender, GridItemEventArgs e) |
{ |
if (e.Item is GridNestedViewItem) |
{ |
(e.Item.FindControl("InnerGridId") as RadGrid).NeedDataSource += new GridNeedDataSourceEventHandler(_Default_NeedDataSource); |
} |
} |
void _Default_NeedDataSource(object source, GridNeedDataSourceEventArgs e) |
{ |
//define inner grid data source. |
// ((source as RadGrid).NamingContainer as GridNestedViewItem) gives a reference to the |
//parent nested view item |
} |
As you can see from the above code, you need to find the inner RadGrid in the nested item's ItemCreated event and attacha a NeedDataSource event handler for it (you need advanced databinding using NeeDDataSource, if you want to insert/update/delete)
In the inner grid's NeedDataSource event, as commented, you can reference the parent GridNestedViewItem, and from there, the owner data item, GridTableView and parent RadGrid.
Using PreRender event of parent grid to yet begin initializing your inner grid won't work for you - too late for any proper initialization of the inner grid.
Regards,
Veli
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.

I tried the same approach to bind my nested grid. In one of my web page, I have to show extra details of an item and some other stats on a row click. I am using NestedViewTemplate to show the details. I have a main object Employee, which has a Department collection. The main grid is binded to the Employee collection, and the nested grid is binded to the corresponding department collection. The steps to achieve this are as follows:
1. In the NeedDataSource event of main grid I have fetched the employees and set as a datasource.
2. In the NeedDataSource event of nested grid I got the instance of the parent employee using '((source as RadGrid).NamingContainer as GridNestedViewItem).DataItem' and use the Department collection to set the datasource.
Code Snippet:
protected void MainGrid_ItemCreated(object sender, GridItemEventArgs e) |
{ |
if (e.Item is GridNestedViewItem) |
{ |
(e.Item.FindControl("Departments") as RadGrid).NeedDataSource += new GridNeedDataSourceEventHandler(NestedGrid_NeedDataSource); |
} |
} |
protected void NestedGrid_NeedDataSource(object source, GridNeedDataSourceEventArgs e) |
{ |
try |
{ |
Employee employee = ((source as RadGrid).NamingContainer as GridNestedViewItem).DataItem as Employee; |
if (employee != null) |
(source as RadGrid).DataSource = employee.Departments; |
} |
catch (Exception ex) { ShowErrorMessage(ex.Message); } |
} |
I have paging enabled on the main grid. Everything works fine for all the rows of the Ist page. But when any other page is clicked, the nested grid is not shown. On debugging I realised that the DataItem of the Naming container is always null when and different page is choosen (works fine on the initial load page). I am using HierarchyLoadMode as client. Using the server mode and ItemCommand event everything works fine but row expansion takes lot of time. Therefore we are trying to us the client mode.
Please help.
Thanks & Regards
Ashish Garg
Your observations are correct. The reason you are not getting your DataItem property on all postbacks (e.g. on Page event), is because GridItem.DataItem is populated only when RadGrid rebinds to its data source. So, unless you are rebinding on every postback, GridItem.DataItem will point to the respective object from the data source. On postbacks when RadGrid is not rebound, DataItem is null.
In this context, we advise you to not rely on GridItem.DataItem for populating your nested grid, unless you deliberately rebind your RadGrid on every postback. We advise you to instead get the data key value for the parent item and use it to fetch the correct data item from the data source:
object dataKeyValue = ((source as RadGrid).NamingContainer as DataItem).GetDataKeyValue("ID"); |
//use the dataKeyValue to fetch the correct Employee object |
The above code assumes you have an Employee property named ID and you use it as the data key value for the RadGrid data item (by settings DataKeyNames="ID" in the respective GridTableView).
Regards,
Veli
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.

Hi Veli,
Currently, I am working on the Telerik Hierarchy Grid with Dynamic Data. I tried to initialize the inner RadGrid in your upper RadGrid's ItemCreated event:
protected void RadGrid_ItemCreated(object sender, GridItemEventArgs e) |
{ |
if (e.Item is GridNestedViewItem) |
{ |
(e.Item.FindControl("DetailGridView") as RadGrid).NeedDataSource += new GridNeedDataSourceEventHandler(NestedGrid_NeedDataSource); |
} |
} |
protected void NestedGrid_NeedDataSource(object source, GridNeedDataSourceEventArgs e) |
{ |
try |
{ |
object dataKeyValue = ((source as RadGrid).NamingContainer as DataItem).GetDataKeyValue("ID"); |
//.... |
} |
catch (Exception ex) { } |
} |
However, I got a error about "the DataItem is not a type". The "DataItem" is a property of "GridItem". Then, I tried to use the "GridDataItem" instead of "DataItem":
object dataKeyValue = ((source as RadGrid).NamingContainer as GridDataItem).GetDataKeyValue("ID"); |
Then I got "[System.NullReferenceException] = {"Object reference not set to an instance of an object."}" exception.
Why did I get the Null value for "dataKeyValue"? How can I solve the problem?
Thanks a lot
Bill

You can try out the following code to access the datakeyvalue of the parent row in the NeedDataSource event of the nested grid:
c#:
protected void NestedGrid_NeedDataSource(object source, GridNeedDataSourceEventArgs e) |
{ |
try |
{ |
GridNestedViewItem nestedItem = (GridNestedViewItem)((source as RadGrid).NamingContainer); |
object dataKeyValue = nestedItem.ParentItem.GetDataKeyValue("ID"); |
//.... |
} |
catch (Exception ex) { } |
} |
Thanks
Princy.

I am also working on the similar issue,
i am able to the RadGrid placed inside a NestedTemplateView with out any problem...by getting the DataKeyValue from the GridDataItem in the Item_Created event of the ParentGrid,
Inorder to bind the Nested RadGrid i used NeedDataSource event of the ChildGrid and also parallelly binding it in the Item_Created event of the ParentGrid....i am able to see the data correctly now...
But the problem is when i click on the next page button of the ChildGrid...the data shows incorrectly with some binding texts..as attached in the image file below...i dont know why it is like that..
the below is the code i implemented ,
ItemCreatedEvent()
{
RadGrid
rgChildRequirement = (RadGrid)e.Item.FindControl("rgChildRequirements");
BindSubRequirments(rgChildRequirement);
}
public void BindSubRequirments(RadGrid rgSubRequirement)
{
LstChildRequirement = reqLogic.GetChildRequirementDetails(4, requirementID);
if (LstChildRequirement != null && LstChildRequirement.Count > 0)
{
if (rgSubRequirement.MasterTableView.Columns.Count == 0)
{
List<FieldDefinition> lstFields = reqLogic.GetPageFields(EntityType.EntityTypeID, 4);
for (int i = 0; i < lstFields.Count; i++)
{
lstFields[i].FieldDataTypeReference.Load();
GridBoundColumn dField = new GridBoundColumn();
dField.HeaderText = lstFields[i].FieldLiteral.ToString();
dField.HeaderStyle.Font.Bold =
true;
dField.HeaderStyle.Font.Size = 9;
dField.HeaderStyle.Font.Name =
"Arial";
dField.HeaderStyle.ForeColor = System.Drawing.
Color.Black;
dField.UniqueName = dField.HeaderText;
dField.SortExpression = dField.HeaderText;
dField.DataField = lstFields[i].FieldName;
dField.HeaderButtonType =
GridHeaderButtonType.TextButton;
rgSubRequirement.MasterTableView.Columns.Add(dField);
}
}
rgSubRequirement.AutoGenerateColumns =
false;
rgSubRequirement.DataSource = LstChildRequirement;
rgSubRequirement.Rebind();
}
}
and calling the same method in the ChildRequirement_NeedDataSource event;
tell me if there any wrong in my code..and also whether this kind of approach is correct or not...
Please do reply me asap.
Thanks:
chaitanya.E
You should not be setting RadGrid's data source outside of its NeedDataSource event in this case. A call to BindSubRequirments() can be placed in the respective grid's NeedDataSource event only, but remember to remove the Rebind() call from inside, as Rebind() must not be called from NeedDataSource event.
Additionally, if you have already declared your inner grid in the page markup, you need to make sure your Columns are first added to the RadGrid.MasterTableView.Columns collection before having their properties set:
GridBoundColumn col =
new
GridBoundColumn();
RadGrid1.MasterTableView.Columns.Add(col);
col.DataField =
"DataField"
;
col.HeaderText =
"HeaderText"
;
//...other col properties
For more information on creating your grid column, you can refer to this help article on RadGrid programmatic definition.
This should get you going now. Let me know what you get.
Sincerely yours,
Veli
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.

Thanks for the quick response... I had implemented suggestions given by you.. now i am not facing any problem at the nested grid pagination but now the problem is the nested grids are not getting laoded for the first expand click of parent row...
when ever i click the expand command the needdatasource of the nested grids does'nt get fired... at the collapse click command it get's fired and afterwards every thing goes cool..
and the second thing is if i need to change the data of the nested grids using the ItemDataBound is not updating i dont know why..
I modified the code as follows:
Item_Created event()
{
if
(e.Item is GridNestedViewItem)
{
GridNestedViewItem gnviewItem = e.Item as GridNestedViewItem;
RadTabStrip rts = (RadTabStrip)e.Item.FindControl("rtsChildElements");
rts.Tabs[0].Selected =
true;
//GridNestedViewItem gnViewItem = e.Item as GridNestedViewItem;
RadGrid rgReviews = (RadGrid)e.Item.FindControl("rgReviews");
RadGrid rgChildRequirement = (RadGrid)e.Item.FindControl("rgChildRequirements");
RadGrid rgTests = (RadGrid)e.Item.FindControl("rgTests");
RadGrid rgWorkPackages = (RadGrid)e.Item.FindControl("rgWorkPackages");
//Inorder to bind the related to the NestedGrids
rgReviews.NeedDataSource +=
new GridNeedDataSourceEventHandler(rgReviews_NeedDataSource);
rgChildRequirement.NeedDataSource +=
new GridNeedDataSourceEventHandler(rgChildRequirement_NeedDataSource);
rgTests.NeedDataSource +=
new GridNeedDataSourceEventHandler(rgTests_NeedDataSource);
rgWorkPackages.NeedDataSource +=
new GridNeedDataSourceEventHandler(rgWorkPackages_NeedDataSource);
rgReviews.ItemDataBound +=
new GridItemEventHandler(rgReviews_ItemDataBound);
rgChildRequirement.ItemDataBound +=
new GridItemEventHandler(rgChildRequirement_ItemDataBound);
rgTests.ItemDataBound +=
new GridItemEventHandler(rgTests_ItemDataBound);
rgWorkPackages.ItemDataBound +=
new GridItemEventHandler(rgWorkPackages_ItemDataBound);
}
void rgReviews_NeedDataSource(object source, GridNeedDataSourceEventArgs e)
{
GridNestedViewItem nestedItem = (GridNestedViewItem)((source as RadGrid).NamingContainer);
requirementID =
int.Parse(nestedItem.ParentItem.GetDataKeyValue("RequirementID").ToString());
BindRequirementReviews(source
as RadGrid);
}
protected
void rgReviews_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item is GridDataItem)
{
GridDataItem gdItem = (GridDataItem)e.Item;
try
{
string ColumnName = string.Empty;
short FieldID;
foreach (string str in ReviewLovFields)
{
ColumnName = str.Split(
'-')[0].ToString();
FieldID =
short.Parse(str.Split('-')[1].ToString());
if (gdItem[ColumnName] != null)
{
gdItem[ColumnName].Text = reqLogic.GetRequirementFieldDescription(
short.Parse(gdItem[ColumnName].Text), 4, EntityType.EntityTypeID, FieldID);
}
}
}
catch
{
}
}
}
}
let me know whether it is correct or not
Thanks in advance
Chaitanya.E
If your inner grids do not bind on initially expanding the parent item, try to explicitly rebind them in the parent grid's ItemCommand event:
protected
void
RadGrid1_ItemCommand(
object
source, GridCommandEventArgs e)
{
if
(e.CommandName == RadGrid.ExpandCollapseCommandName && !e.Item.Expanded)
{
((e.Item
as
GridDataItem).ChildItem.FindControl(
"gridID"
)
as
RadGrid).Rebind();
}
}
In the above code snippet RadGrid1 is the topmost parent RadGrid and gridID is the server ID of one of the grids. I explicitly rebind gridID in the command event when expanding the parent item. You can do the same for all of your grids.
As for modifying the grid cells in ItemDataBound, first make sure if your ItemDataBound event is fired (if it is attached properly and is firing OK), and, second, remove the try-catch block to see if you do not have any exceptions being thrown.
Best wishes,
Veli
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.

Thanks for the Quick response,
and it is working fine now...
thanks a lot veli

If you use a declarative data source control, you can set its ID to the DataSourceID of the nested grid from the markup. If binding manually, you need to find the child grid from parent Grid's ItemDataBound event. Suppose the parent grid's ID is RadGrid1, while the nested RadGrid in the form template has an ID of RadGrid2:
protected
void
RadGrid1_ItemDataBound(
object
sender, GridItemEventArgs e)
{
if
(e.Item
is
GridEditFormItem && e.Item.IsInEditMode)
{
GridEditFormItem editItem = (GridEditFormItem)e.Item;
//editItem.GetDataKeyValue() can be used to extract the data keys of the edited item
//editItem.ParentItem references the parent edited item
RadGrid RadGrid2 = (RadGrid)editItem.FindControl(
"RadGrid2"
);
//here is the inner grid. You can bind here
RadGrid2.Rebind()
}
}
The above code demonstrates how RadGrid can be found in the edit form when the edited item is created. You need to have inner RadGrid's NeedDataSource event hooked up. If you need to the parent edit form from within RadGrid's NeedDataSource event handler, you can use:
protected
void
RadGrid2_NeedDataSource(
object
source, GridNeedDataSourceEventArgs e)
{
RadGrid RadGrid2 = (RadGrid)source;
GridEditFormItem parentEditItem = (GridEditFormItem)RadGrid2.NamingContainer;
//edit form item
GridDataItem dataItem = parentEditItem.ParentItem;
//edited data item
}
Regards,
Veli
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.

My needs are fairly unusual so I've implemented a programmatic version of the NestedViewTemplate example found in "Grid / Hierarchy with Templates". Everything is wired up and looks great with each sub-table of information in a discrete tab but the performance is not good. I've killed the viewstate on the sub-grids to cut down bandwidth consumption as well as a few other minor tweaks but I haven't gotten much improvement.
The system is completely dynamic but, in my test case, each of my top-tier records (page size of 10) contains a pair of tab-encapsulated tables each typically having only a few records max and under 10 columns defined between them cumulatively. So even with all of them being fully rendered for client-side expansion, there's not a lot of data (verified by eavesdropping with Fiddler).
Initially I thought perhaps it was either the result of a query/data binding inefficiency or a product of rendering 21 (10*2 subgrids + 1 master) grids however a quick profile of the database activity showed things to be quite fast. So to completely rule out either possibility I truncated all of the data and metadata population of the subgrids and reduced the page size of the master grid to 1. Even with just two completely unbound/unpopulated sub-grids the resultant load times still hovered around the 7-10s page-to-page load time.
Shortly thereafter I narrowed it down to just the mere presence of the templatized subgrids. When they're present in the heirarchy, the CPU spikes for several seconds and the delay appears to reside somewhere in the event/post-event processing. Not a lot is being rendered (maybe 150k) so I suspect there may be some fairly brute-force tree walking that's getting induced by the presence of the template-generated subgrids but it's clearly occurring at some black-box level that is beyond my ability to pinpoint.
My hope is that it's simply some property of the embedded grid that needs to be set rather than an accepted inefficiency of attempting such a rich UI (but I doubt the example I've derived from would exist if that was the case). On the chance that it will provide a clue, here is a snippet of my simplified subgrid creation/initialization code:
subgrid.ID = String.Format("SubGrid_{0}", pageView.ID);
pageView.Controls.Add(subgrid);
subgrid.AutoGenerateColumns = false;
subgrid.Width = Unit.Percentage(100);
subgrid.AllowPaging =
true
;
subgrid.PageSize = 5;
subgrid.PagerStyle.AlwaysVisible =
false
;
subgrid.PagerStyle.Mode = GridPagerMode.NextPrevAndNumeric;
subgrid.ClientSettings.AllowColumnsReorder =
true
;
subgrid.ClientSettings.ReorderColumnsOnClient =
true
;
subgrid.EnableViewState =
false
;
// Trial tweaks.
subgrid.ViewStateMode = System.Web.UI.ViewStateMode.Disabled;
subgrid.RegisterWithScriptManager =
true
;
subgrid.ClientIDMode = System.Web.UI.ClientIDMode.Static;

In what radgrid event do you initialize the subgrids (eg: ItemCreated, ItemDataBind)? Do you also bind the subgrids in the same event? Have you set the HierarchyLoadMode of the RadGrid to ServerSide? Is it completely necessary to bind the subgrids before the user actually opens the hierarchical view that contains those subgrids or would it be ok to bind them only when they open such hierarchical view?
Regards,
Manuel

I should also note that it's definitely spiking prior to prerendering on the server-side and not some odd rendering spike on the browser.
You need to have in mind that you are rendering all your RadGrid instances all at once. If you have the main grid with page size 10 and you have 2 RadGrid instances in tabs in each NestedViewTemplate, that makes 21 RadGrids (10 x 2 per parent item + 1 main grid), 10 RadTabStrips and 10 RadMultiPages (1 in each nested item). These are all coming with their own CSS and script files. You can consider reducing the number of controls rendered on initial load by using LoadOnDemand hierarchy loading where each nested table is initialized when the parent grid item is expanded.
Regards,
Veli
the Telerik team

To put the punchline first: It appears that, in fact, it can handle the test scenario. Quite well, so I'm told.
My concern was/is that the rendering time for 20 completely empty and unbound subgrids (resulting in well under 100k of additional output IIRC) is taking in excess of 7.5s on my brand new i7 quad-core laptop and is spiking the CPU long enough to spin up the fan. Even setting my page size to 2 (thus rendering only 4 subgrids, still unpopulated) takes about 3.5s. I've since deployed this to other machines to test and they do not exhibit this behavior and, in fact, the rendering time is nearly immeasurable on those machines. My machine, however, still exhibits this extreme slowness despite having the same code, comparable hardware and the same version of the Telerik suite as the others.
While my immediate performance fears are reduced, I'm still compelled to pinpoint the source of these oddities as I'm concerned about this problem cropping up in a production setting. I'd appreciate any war stories anyone could share regarding this and I will of course share anything I discover regarding this as well.

So your implementation worked? Even though you don't use LoadOnDemand?? How much did it take to for the page containing the nested grids to load?? If it takes less than 3 seconds I am inclined to change my implementation and eliminate the LoadOnDemand!!! It should be nicer!!!
Regards,
Manuel

I can probably shave off a bit more overhead by bulk loading the child records but it's already shaping up to be much more along the lines I was hoping for. Even if under fairly heavy production load that time grows to 2 seconds, most everyone I've showed it to agrees that the snappy behavior of preloading is well worth the up-front cost.
It's probably important to mention that your needs may differ. My sub-grids thus far rarely have more than a few records each. So of course your results may vary. Also, you'll probably want to check your before and after bandwidth usage with something like Fiddler, if you're not already doing so, to see if the increase in I/O is acceptable to your bandwidth constraints.

Is there a property of NestedViewTemplate so that only one item is expanded? Currently if I expand items under multiple rows they all stay expanded. I would like the "previous" nested view to close when I open a new one.
Thanks
milind
I think that the solution presented in this topic will help you attain the single expand functionality you are after.
Best regards,
Sebastian
the Telerik team

I followed the suggestions in the thread and the soft wired _NeedDataSource event just won't fire, the code runs through the parent grid's ItemCreated event and that's it, the child grid's _NeedDataSource event is not fired at all.
Can you help?
Can you ensure that you wire the NeedDataSource event of the nested grid inside the ItemCreated handler of the outer grid and bind it inside the ItemDataBound handler or elsewhere? Thus the NeedDataSource event should be raised as expected. Alternatively, hook the event directly in the markup of the second grid and compare the results.
Also verify that the nested grid is not invisible (Visible = false) as in such case it will not be bound to data and the NeedDataSource event will not be fired.
Regards,
Sebastian
the Telerik team