In-Depth
Choose the Right Tab Control
ASP.NET's Repeater, DataList, and DataGrid controls display data in a tabular format with various features. Learn which control is the best fit for your app.
P>
Technology Toolbox: VB.NET, SQL Server 2000, ASP.NET, Visual Studio .NET 2003
ASP.NET supports three types of list controls that you can use to display data in a tabular format: Repeater, DataList, and DataGrid. Each has specific strengths and weaknesses that you should take into consideration before selecting one for your application. In this article, I'll cover the controls' features and when it's best to use each one. For a preview of what ASP.NET 2.0 has to offer, see the sidebar, "What's New for Tabular List Controls in ASP.NET 2.0?" Download the sample Web pages described in this article here.
The Repeater control is the simplest of the ASP.NET list controls. It's used traditionally to display the data from a data source one item after the other (although you can customize it to view information in the classic rows and columns view). It provides a read-only view, and it doesn't support inline editing, paging, or sorting.
The Repeater has no default appearance, even when it's bound to a default data source. It requires a data source and at least one of the supported template tags:
<HeaderTemplate>
<ItemTemplate>
<AlternatingItemTemplate>
<FooterTemplate>
ASP.NET applies the formatting defined inside these tags to the items of that type. Consider how you use the Repeater format templates to create a table view of the SQL Server Authors database table (see Listing 1). Notice that the HTML Table definition begins inside the <HeaderTemplate> and concludes inside the <FooterTemplate>.
You can associate a server-side event handler to provide additional functionality. For example, if you supply an event handler for the Repeater's OnItemCommand event, your event handler fires whenever a user clicks on a child control within the Repeater:
<asp:repeater id="pubsRepeater"
OnItemCommand="myItemEventHandler"
runat="server">
Keep in mind that all child control events inside the Repeater "bubble up" to this event handler, so you'll need to provide logic within it to determine what was clicked on.
When you look at the output of the Repeater for the Authors example, you can see that the Repeater is the simplest of all tabular list controls (see Figure 1). You should use it when you want to display data from a repeatable data source in a simple, read-only format. You don't need to support in-line editing, and you don't need event handling capabilities for child controls within the table.
Display Items Consecutively
The DataList control supports all the features the Repeater does, but it also provides several additional features and more formatting options. You use this control when you want to display items from a data source one after the other, but not in a traditional rows and columns view. The DataList renders as an HTML table, so the formatting in the Repeater example to get a classic rows and columns view of the data doesn't work. To get that view, you'd have to set the DataList property called ExtractTemplateRows to True, then use <ASP:TABLE>, <ASP:TABLEROW>, and <ASP:TABLECELL> server controls nested within the template tags. For this reason, I don't recommend using the DataList control if you want to render your output in the classic rows and columns view.
To use the DataList, you associate it with a data source and specify one of the templates you saw earlier. The DataList also supports these templates: EditItemTemplate, which defines the display for the record that's being edited; and SelectedItemTemplate, which defines the display for the record that's selected currently. And it supports the use of styles for each item type. Instead of having to embed style information, you can use the appropriate style template tag for each individual item type. This includes support for links to external stylesheets as well:
<HeaderStyle Font-Size="X-Small">
</HeaderStyle>
The DataList supports four built-in events: Edit (DataList.EditCommand), Delete (DataList.DeleteCommand), Update (DataList.UpdateCommand), and Cancel (DataList.CancelCommand). When you add one of the child controls that support these events (Button, LinkButton, and ImageButton) to one of the templates and associate the control with one of these built-in commands, ASP.NET fires the associated event handler automatically.
Here's an example of a Button control inside of an <ItemTemplate> that raises an EditCommand event when clicked on:
<ItemTemplate>
<asp:LinkButton ID=EditButton
CommandName="edit">Edit</asp:LinkButton>
</ItemTemplate>
Keep in mind that the ItemCommand event also fires, but before the specific command name event (in this case, EditCommand).
You can also create your own command name and use the ItemCommand event handler to process it. To do this, use one of the child controls that support these events in one of the DataList's templates. Here's an example of an <asp:LinkButton> and the event handler code to process it:
<asp:LinkButton ID=EditButton
CommandName="Special">
Special Command
</asp:LinkButton>
Private Sub myDataList_ItemCommand ( _
ByVal sender As System.Object, _
ByVal e As DataListCommandEventArgs) _
Handles pubsDataList.ItemCommand
Select Case e.CommandName
Case "Special"
' Specialized logic goes here
End Select
End Sub
Take the Authors example and apply it to the DataList, but this time use the DataList to display the data in sections. Also use the <EditItemTemplate> and command event handlers to provide inline-editing capabilities. I've included the DataList definition (see Listing 2) and the code-behind file with the event handlers for the DataList (see Listing 3).
Set the EditItemIndex
When you click on the Edit link button, the EditCommand event handler is fired and you set the EditItemIndex for the DataList. When you rebind the data, ASP.NET uses the <EditItemTemplate> formatting information to create textboxes to display that record's information so the user can edit the information. If the user selects the Update link button, you can save the record data from the textboxes back to the data source. We could have put the code for all commands inside the ItemCommand event handler, but using the standard command event handler that's provided yields much cleaner code.
You're also able to force the DataList to render using HTML <span> tags instead of <table> tags by setting the RepeatLayout property to "Flow" (instead of "Table," which is the default). You can adjust the RepeatColumns property if you want to display more than one data record on a line (the default is 1).
The output of the Authors example using the DataList appears in a sectional view that supports inline editing (see Figure 2). It's best to use the DataList instead of a Repeater (or DataGrid) when you don't need a classic rows and columns view of your data, want to provide simplistic inline editing, need greater event handling capabilities than the Repeater offers, and don't need paging or sorting capabilities.
The DataGrid is the most sophisticated of the tabular list controls. It provides the most functionality and customization options, giving you the most control over rendered output. As you've seen, creating a classic rows and columns view using the Repeater control is fairly simple. The DataGrid provides this view by default by defining the control and binding it to a data source:
<asp:DataGrid id="myDataGrid"
runat="server">
myDataGrid.DataSource = _
ds.Tables("authors").DefaultView
myDataGrid.DataBind()
Keep in mind, however, that the overhead involved with the DataGrid (specifically the view state) is much higher than it is for the Repeater control. For performance reasons, you'll probably want to use the Repeater control if all you want is a read-only rows and columns view of your data.
Using the DataGrid results in a set of columns that are displayed in the order they're provided in the data source. You can also control which columns are displayed and in what order by setting the Grid's AutoGenerateColumns property to False and then using bound columns (<asp:boundcolumn>) to map the order and binding of grid columns to data table columns:
<asp:DataGrid id="myDataGrid"
runat="server">
<Columns>
<asp:BoundColumn DataField="name">
</asp:BoundColumn>
</Columns>
</asp:DataGrid>
You also have the same wealth of style template tags to choose from to take control of the look and feel of your grid. The DataGrid also supports a style template for pagers. However, it doesn't support a separator item or style, though you can render this easily using the DataGrid's overall row-formatting features, such as cell spacing and border.
Streamline Inline Editing
One of the prime features of the DataGrid is its support for more streamlined inline editing. You don't have to create textbox controls; the DataGrid provides this capability. All you need to do is define your bound columns, then add logic to determine the grid's edited item index (just as you do with the DataList control) when an item is clicked on. ASP.NET generates textboxes automatically in place of the read-only text and fills in the values. One drawback of this feature is that the size of the textbox (21 characters) is static across all bound columns, so you could end up with a textbox that is too small or too large for your purposes. If you want more granular control over the textbox size, you can always use the <EditItemTemplate> to define it. Here's an example of a DataGrid that displays a name and an address, where the name uses the standard inline editing textbox and the address uses a custom textbox of 60 characters:
<asp:BoundColumn DataField="name">
</asp:BoundColumn>
<asp:TemplateColumn>
<ItemTemplate>
<asp:Label
text='<%# Container.DataItem("address")%>'
runat="server">
</asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID=txtAddress
text='<%# Container.DataItem("address")%>'
size="60" runat="server">
</asp:TextBox>
</EditItemTemplate>
</asp:TemplateColumn>
The DataGrid also supports the use of command "items" within a column. Similar to the <asp:LinkButton> inside <ItemTemplate> in the DataList example, you can add the <asp:EditCommandColumn> to hook up the Grid's inline editing functionality:
<asp:EditCommandColumn EditText="Edit"
CancelText="Cancel"
UpdateText="Update">
</asp:EditCommandColumn>
The only thing you need to do to support inline editing is to provide event handlers for EditCommand and CancelCommand, so you can set (or reset) the value of the Grid's EditItemIndex:
' Set the index
myGrid.EditItemIndex = e.Item.ItemIndex
' Reset the index
myGrid.EditItemIndex = -1
You can also define an <asp:ButtonColumn> or <asp:HyperlinkColumn> for additional customized events. Here's an example of an <asp:ButtonColumn> that is tied to a Delete image, which you can then use for deleting a record in your grid:
<asp:ButtonColumn
Text="<img border=0 src=delete.gif"
CommandName="Delete">
Given you've used the standard command name "Delete," you'll use the standard DeleteCommand event handler to process this button click. If you wanted to use one of the nonstandard command names, you'd need to use the ItemCommand event handler to process the button click.
The DataGrid provides a built-in mechanism for paging. If you set the AllowPaging property to True, the Grid provides either numeric or Prev/Next "Pager" navigation controls. You can control the number of items per page by setting the PageSize property (the default value is 10). The only code you need to write to support paging is code to set the Grid's page index whenever users click on one of the "Pager" navigation controls (which fires the PageIndexChanged event):
myGrid.CurrentPageIndex = e.NewPageIndex
If you don't like the look and feel of ASP.NET's default paging, you can always customize it by using the <PagerItem> and <PagerItemStyle> tags. Or, you can bypass the Grid's built-in paging features and add your own by hooking in your "Pager" navigation controls outside of the DataGrid.
The DataGrid provides support for what it calls sorting, but it's hardly what you'd think of as built-in sorting. Really, what it provides is an event handler that is called when you click on the heading of a column. Enable this feature by setting the AllowSorting property of the Grid to True and setting the SortExpression property of each sortable column:
<asp:BoundColumn DataField="name"
SortExpression="name" HeaderText="Name">
You fire the Grid's SortCommand event by clicking on the column header, but that doesn't actually sort the data. You're responsible for re-querying the data and either sorting it through the query or providing a data view with the new sort criteria.
Look at the complete ASP.NET page for the Authors example using the DataGrid (see Listing 4) and the associated code-behind file with all the event handlers to support inline editing, paging, and sorting (see Listing 5). Notice how you implemented the sorting feature. Your grid supports sorting on several of the fields. The field name is stored as the sort when the user clicks on one of these headers. You're also able to keep track of whether the sort is ascending or descending. This information is then used in a data view when binding data to the grid. You could have also used this information to manipulate the SELECT query directly instead of using a data view.
Also notice that in the ItemDataBound event handler (which is called for each row that is bound to the DataGrid), you're adding an Up/Down arrow (using the Webdings font) to the header column that's being sorted currently. This lets the user know which column is being sorted, and whether the sort is ascending or descending. This is just one of the cool tricks you can use in conjunction with the DataGrid to enrich the UI.
The output of the Authors example using the DataGrid results in a rows and columns view that supports inline editing, paging, and sorting (see Figure 3). As you can see, the DataGrid is the most powerful of the tabular list controls, but its power can come at a performance price. You should use it when you want a classic rows and columns view of your data with editing features, want to provide more advanced inline editing, need the most control over the rendered output, and need paging and sorting capabilities.
The Repeater, DataList, and DataGrid controls provide you with various options for displaying tabular data to users. Selecting the control that best fits your application's end goal can help you avoid the performance penalties of selecting a control that's too robust, as well as having to write mounds of custom code to support a control that's not robust enough.