From the December 2001 issue of MSDN Magazine.
|DataList vs. DataGrid in ASP.NET |
|Download the code for this article: ASP0112.exe (40KB)|
Browse the code for this article at Code Center: Guitaromania DataGrid
| n my last column (September 2001) I looked at ASP standard server-side controls and showed how they simplify Web-based server-side UI by helping you manage the HTML that ends up on the client machine using programmatic abstractions (the server-side control classes for HTMLControls and WebControls). This month I want to look at two of the more specialized controls that come with the ASP.NET Framework: the DataList and the DataGrid. Both of these controls are full-featured data-managing tools. In addition to providing a simplified UI programming model for displaying data, ASP.NET includes facilities for binding data sources to these controls so you don't have to write all the code necessary to fish around a database and present your content. This month I'll compare and contrast the DataGrid and DataList controls, starting with DataGrid.|
Grids (two-dimensional tables) are a classic way to present data. They've been around since the beginning of computing. The first killer application for the PC was the spreadsheet, a grid-oriented way of managing data. Throughout the 1990s, several companies made a lot of money selling grid controls—including Visual Basic® custom controls (VBX) in the early 1990s, and Java applets and ActiveX® controls during the mid- to late 1990s. It makes complete sense to have the equivalent functionality within ASP.NET.
For sample code this month, I've set up two separate pages with similar functionality—the ability to interactively select items from an inventory. However, one page uses a DataGrid and the other uses a DataList. I'll examine the features of each. This sort of functionality is very useful for Web site features such as shopping carts. Figure 1 shows a page that uses a DataGrid.
Figure 1 DataGrid Displaying Product Info
The idea behind the interface in this example is that you get to see all of the available inventory and select from the inventory by pressing a button. Before looking at how to accomplish this through the DataGrid, let's look at how ASP.NET manages binding data to these controls automatically.
Data Binding DataGrid and DataList (among other controls) iterate over a collection automatically and render some HTML for each item (you specify the layout using templates). The automatic data binding of collections works for the following controls: HtmlSelect, CheckBoxList, DataGrid, DataList, Repeater, DropDownList, ComboBox, ListBox, and RadioButtonList. Each of these controls will automatically bind to the following classes representing collections: Array, ArrayList, HashTable, Queue, SortedList, Stack, StringCollection, DataView, DataTable, DataSet, SqlDataReader, and the OleDbDataReader.
Each of the controls I just listed (including DataGrid and DataList) include a property named DataSource. The DataSource property can be any System.Object, but for the data binding to work over a collection, it has to implement IEnumerable.
ASP.NET has a very convenient binding syntax. For example, Figure 2 includes a little bit of code that sets up an ArrayList full of data, a ListBox control, a set of RadioButtons, and a regular HTML selection control. Then the page binds the ArrayList to the various controls and renders the right HTML on the client.
Figure 2 includes some standard ASP.NET code describing a form with some standard server-side controls like you saw in the September ASP Column. The script block sets up an ArrayList and calls Control.DataBind (remember, System.Web.UI.Page derives from Control). DataBind connects the controls to their DataSource properties. Figure 3 shows the results of the data binding as they appear on the client's browser.
Figure 3 Data in the Browser
The DataGrid Binding to a standard collection is straightforward enough. ASP.NET saves you the trouble of iterating through the list yourself and pushing the HTML out to the browser by hand. While these controls are definitely very useful, modern Web sites demand more sophisticated data presentation. To make it easier to create sophisticated UIs, ASP.NET includes the DataGrid control.
The ASP.NET DataGrid control renders a table as a multicolumn grid. The DataGrid can include different column types (heterogeneous columns) for defining the layout of the cell contents. These include bound, button, and template columns, among others. In addition, the DataGrid supports interactive functionality such as column sorting, editing, and commands.
Placing a DataGrid on an ASPX Page When defining a DataGrid control on your ASP.NET page, you first generate a data source and plug it into the DataGrid control in a fashion similar to what I've described. The DataGrid control then displays the fields of a data source as columns in a table, and each record is represented by a separate row in the DataGrid. Figure 4 shows the ASPX source code for setting up the two DataGrid controls shown in Figure 1.
The page in Figure 1 includes two DataGrids. The first grid represents the available inventory. The second grid represents the selected items. The inventory grid is set up entirely using ASP.NET declarations. Notice that the DataGrid includes three bound columns, a button column, and a custom template column (which shows a picture). The column types are nested within the DataGrid declarations. The call to DataBinder.Eval within the TemplateColumn/ItemTemplate declarations instruct ASP.NET to pull out the image field and generate an image tag. Notice the syntax surrounding the call to DataBinder.Eval: the <%# and %> tags tell ASP.NET to bind the data coming from the call to Eval to the image control within the ItemTemplate.
The second grid doesn't declare any columns in the ASPX page. They're added programmatically in the code-behind page, as you'll see in a moment. Finally, notice that the SelectedItemsGrid points to SelectedItemsGrid_Command to handle commands (this is the function that will handle the button events). Figure 5 lists the different kinds of column types you may use with a DataGrid.
Programming the DataGrid If all you want to do is show your data in rows and columns, you can install a table-oriented DataSource in your DataGrid and stop there. ASP.NET will automatically iterate through the table rows and show them. But it's often useful to add some interactive functionality to the DataGrid.
Figure 6 shows the skeleton code for managing the DataGrid. I'll go over each piece in detail.
Setting up a DataSource The first step in programming a DataGrid is to set up its DataSource property. There are several ways to establish a DataSource. For most real-world applications, you'd probably use a SqlConnection object and a SqlCommand object to create a DataReader representing the database. I'll look at integrating ADO.NET with ASP.NET in a future column. For this example, I created a table by hand using the common language runtime (CLR) classes DataTable, DataRow, and DataView. The Page_Load and CreateDataSource method implementations can be found in the code download at the link at the top of this article.
Page_Load calls CreateDataSource and adds DataRow objects to the DataTable CLR class to form a table. Then CreateDataSource makes a DataView object out of the table and returns the DataView, where it is bound to the controls when the page loads. Remember the SelectedItemsGrid declared on the ASPX page without the column? SelectedItemsGrid's columns are added programmatically. In addition to creating and binding a data source for the InventoryGrid, Page_Load also creates a DataView for the SelectedItemsGrid. These steps are necessary to make the grid bind automatically. The loading code also adds a button column. (There's no reason the columns have to be added programmatically—I just did it this way to show it can be done.)
Selecting and Deselecting Items The button column within the InventoryGrid is useless without a command handler. The method InventoryGrid_Command handles button presses within the InventoryGrid. Figure 7 shows the InventoryGrid_Command method.
Pressing the Add button on the client browser generates a command event for the InventoryGrid, which is picked up within InventoryGrid_Command. Because this is a DataGrid, the DataGridCommandEventArgs.Item property includes the row of data selected by the user represented by TableCells. If the command name (the ID of the control generating the command event) is Add, this method creates a new row and adds it to the SelectedItemsGrid.
Of course, users would probably also like to deselect items (as when removing items from a shopping cart). The SelectedItemsGrid includes a button column for removing items from the grid. Figure 8 shows the command handler for the SelectedItemsGrid.
The data selected for removal comes through the DataGridCommandEventArgs parameter in the form of a TableCell. Removing the item requires you to set up a filter to find the row that includes the product number. Once you find the row, you may delete it. The SelectedItemsView enables the data binding between the SelectedItemsData and the SelectedItemsGrid. Deleting the row from the view and then performing a DataBind on the SelectedItemsGrid removes the item from the DataGrid.
The DataList As mentioned earlier, another alternative for displaying data is the DataList. The ASP.NET DataList displays items from a data source. However, rather than displaying rows and columns, the DataList displays the contents of your data in more of a "list of records" type of format using templates. The templates customize the appearance and content of the DataList. Figure 9 shows the same data from the DataGrid example. However, this example uses the DataList control to show the inventory. (This example uses the same DataGrid setup to display the selected items.)
Figure 9 Using the DataList Control
Placing a DataList on the ASPX Page The first step in setting up a DataList is to declare one on your ASPX page. This process is similar to declaring a DataGrid. Figure 10 shows the ASPX code for declaring the DataList shown in Figure 9.
As with the DataGrid declaration, the DataList sandwiches one or more template declarations between the DataList tags. The code in Figure 10 lists an ItemTemplate which will push the image tag out to the client, followed by the product name, product number, price, and a button to press to select the item. Also notice the example uses a SeparatorTemplate to define HTML tags to be pushed out to the client browser between items. Figure 11 lists the templates available for use with the DataList. Finally, the DataList in the example defines a SelectedItemTemplate which colors the background of the selected item light blue.
Programming the DataList The DataList has a programmable aspect to it, just like the DataGrid does. Once the DataList is declared on the ASPX page, it needs to have a DataSource associated with it. This is done within the Page_Load handler, just as in the DataGrid example. Once the DataList control is bound to the DataSource, ASP.NET goes through each row within the DataSource and renders the tags defined within the templates. The main difference between the DataGrid and the DataList is that the DataGrid is modeled after a table while the model under the DataList is a list of rows.
The code for hooking up the DataList to its DataSource and for handling the button press to select an item (guitaromaniadatalist.cs) is available in the code download.
Selecting an Item within the DataList DataList controls may handle commands (just as the DataGrid does). Guitaromaniadatalist.cs defines a method named InventoryList_Command, which responds to the Select button within the DataList. Whereas the DataGrid responds to commands by passing in the selected row data as a set of table cells, the DataList simply passes in the selected index. The handler selects a certain item within the InventoryList. When the page renders again, the selected item will be shown using the SelectedItem template (in this case, the selected item will have a light blue background). The handler also extracts the selected item's data from the DataSource (using the index of the selected item) and adds the item to the SelectedItemsGrid DataGrid.
Conclusion As far as UI programming goes, the main contribution of ASP.NET lies in providing useful abstractions over the normal HTML-tag-style programming of classic ASP. Two of the main ASP.NET UI abstractions include the DataGrid and the DataList controls. Once connected to a data source, these two controls iterate through the rows in the data source, generating HTML at the browser end for rendering either a table (in the case of the DataGrid) or a simple list of rows (in the case of the DataList). The DataGrid displays a table in the standard row/column format while the DataList displays the data source as a list of records. In future columns I'll look more closely at binding data to controls—especially using ADO.NET.
Send questions and comments for George to firstname.lastname@example.org.
| George Shepherd is a software consultant and an instructor with DevelopMentor. George is the coauthor of MFC Internals (Addison-Wesley, 1996), Programming Visual C++ (Microsoft Press, 1998), and Applied .NET (Addison-Wesley, 2001). George may be reached at email@example.com.|