Both the Repeater and DataList controls—the subjects of this chapter—enable you to display a set of data items at a time. For example, you can use these controls to display all the rows contained in a database table.
The Repeater control is entirely template driven. You can format the rendered output of the control in any way that you please. For example, you can use the Repeater control to display records in a bulleted list, a set of HTML tables, or even in a comma-delimited list.
The DataList control is also template driven. However, unlike the Repeater control, the default behavior of the DataList control is to render its contents into an HTML table. The DataList control renders each record from its data source into a separate HTML table cell.
In this chapter, you learn how to use both of these controls to display database data. You also learn how to use each of the different types of templates that each of the controls supports. Finally, you can see how to handle the different types of events that the controls expose.
The Repeater control provides you with the maximum amount of flexibility in rendering a set of database records. You can format the output of the Repeater control in any way that you please. In this section, you learn how to display data with the Repeater control and handle Repeater control events.
To display data with the Repeater control, you must create an ItemTemplate. For example, the page in Listing 13.1 displays the contents of the Movies database table (see Figure 13.1).
Example 13.1. ShowRepeater.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> html { background-color:silver; } .content { width:600px; border:solid 1px black; background-color:#eeeeee; } .movies { margin:20px 10px; padding:10px; border:dashed 2px black; background-color:white; } </style> <title>Show Repeater</title> </head> <body> <form id="form1" runat="server"> <div class="content"> <asp:Repeater id="rptMovies" DataSourceID="srcMovies" Runat="server"> <ItemTemplate> <div class="movies"> <h1><%#Eval("Title") %></h1> <b>Directed by:</b> <%# Eval("Director") %> <br /> <b>Box Office Totals:</b> <%# Eval("BoxOfficeTotals","{0:c} ") %> </div> </ItemTemplate> </asp:Repeater> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Title,Director,BoxOfficeTotals FROM Movies" Runat="server" /> </div> </form> </body> </html>
The Repeater control in Listing 13.1 displays each record in a separate HTML <div>
tag. A databinding expression is used to display the value of each column.
In Listing 13.1, declarative databinding is used to bind the Repeater to the SqlDataSource
. You also can databind a Repeater control programmatically.
For example, the page in Listing 13.2 contains a Repeater control that renders a JavaScript array. The Repeater control is programmatically databound to the list of files in the Photos directory.
Example 13.2. ShowRepeaterPhotos.aspx
<%@ Page Language="C#" %> <%@ Import Namespace="System.IO" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> void Page_Load() { if (!Page.IsPostBack) { DirectoryInfo dir = new DirectoryInfo(MapPath("~/Photos")); rptPhotos.DataSource = dir.GetFiles("*.jpg"); rptPhotos.DataBind(); } } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> .photo { width:400px; background-color:white; filter:progid:DXImageTransform.Microsoft.Fade(duration=2); } </style> <script type="text/javascript"> var photos = new Array(); window.setInterval(showImage, 5000); function showImage() { if (photos.length > 0) { var index = Math.floor(Math.random() * photos.length); var image = document.getElementById('imgPhoto'), image.src = photos[index]; if (image.filters) { image.filters[0].Apply(); image.filters[0].Play(); } } } </script> <title>Show Repeater Photos</title> </head> <body> <form id="form1" runat="server"> <div> <img id="imgPhoto" alt="" class="photo" /> <script type="text/javascript"> <asp:Repeater id="rptPhotos" Runat="server"> <ItemTemplate> <%# Eval("Name", "photos.push('Photos/{0} ')") %> </ItemTemplate> </asp:Repeater> showImage(); </script> </div> </form> </body> </html>
The page in Listing 13.2 randomly displays a different photo every five seconds. A random image is selected from the JavaScript array and displayed by the JavaScript showImage()
function. An Internet Explorer transition filter is used to create a fade-in effect.
The Repeater control supports five different types of templates:
ItemTemplate—. Formats each item from the data source.
AlternatingItemTemplate—. Formats every other item from the data source.
SeparatorTemplate—. Formats between each item from the data source.
HeaderTemplate—. Formats before all items from the data source.
FooterTemplate—. Formats after all items from the data source.
You are required to use only an ItemTemplate; the other types of templates can be used at your own discretion. The order in which you declare the templates in the Repeater control does not matter.
You can use the SeparatorTemplate to create a banding effect (as in old-time computer paper). In other words, you can use the SeparatorTemplate to display alternating rows with a different background color. This approach is illustrated by the page in Listing 13.3 (see Figure 13.2).
Example 13.3. ShowRepeaterTable.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> html { background-color:silver; } .content { width:600px; border:solid 1px black; background-color:white; } .movies { border-collapse:collapse; } .movies th,.movies td { padding:10px; border-bottom:1px solid black; } .alternating { background-color:#eeeeee; } </style> <title>Show Repeater Table</title> </head> <body> <form id="form1" runat="server"> <div class="content"> <asp:Repeater id="rptMovies" DataSourceID="srcMovies" Runat="server"> <HeaderTemplate> <table class="movies"> <tr> <th>Movie Title</th> <th>Movie Director</th> <th>Box Office Totals</th> </tr> </HeaderTemplate> <ItemTemplate> <tr> <td><%#Eval("Title") %></td> <td><%#Eval("Director") %></td> <td><%#Eval("BoxOfficeTotals","{0:c} ") %></td> </tr> </ItemTemplate> <AlternatingItemTemplate> <tr class="alternating"> <td><%#Eval("Title") %></td> <td><%#Eval("Director") %></td> <td><%#Eval("BoxOfficeTotals","{0:c} ") %></td> </tr> </AlternatingItemTemplate> <FooterTemplate> </table> </FooterTemplate> </asp:Repeater> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Title,Director,BoxOfficeTotals FROM Movies" Runat="server" /> </div> </form> </body> </html>
The Repeater control in Listing 13.3 renders an HTML table in which every other row appears with a gray background color. Notice that this Repeater control uses four out of five of the templates supported by the Repeater: the ItemTemplate, AlternatingItemTemplate, HeaderTemplate, and FooterTemplate.
Notice that the AlternatingItemTemplate contains almost exactly the same content as the ItemTemplate. The only difference is that the <tr>
tag includes a class attribute that changes its background color.
The SeparatorTemplate is used to add content between each data item from the data source. For example, the page in Listing 13.4 uses a SeparatorItemTemplate to create a tab strip with the Repeater control (see Figure 13.3).
Example 13.4. ShowSeparatorTemplate.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> html { background-color:silver; } .content { width:600px; height:400px; padding:10px; border:solid 1px black; background-color:white; } a { color:blue; } </style> <title>Show SeparatorTemplate</title> </head> <body> <form id="form1" runat="server"> <div class="content"> <asp:Repeater id="rptMovieCategories" DataSourceID="srcMovieCategories" Runat="server"> <ItemTemplate> <asp:HyperLink id="lnkMenu" Text='<%#Eval("Name")%>' NavigateUrl='<%#Eval("Id","ShowSeparatorTemplate.aspx?id={0} ")%>' Runat="server" /> </ItemTemplate> <SeparatorTemplate> | </SeparatorTemplate> </asp:Repeater> <asp:Repeater id="rptMovies" DataSourceID="srcMovies" Runat="server"> <HeaderTemplate> <ul> </HeaderTemplate> <ItemTemplate> <li><%#Eval("Title")%></li> </ItemTemplate> <FooterTemplate> </ul> </FooterTemplate> </asp:Repeater> <asp:SqlDataSource id="srcMovieCategories" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Id, Name FROM MovieCategories" Runat="server" /> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Title FROM Movies WHERE CategoryId=@CategoryId" Runat="server"> <SelectParameters> <asp:QueryStringParameter Name="CategoryId" QueryStringField="Id" /> </SelectParameters> </asp:SqlDataSource> </div> </form> </body> </html>
The page in Listing 13.4 contains two Repeater controls. The first Repeater control displays a tab strip of movie categories. The second Repeater control displays a bulleted list of matching movies.
The Repeater control supports the following events:
DataBinding
—. Raised when the Repeater control is bound to its data source.
ItemCommand
—. Raised when a control contained in the Repeater control raises an event.
ItemCreated
—. Raised when each Repeater item is created.
ItemDataBound
—. Raised when each Repeater item is bound.
The page in Listing 13.5 illustrates how you can use the DataBinding
, ItemCommand
, and ItemDataBound
events. This page uses a Repeater control to update, delete, and insert database records (see Figure 13.4).
Example 13.5. EditRepeater.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> // The name of the primary key column string DataKeyName = "Id"; /// <summary> /// Stores the primary keys in ViewState /// </summary> Hashtable Keys { get { if (ViewState["Keys"] == null) ViewState["Keys"] = new Hashtable(); return (Hashtable)ViewState["Keys"]; } } /// <summary> /// Build the primary key collection /// </summary> protected void rptMovies_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { Keys.Add(e.Item.ItemIndex, DataBinder.Eval(e.Item.DataItem, "Id")); } } /// <summary> /// Clear the primary keys when Repeater is rebound /// to its data source /// </summary> protected void rptMovies_DataBinding(object sender, EventArgs e) { Keys.Clear(); } /// <summary> /// When you click the Update,Insert, or Delete /// button, this method executes /// </summary> protected void rptMovies_ItemCommand(object source, RepeaterCommandEventArgs e) { switch (e.CommandName) { case "Update": UpdateMovie(e); break; case "Insert": InsertMovie(e); break; case "Delete": DeleteMovie(e); break; } } /// <summary> /// Update a movie record /// </summary> void UpdateMovie(RepeaterCommandEventArgs e) { // Get the form fields TextBox txtTitle = (TextBox)e.Item.FindControl("txtTitle"); TextBox txtDirector = (TextBox)e.Item.FindControl("txtDirector"); CheckBox chkInTheaters = (CheckBox)e.Item.FindControl("chkInTheaters"); // Set the DataSource parameters srcMovies.UpdateParameters["Id"].DefaultValue = Keys[e.Item.ItemIndex].ToString(); srcMovies.UpdateParameters["Title"].DefaultValue = txtTitle.Text; srcMovies.UpdateParameters["Director"].DefaultValue = txtDirector.Text; srcMovies.UpdateParameters["InTheaters"].DefaultValue = chkInTheaters.Checked.ToString(); // Fire the UpdateCommand srcMovies.Update(); } /// <summary> /// Insert a movie record /// </summary> void InsertMovie(RepeaterCommandEventArgs e) { // Get the form fields TextBox txtTitle = (TextBox)e.Item.FindControl("txtTitle"); TextBox txtDirector = (TextBox)e.Item.FindControl("txtDirector"); CheckBox chkInTheaters = (CheckBox)e.Item.FindControl("chkInTheaters"); // Set the DataSource parameters srcMovies.InsertParameters["Title"].DefaultValue = txtTitle.Text; srcMovies.InsertParameters["Director"].DefaultValue = txtDirector.Text; srcMovies.InsertParameters["InTheaters"].DefaultValue = chkInTheaters.Checked.ToString(); // Fire the InsertCommand srcMovies.Insert(); } /// <summary> /// Delete a movie record /// </summary> void DeleteMovie(RepeaterCommandEventArgs e) { // Set the DataSource parameters srcMovies.DeleteParameters["Id"].DefaultValue = Keys[e.Item.ItemIndex].ToString(); // Fire the DeleteCommand srcMovies.Delete(); } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> html { background-color:silver; } .content { width:600px; height:400px; padding:10px; border:solid 1px black; background-color:white; } .movies td { text-align:center; } a { color:blue; } </style> <title>Edit Repeater</title> </head> <body> <form id="form1" runat="server"> <div class="content"> <asp:Repeater id="rptMovies" DataSourceID="srcMovies" Runat="server" OnItemCommand="rptMovies_ItemCommand" OnItemDataBound= "rptMovies_ItemDataBound" OnDataBinding="rptMovies_DataBinding"> <HeaderTemplate> <table class="movies"> <tr> <th>Title</th> <th>Director</th> <th>In Theaters</th> </tr> </HeaderTemplate> <ItemTemplate> <tr> <td> <asp:TextBox id="txtTitle" Text='<%#Eval("Title")%>' Runat="server" /> </td> <td> <asp:TextBox id="txtDirector" Text='<%#Eval("Director")%>' Runat="server" /> </td> <td> <asp:CheckBox id="chkInTheaters" Checked='<%#Eval("InTheaters")%>' Runat="server" /> </td> <td> <asp:LinkButton id="lnkUpdate" CommandName="Update" Text="Update" Runat="server" /> | <asp:LinkButton id="lnkDelete" CommandName="Delete" Text="Delete" OnClientClick="return confirm('Are you sure?')," Runat="server" /> </td> </tr> </ItemTemplate> <FooterTemplate> <tr> <td> <asp:TextBox id="txtTitle" Runat="server" /> </td> <td> <asp:TextBox id="txtDirector" Runat="server" /> </td> <td> <asp:CheckBox id="chkInTheaters" Runat="server" /> </td> <td> <asp:LinkButton id="lnkInsert" CommandName="Insert" Text="Insert" Runat="server" /> </td> </tr> </table> </FooterTemplate> </asp:Repeater> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies" UpdateCommand="UPDATE Movies SET Title=@Title, Director=@Director,InTheaters=@InTheaters WHERE Id=@Id" InsertCommand="INSERT Movies (Title,Director,InTheaters) VALUES (@Title,@Director, DeleteCommand="DELETE Movies WHERE Id=@Id" Runat="server"> <UpdateParameters> <asp:Parameter Name="Id" /> <asp:Parameter Name="Title" /> <asp:Parameter Name="Director" /> <asp:Parameter Name="InTheaters" /> </UpdateParameters> <InsertParameters> <asp:Parameter Name="Title" /> <asp:Parameter Name="Director" /> <asp:Parameter Name="InTheaters" /> </InsertParameters> <DeleteParameters> <asp:Parameter Name="Id" /> </DeleteParameters> </asp:SqlDataSource> </div> </form> </body> </html>
In Listing 13.5, the ItemDataBound
event handler builds a collection of primary keys from the data source. The collection of primary keys is stored in ViewState so that they will be available after a postback to the server.
The DataBinding
event handler clears the primary key collection when the Repeater is rebound to its data source (after a record is updated or deleted). If you don’t clear the collection, then you get duplicates of the primary keys and an exception is raised.
The ItemCommand
event handler takes care of processing the button click events. When you click an Insert, Update, or Delete button, the event bubbles up and raises the ItemCommmand
event. The ItemCommand
event handler grabs the values from the form fields and calls the Insert()
, Update()
, or Delete()
methods of the SqlDataSource control.
The DataList control, like the Repeater control, is template driven. Unlike the Repeater control, by default, the DataList renders an HTML table. Because the DataList uses a particular layout to render its content, you are provided with more formatting options when using the DataList control.
In this section, you learn how to use the DataList control to display data. You also learn how to render database records in both single-column and multi-column HTML tables. We also explore how you can edit data with the DataList control.
To display data with the DataList control, you must supply the control with an ItemTemplate. The contents of the ItemTemplate are rendered for each data item from the data source.
For example, the page in Listing 13.6 uses a DataList to display the contents of the Movies database table. The ItemTemplate displays the values of the Title, Director, and BoxOfficeTotals columns (see Figure 13.5).
Example 13.6. ShowDataList.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Show DataList</title> </head> <body> <form id="form1" runat="server"> <div> <asp:DataList id="dlstMovies" DataSourceID="srcMovies" Runat="server"> <ItemTemplate> <h1><%#Eval("Title")%></h1> Directed by: <%#Eval("Director") %> <br /> Box Office Totals: <%#Eval("BoxOfficeTotals","{0:c} ") %> </ItemTemplate> </asp:DataList> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Title,Director,BoxOfficeTotals FROM Movies" Runat="server" /> </div> </form> </body> </html>
The DataList in Listing 13.6 renders an HTML table. Each data item is rendered into a separate table cell (<td>
tag). The rendered output of the DataList control in Listing 13.6 looks like this:
<table id="dlstMovies" cellspacing="0" border="0" style="border-collapse:collapse;"> <tr> <td> <h1>Titanic</h1> Directed by: James Cameron <br /> Box Office Totals: $600,000,000.00 </td> </tr> <tr> <td> <h1>Star Wars</h1> Directed by: George Lucas <br /> Box Office Totals: $500,000,000.00 </td> </tr> ... </table>
The default behavior of the DataList control is to render an HTML table. However, you can override this default behavior and display the contents of each data item in a separate HTML <span>
tag. This approach is illustrated in Listing 13.7.
Example 13.7. ShowFlowDataList.aspx
<%@ Page Language="C#" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Show Flow DataList</title> </head> <body> <form id="form1" runat="server"> <div> <asp:DataList id="dlstMovies" DataSourceID="srcMovies" RepeatLayout="Flow" Runat="server"> <ItemTemplate> <%#Eval("Title")%> </ItemTemplate> </asp:DataList> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Title FROM Movies" Runat="server" /> </div> </form> </body> </html>
Notice that the DataList control in Listing 13.7 includes a RepeatLayout
property that has the value Flow
. Each movie title is rendered in a <span>
tag followed by a line-break tag (<br>
).
The RepeatLayout
property accepts one of the following two values:
Table
—. Data Items are rendered in HTML table cells.
Flow
—. Data Items are rendered in HTML <span>
tags.
You can render the contents of a DataList control into a multi-column table in which each data item occupies a separate table cell. Two properties modify the layout of the HTML table rendered by the DataList control:
RepeatColumns
—. The number of columns to display.
RepeatDirection
—. The direction to render the cells. Possible values are Horizontal
and Vertical
.
For example, the page in Listing 13.8 displays the contents of the Movies database table in a three-column layout (see Figure 13.6).
Example 13.8. MultiColumnDataList.aspx
<%@ Page Language="C#" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>MultiColumn DataList</title> </head> <body> <form id="form1" runat="server"> <div> <asp:DataList id="dlstMovies" DataSourceID="srcMovies" RepeatColumns="3" GridLines="Both" Runat="server"> <ItemTemplate> <h1><%#Eval("Title")%></h1> Directed by: <%#Eval("Director") %> <br /> Box Office Totals: <%#Eval("BoxOfficeTotals","{0:c}") %> </ItemTemplate> </asp:DataList> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Title,Director,BoxOfficeTotals FROM Movies" Runat="server" /> </div> </form> </body> </html>
Notice that the DataList control in Listing 13.8 includes a RepeatColumns
property that has the value 3.
If you set the RepeatDirection
property to the value Horizontal
and do not assign a value to the RepeatColumns
property, then the DataList renders its data items horizontally without end.
The DataList control supports all the same templates as the Repeater control:
ItemTemplate—. Formats each item from the data source.
AlternatingItemTemplate—. Formats every other item from the data source.
SeparatorTemplate—. Formats between each item from the data source.
HeaderTemplate—. Formats before all items from the data source.
FooterTemplate—. Formats after all items from the data source
In addition, the DataList supports the following templates:
EditItemTemplate—. Displayed when a row is selected for editing.
SelectedItemTemplate—. Displayed when a row is selected.
The DataList control in Listing 13.9 includes both a HeaderTemplate and a FooterTemplate. The HeaderTemplate contains the caption for the table. The FooterTemplate contains a Label control that displays the total for all the preceding rows (see Figure 13.7).
Example 13.9. ShowDataListTemplates.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> decimal totals; protected void dlstMovies_ItemDataBound(object sender, DataListItemEventArgs e) { if (e.Item.DataItem != null) totals += (decimal)DataBinder.Eval(e.Item.DataItem, "BoxOfficeTotals"); if (e.Item.ItemType == ListItemType.Footer) { Label lblTotal = (Label)e.Item.FindControl("lblTotal"); lblTotal.Text = totals.ToString("c"); } } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> .movies td { padding:10px; text-align:right; } </style> <title>Show DataList Templates</title> </head> <body> <form id="form1" runat="server"> <div> <asp:DataList id="dlstMovies" DataSourceID="srcMovies" GridLines="Horizontal" UseAccessibleHeader="true" OnItemDataBound="dlstMovies_ItemDataBound" CssClass="movies" Runat="server" > <HeaderTemplate> Movie Box Office Totals </HeaderTemplate> <ItemTemplate> <%#Eval("Title")%>: <%#Eval("BoxOfficeTotals","{0:c}") %> </ItemTemplate> <FooterTemplate> <b>Total:</b> <asp:Label id="lblTotal" Runat="server" /> </FooterTemplate> </asp:DataList> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Title,BoxOfficeTotals FROM Movies" Runat="server" /> </div> </form> </body> </html>
The total displayed in the FooterTemplate is calculated by the ItemDataBound
event handler. The Label control is extracted by the FindControl()
method and the total is assigned to the control’s Text
property.
You can use a DataList control as a menu by taking advantage of the control’s SelectedValue
property. For example, the page in Listing 13.10 enables you to pick a movie category and display a list of matching movies (see Figure 13.8).
Example 13.10. SelectDataList.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> html { background-color:orange; } .content { margin:auto; width:600px; background-color:white; } .column { float:left; width:250px; padding:20px; } .movies td { padding:10px; } a { padding:10px; color:red; } a:hover { background-color:Gold; } </style> <title>Select DataList</title> </head> <body> <form id="form1" runat="server"> <div class="content"> <div class="column"> <asp:DataList id="dlstMovieCategories" DataSourceID="srcMovieCategories" DataKeyField="Id" GridLines="Both" CssClass="movies" Runat="server"> <ItemTemplate> <asp:LinkButton id="lnkMovie" Text='<%#Eval("Name") %>' CommandName="Select" Runat="server" /> </ItemTemplate> </asp:DataList> </div> <div class="column"> <asp:DataList id="dlstMovieDetails" DataSourceID="srcMovieDetails" Runat="server"> <ItemTemplate> <h1><%#Eval("Title")%></h1> Directed by: <%#Eval("Director") %> <br /> Box Office Totals: <%#Eval("BoxOfficeTotals","{0:c}") %> </ItemTemplate> </asp:DataList> </div> <br style="clear:both" /> </div> <asp:SqlDataSource id="srcMovieCategories" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Id, Name FROM MovieCategories" Runat="server" /> <asp:SqlDataSource id="srcMovieDetails" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Title,Director,BoxOfficeTotals FROM Movies WHERE CategoryId=@CategoryId" Runat="server"> <SelectParameters> <asp:ControlParameter Name="CategoryId" ControlID="dlstMovieCategories" PropertyName="SelectedValue" /> </SelectParameters> </asp:SqlDataSource> </form> </body> </html>
The page in Listing 13.10 contains two DataList controls. The first control displays a menu of movie categories and the second DataList control displays a list of matching movies.
Notice that the first DataList in Listing 13.10 includes a DataKeyField
property. The DataKeyField
property accepts the name of a primary key column from the data source. When this property is set, the DataList control’s DataKeys collection is populated with the primary keys from the data source when the control is bound to its data source.
The first DataList contains a LinkButton inside its ItemTemplate, which looks like this:
<asp:LinkButton id="lnkMovie" Text='<%#Eval("Name") %>' CommandName="Select" Runat="server" />
Because the LinkButton control’s CommandName
property has the value Select
, clicking the button changes the value of the DataList control’s SelectedValue
property. The DataList control’s SelectedValue
property is used by the second SqlDataSource
control to return movies that match the selected category.
You can use the DataList control to edit database records. However, editing with the DataList control requires more coding than editing with other DataBound controls such as the GridView
, FormView
, or DetailsView
controls.
The page in Listing 13.11 illustrates how you can edit and delete database records with the DataList control (see Figure 13.9).
Example 13.11. EditDataList.aspx
<%@ Page Language="C#" MaintainScrollPositionOnPostback="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> protected void dlstMovies_EditCommand(object source, DataListCommandEventArgs e) { dlstMovies.EditItemIndex = e.Item.ItemIndex; dlstMovies.DataBind(); } protected void dlstMovies_UpdateCommand(object source, DataListCommandEventArgs e) { // Get form fields TextBox txtTitle = (TextBox)e.Item.FindControl("txtTitle"); TextBox txtDirector = (TextBox)e.Item.FindControl("txtDirector"); CheckBox chkInTheaters = (CheckBox)e.Item.FindControl("chkInTheaters"); // Assign parameters srcMovies.UpdateParameters["Id"].DefaultValue = dlstMovies.DataKeys[e.Item.ItemIndex].ToString(); srcMovies.UpdateParameters["Title"].DefaultValue = txtTitle.Text; srcMovies.UpdateParameters["Director"].DefaultValue = txtDirector.Text; srcMovies.UpdateParameters["InTheaters"].DefaultValue = chkInTheaters.Checked.ToString(); // Call SqlDataSource Update srcMovies.Update(); // Take out of Edit mode dlstMovies.EditItemIndex = -1; } protected void dlstMovies_DeleteCommand(object source, DataListCommandEventArgs e) { // Assign parameters srcMovies.DeleteParameters["Id"].DefaultValue = dlstMovies.DataKeys[e.Item.ItemIndex].ToString(); // Call SqlDataSource Delete srcMovies.Delete(); } protected void dlstMovies_CancelCommand(object source, DataListCommandEventArgs e) { dlstMovies.EditItemIndex = -1; dlstMovies.DataBind(); } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <style type="text/css"> html { background-color:silver; } .movies { background-color:white; } .movies td,.movies th { padding:10px; border:solid 1px black; } .edit { background-color:yellow; } a { color:blue; } </style> <title>Edit DataList</title> </head> <body> <form id="form1" runat="server"> <div> <asp:DataList id="dlstMovies" DataSourceID="srcMovies" DataKeyField="Id" GridLines="None" OnEditCommand="dlstMovies_EditCommand" OnCancelCommand="dlstMovies_CancelCommand" OnUpdateCommand="dlstMovies_UpdateCommand" OnDeleteCommand="dlstMovies_DeleteCommand" CssClass="movies" EditItemStyle-CssClass="edit" Runat="server"> <ItemTemplate> <h1><%#Eval("Title")%></h1> Directed by: <%#Eval("Director") %> <br /> In Theaters: <%#Eval("InTheaters") %> <br /><br /> <asp:LinkButton id="lnkEdit" CommandName="Edit" Text="Edit" Runat="server" /> | <asp:LinkButton id="lnkDelete" CommandName="Delete" Text="Delete" OnClientClick="return confirm('Are you sure?')," Runat="server" /> </ItemTemplate> <EditItemTemplate> <asp:Label id="lblTitle" Text="Title:" AssociatedControlID="txtTitle" Runat="server" /> <br /> <asp:TextBox id="txtTitle" Text='<%#Eval("Title")%>' Runat="server" /> <br /><br /> <asp:Label id="lblDirector" Text="Director:" AssociatedControlID="txtDirector" Runat="server" /> <br /> <asp:TextBox id="txtDirector" Text='<%#Eval("Director")%>' Runat="server" /> <br /><br /> <asp:CheckBox id="chkInTheaters" Text="In Theaters" Checked='<%#Eval("InTheaters")%>' Runat="server" /> <br /><br /> <asp:LinkButton id="lnkUpdate" CommandName="Update" Text="Update" Runat="server" /> | <asp:LinkButton id="lnkCancel" CommandName="Cancel" Text="Cancel" Runat="server" /> </EditItemTemplate> </asp:DataList> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Id,Title,Director,InTheaters FROM Movies" UpdateCommand="UPDATE Movies SET Title=@Title, Director=@Director,InTheaters=@InTheaters WHERE Id=@Id" DeleteCommand="DELETE Movies WHERE Id=@Id" Runat="server"> <UpdateParameters> <asp:Parameter Name="Id" /> <asp:Parameter Name="Title" /> <asp:Parameter Name="Director" /> <asp:Parameter Name="InTheaters" /> </UpdateParameters> <DeleteParameters> <asp:Parameter Name="Id" /> </DeleteParameters> </asp:SqlDataSource> </div> </form> </body> </html>
The ItemTemplate contained in the DataList in Listing 13.11 includes an Edit LinkButton and a Delete LinkButton. When you click the Edit LinkButton, the DataList raises its EditCommand
event and the dlstMovies_Edit()
method is executed. Clicking the Delete LinkButton raises the DeleteCommand
event and the dlstMovies_Delete()
method is executed.
The dlstMovies_Edit()
method sets the EditItemIndex
property of the DataList control. The EditItemTemplate is displayed for the item in the DataList that matches the EditItemIndex
.
The EditItemTemplate includes form fields for editing a movie record and an Update and Cancel LinkButton. These LinkButtons raise the UpdateCommand
and CancelCommand
events, and execute the corresponding event handlers.
Notice that the <%@ Page %>
directive includes a MaintainScrollPositionOnPostback
attribute. This attribute causes a page to scroll to the same position whenever you post the page back to the server. For example, when you click the Edit link next to a row in the DataList, the page scrolls to the Edit link that you clicked. This attribute works with Internet Explorer 6+, FireFox 1+, and Opera 8+.
The DataList control includes a rich set of properties that you can use to format the HTML rendered by the control. If you want to associate Cascading Style Sheet rules with different elements of the DataList, then you can take advantage of any of the following properties:
CssClass
—. Enables you to associate a CSS class with the DataList.
AlternatingItemStyle
—. Enables you to format every other row of the DataList.
EditItemStyle
—. Enables you to format the DataList row selected for editing.
FooterStyle
—. Enables you to format the footer row of the DataList.
HeaderStyle
—. Enables you to format the header row of the DataList.
ItemStyle
—. Enables you to format each row displayed by the DataList.
SelectedItemStyle
—. Enables you to format the selected row in the DataList.
SeparatorStyle
—. Enables you to format the row separator displayed by the DataList.
When formatting the DataList, you also need to work with the following properties:
GridLines
—. Enables you to add rules around the cells in the DataList. Possible values are None
, Horizontal
, Vertical
, and Both
.
ShowFooter
—. Enables you to show or hide the footer row.
ShowHeader
—. Enables you to show or hide the header row.
UseAccessibleHeader
—. Enables you to render HTML <th>
tags instead of <td>
tags for the cells in the header row.
To make a page that contains a DataList more accessible to persons with disabilities, you should always include a HeaderTemplate and enable the UserAccessibleHeader
property.
The page in Listing 13.12 illustrates how you can take advantage of several of these formatting properties (see Figure 13.10).
Example 13.12. FormatDataList.aspx
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <style type="text/css"> html { background-color:#Silver; } .movies { font:14px Arial,Sans-Serif; } .header { font-size:18px; letter-spacing:15px; } .item { padding:5px; background-color:#eeeeee; border-bottom:Solid 1px blue; } .alternating { padding:5px; background-color:LightBlue; border-bottom:Solid 1px blue; } </style> <title>Format DataList</title> </head> <body> <form id="form1" runat="server"> <div> <asp:DataList id="dlstMovies" DataSourceID="srcMovies" UseAccessibleHeader="true" CssClass="movies" HeaderStyle-CssClass="header" ItemStyle-CssClass="item" AlternatingItemStyle-CssClass="alternating" Runat="server"> <HeaderTemplate> Movies </HeaderTemplate> <ItemTemplate> <%#Eval("Title")%> </ItemTemplate> </asp:DataList> <asp:SqlDataSource id="srcMovies" ConnectionString="<%$ ConnectionStrings:Movies %>" SelectCommand="SELECT Title FROM Movies" Runat="server" /> </div> </form> </body> </html>
In this chapter, you learned how to use the Repeater control and the DataList controls to display a set of database records. First, you learned how to use the Repeater control to display and edit database records. For example, you learned how to use the Repeater control to enable users to edit, delete, and insert database records.
In the second half of this chapter, you learned how to work with the DataList control. You learned how to render both single and multi-column tables with the DataList control. You also learned how to selected rows with the DataList control. Finally, you learned how to edit records using the DataList control.