RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Nested DataGrids Simplify Hierarchical Data Display : Page 3

Learn how to use nested DataGrids to display hierarchical data and avoid the maintenance nightmare of dynamically-created HTML tables.

Other Data-Binding Syntax Applications
Once you understand the hierarchy of nested controls, you'll find numerous additional applications for nested DataGrids. For example, suppose you're displaying orders and their products, but you don't want to display the nested DataGrid if the order contains no products. The DataGrid's Visible property is the obvious place to begin. You can combine it with data-binding syntax as follows:

   Visible='<%# ((DataRowView)Container.DataItem).Row.GetChildRows(
       "Orders_Products").Length > 0 %>'
This is nearly identical to the syntax used for the DataSource property, except that it returns True only if the length of the array returned by GetChildRows() is greater than zero—in other words, the Visible property is set to True only if there are one or more products for the current order.

The Parent of a Parent's Parent Problem
Unfortunately understanding the data-binding syntax is not sufficient for all hierarchical problems. For example, suppose you want to sort the data in an innermost loop in an order other than the way the database returned it. The GetChildRows() method does not specify a sort order. As another example, consider an innermost loop that must call GetChildRows() on the data of a higher-level loop, for example, two loops up:

That's just messy! The appropriate approach for both of these problems is to go back to the code-behind approach and use the OnItemDataBound event instead. The OnItemDataBound event occurs for multi-record controls when the control creates a ControlItem and binds it to a record; therefore, the event is an excellent place to discover any nested controls, set their DataSource and call DataBind().

   protected void rptOuter_ItemDataBound(
     object sender, RepeaterItemEventArgs e) 
     if (e.Item.ItemType == ListItemType.Item ||
           e.Item.ItemType == ListItemType.AlternatingItem) {
       Repeater rptInner =      (Repeater)e.Item.FindControl("rptInner");
       rptInner.DataSource =
Figure 5. Northwind's Data Model: The sample orders advanced search sample primarily displays orders and order details.
} }
Notice the check for e.Item.ItemType. The .NET Framework calls the ItemDataBound event for headers and footers as well as ControlItems, so the if statement is very important.

This approach requires more code and is slightly more complicated than the data-binding syntax, but works in all data-binding scenarios, and is less error-prone because it can take advantage of compiler-provided type checking. One could make a case for using the code-behind approach exclusively, thereby choosing consistency and reliability over convenience. It would ultimately be a matter of personal preference.

Putting It All Together
The accompanying source code, the majority of which was generated by Blue Ink, a rapid application development tool, compiles to a fully working five-tier application with View/Add/Update/Search pages for all the tables in the Northwind sample database (you can review Northwind's data model in Figure 5). The Orders_SearchAdvanced.aspx page (not generated), is relevant to this article. It illustrates all the concepts mentioned thus far plus a few extra (such as searching using multi-value search criteria), within an enterprise-level, real world environment. You can try out this working version to get a better sense of how the application acts from the user point of view.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date