Build a Nested GridView Control with ASP.NET
The biggest oversight in ASP.NET is the lack of an easy way to create fully functional nested grid and user control views (nested means one or more controls exist in one or more GridView cells; these controls may be grids or user control grids nested n-levels deep.) Propagating data downstream, permitting full editing functionality, and event handling are still very labor intensive. This is a glaring deficiency in the way you can develop Web applications with ASP.NET.
Suppose you want to show customers, orders, order details, and maybe product information from a Northwind database in a related way. The mechanically easy way to derive such a presentation is to establish links between pages and have each subsequent page zoom in to a related downstream piece of information. To put it mildly, this type of implementation results in a tedious series of clicking, posting, and page navigation. (Even with the asynchronous capabilities of Atlas, all of the required clicking can be cumbersome.) Worse still, editing can be a nightmare with partial state changes and database modifications.
The objective is simple: Show all of the orders for each customer in a single page (see Figure 1). (The demonstration is not interested in "prettification"; with a style sheet, you could easily dress up the view.)
Figure 1: A Nested GridView Control Showing Customers and Orders
Building a Master Detail View Using the GridView
Due to space constraints, this article shows only two levels of nesting. However, by the time you are done, you will see that this approach works for n levels of nesting. The only caution is that with very complex presentation styles bandwidth can become an issue.
Tip: If you want a nicely color-coordinated Web application, try Behr's Smart Color tool. It will help you pick a perfectly coordinated, tri-chromatic color palette. Tell them I sent you.
Reviewing the Constituent Parts of the Page
Each level of nesting is composed of three basic parts:
- A page or user control, which basically are the same thing for this demo's purposes
- A GridView (or some other similar type control)
- A UserControl, which will be used to contain the nested elements
- The nested controls to implement the UserControl (these can be individual controls or another GridView)
At the highest level of the nested view is an ASP.NET Web Page. The page is important not only because it will be the root of the presentation layer, but it also is where user data will be stored in session and where changes will be persisted.
The page-level GridView simply repeats and displays the data at the highest level of the relationship. (It is ultimately rendered as an HTML table.)
At every subsequent level of nesting, you will use a UserControlan important element that enables you to divide up pieces of the presentation into manageable parts. The UserControl essentially provides a blank canvas that you can use to design a sub-view and implement the code-behind for that sub-view.
Finally, any child controls you'd like to nest are painted on the UserControls. For now, ignore the mechanics (that is, the code-behind) and focus on building the view.
Assembling the Pieces of the View
The best way to walk through the presentation is to list each step with a brief explanation. Even if you are unfamiliar with GridView, smart tags, or UserControls, the detailed steps should walk you through the process:
- Create a new Web page (or use an existing one in your project).
- Add a GridView to that page. If the GridView is part of a whole page, explore Master pages as a way to get consistent looking pages. DataList and Repeater controls work here too.
- Define bound columns for every element of data in your master object. (I use custom objects more often than not because I like the greater control afforded by custom controls, and I don't need to drag ADO.NET into my presentation layer.)
- Convert one or more bound columns into a template column by clicking on the smart tag at the top-left corner of the GridView, selecting Edit columns from the smart menu, selecting the field to convert, and clicking the self-explanatory link for converting a bound column to a template column (see Figure 2).
Figure 2: Click "Convert this field into a TemplateField"
(In the example in Figure 1, the last column is the template column.)
- Close the Fields dialog.
- Add a UserControl to your project.
- Click the Smart tag on the GridView again and select Edit Templates.
- Drag and drop the UserControl from the solution explorer to the ItemTemplate, remove the existing Label and TextBox, and click Edit UserControl from the Smart tag menu (see Figure 3).
Figure 3: Begin Designing the Nested Sub-view
- Add a second GridView to the UserControl and you have the basic design.
Listing 1 shows you approximately how the ASP code will look after you have completed these steps.
Listing 1: ASP Code After You Have Completed Steps 1 Through 9
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %> <%@ Register Src="Orders.ascx" TagName="Orders" TagPrefix="uc2"%> <%@ Register Src="OrdersControl.ascx" TagName="OrdersControl" TagPrefix="uc1" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:GridView ID="GridView1" runat="server" Height="191px" Width="325px" AutoGenerateColumns="False"> <Columns> <asp:BoundField DataField="CustomerID" HeaderText="Customer ID"> <ItemStyle VerticalAlign="Top" /> <HeaderStyle Wrap="False" /> </asp:BoundField> <asp:BoundField DataField="CompanyName" HeaderText="Company Name"> <ItemStyle VerticalAlign="Top" /> <HeaderStyle Wrap="False" /> </asp:BoundField> <asp:BoundField DataField="ContactName" HeaderText="Contact Name"> <ItemStyle VerticalAlign="Top" /> <HeaderStyle Wrap="False" /> </asp:BoundField> <asp:TemplateField HeaderText="Order Shipping Details"> <EditItemTemplate> </EditItemTemplate> <ItemTemplate> <uc2:Orders ID="Orders1" runat="server"/> </ItemTemplate> <ItemStyle VerticalAlign="Top" /> <HeaderStyle Wrap="False" /> </asp:TemplateField> </Columns> </asp:GridView> </div> </form> </body> </html>
The following are a couple of additional things you can do for further development:
- Define the bound columns for the second GridView on the UserControl.
- Repeat the process for the second and subsequent UserControls if you want additional layers of nesting.
Nested Views Made Easier
Complex nested views can be very challenging. I get more e-mail about nested views (and keyboard hooks) than any other topic. This article showed how to create a basic nested presentation. The key is to use template columns for any fields that will contain nested controls and UserControls. Those UserControls will be critical in managing the code-behind for each sub-view.
About the Author
Paul Kimmel is the VB Today columnist for www.codeguru.com and has written several books on object-oriented programming and .NET. Check out his new book, UML DeMystified, from McGraw-Hill/Osborne. Paul is an architect for Tri-State Hospital Supply Corporation. You may contact him for technology questions at firstname.lastname@example.org.
If you are interested in joining or sponsoring a .NET Users Group, check out www.glugnet.org.
Copyright © 2006 by Paul T. Kimmel. All Rights Reserved.