The intent of this series is to provide more information concerning the functionality and limitations of the available ASP.NET 2.0 data controls. This will mostly be demonstrated through the use of code samples. Once this series is complete, I will demonstrate how one can AJAX enable some of these samples to improve the overall user experience. Therefore, this series will address the basics first before moving onto more advanced tools. Many will feel that there is enough information available concerning these matters. However, for completeness sake, I feel it is important to provide a good foundation from which to launch future articles from. The articles in this series will address typical scenarios that one might encounter in terms of developing with ASP.NET data controls.
The SqlDataSource control is used throughout the series for simplicities sake.
This is the third article in a three part series of articles pertaining to the understanding and application of ASP.NET 2.0 data controls. This article will address common functionality that may be required from ASP.NET DataList and DataRepeater data controls.
Based on various Microsoft documentation, the ASP.NET DataList and Repeater can be summarised as follows.
The DataList control is a data bound list control that displays items using templates. Use the DataList control to display a template-defined data bound list. The DataList control supports selecting and editing. The contents of the DataList control can be manipulated by using templates. In my experience, I have found the DataList control to be useful and well suited to websites that have content focusing on the selling of products. One is able to build rich product catalogs with relative ease using the DataList control.
The Repeater control is a basic templated data-bound list. It has no built-in layout or styles, so you must explicitly declare all HTML layout, formatting, and style tags within the control's templates. The Repeater control is the only Web control that allows a developer to split HTML tags across the templates. To create a table using templates, include the begin table tag (<table>) in the HeaderTemplate, a single table row tag (<tr>) in the ItemTemplate, and the end table tag (</table>) in the FooterTemplate. The Repeater control has no built-in selection capabilities or editing support. The user can use the ItemCommand event to process control events that are raised from the templates to the control. In my experience, as with the DataList control, I have found the Repeater control useful and well suited to implementing product catalogs. I have also used the Repeater control to produce a very simple lightweight reporting solution.
I have not mentioned this before in any of the previous articles, but it should be noted that ASP.NET server controls such as the Repeater, DataList and GridView Web controls can contain child controls that raise events. Therefore, a DataList control may have a child control as part of a template that raises an event. The child control event is "bubbled up " (sent up) to the control's container. The container control raises an event called RowCommand with parameter values. These values allow one to determine which control raised the original event. One is then able to respond to this event. Alternatively, one can write individual event handlers for the child controls.
For this example, a DataList control is used to display a list of customers similar to a contact list. The customers will be displayed in a template that resembles a business card. One is able to view a quick report of orders for a selected customer. The order report will be displayed in a simple Repeater control. A SqlDataSource is used to retrieve data from the database. The DataList allows one to edit existing customers as well as view more detailed information concerning a customer. Something similar to a master detail scenario has been setup such that the DataList behaves as the master and the Repeater control as the detail. However, the Repeater will not display detail concerning the customer but instead a list of orders. The DataList passes a unique id to a modal dialog that contains the Repeater. The repeater will then load a list of orders based on the unique id it recieves.
For this example, a SqlDataSource is used for the DataList data source. The DataList DataSourceID is set to the id of the SqlDataSource.
The following code snippet illustrates the setup required in terms of the DataList control.
We will explore the use of the OnEditCommand, OnCancelCommand, OnUpdateCommand and OnItemCommand later in the article. The important thing to note is that we are using a DataSourceID because we are binding to a SqlDataSource. By default, the items will display accross three columns. CustomerId is used as the primary key or DataKeyField.
<asp:DataList ID="CustomerDataList"
runat="server" DataSourceID="CustomerSqlDataSource"
RepeatColumns="3" DataKeyField="CustomerID"
OnEditCommand="CustomerDataList_EditCommand"
OnCancelCommand="CustomerDataList_CancelCommand"
OnUpdateCommand="CustomerDataList_UpdateCommand"
OnItemCommand="CustomerDataList_ItemCommand">
<EditItemTemplate>
<table>
<tr>
<td colspan="2" style="font-size: 10px">
</td>
</tr>
<tr>
<td style="width: 5px;
background-color: #4682B4">
<asp:Panel ID="SidePanel"
Width="5px" runat="server" />
</td>
<td>
<asp:Panel ID="CustomerPanel"
runat="server" CssClass="CustomerPanel">
<table>
<tr>
<td style="width: 50px">
</td>
<td style="width: 5px">
</td>
<td style="width: 235px">
</td>
</tr>
<tr>
<th align="right">
Company Name:</th>
<td>
</td>
<td>
<asp:TextBox ID="CompanyNameTextBox"
runat="server" Text='<%# Bind("CompanyName") %>' />
<asp:RequiredFieldValidator
ID="CompanyRfv" runat="server"
ControlToValidate="CompanyNameTextBox"
ErrorMessage="*" ToolTip="Company name is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<th align="right">
Contact:</th>
<td>
</td>
<td>
<asp:TextBox ID="ContactNameTextBox"
runat="server" Text='<%# Bind("ContactName") %>' />
<asp:RequiredFieldValidator
ID="ContactNameRfv"
runat="server" ControlToValidate="ContactNameTextBox"
ErrorMessage="*" ToolTip="Contact name is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<th align="right">
Title:</th>
<td>
</td>
<td>
<asp:TextBox ID="ContactTitleTextBox"
runat="server" Text='<%# Bind("ContactTitle") %>' />
<asp:RequiredFieldValidator
ID="ContactTitleRfv"
runat="server" ControlToValidate="ContactTitleTextBox"
ErrorMessage="*" ToolTip="Contact title is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<th align="right">
Phone:</th>
<td>
</td>
<td>
<asp:TextBox ID="PhoneTextBox"
runat="server" Text='<%# Bind("Phone") %>' />
<asp:RequiredFieldValidator
ID="PhoneTextBoxRfv"
runat="server" ControlToValidate="PhoneTextBox"
ErrorMessage="*" ToolTip="Phone number is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<th align="right">
Fax:</th>
<td>
</td>
<td>
<asp:TextBox ID="FaxTextBox"
runat="server" Text='<%# Bind("Fax") %>' />
<asp:RequiredFieldValidator
ID="FaxRfv" runat="server"
ControlToValidate="FaxTextBox"
ErrorMessage="*" ToolTip="Fax number is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<th align="right">
Address:</th>
<td>
</td>
<td>
<asp:TextBox ID="AddressTextBox"
runat="server" Text='<%# Bind("Address") %>' />
<asp:RequiredFieldValidator
ID="AddressRfv" runat="server"
ControlToValidate="AddressTextBox"
ErrorMessage="*" ToolTip="Address is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<th align="right">
City:</th>
<td>
</td>
<td>
<asp:TextBox ID="CityTextBox"
runat="server" Text='<%# Bind("City") %>' />
<asp:RequiredFieldValidator
ID="CityRfv" runat="server"
ControlToValidate="CityTextBox"
ErrorMessage="*" ToolTip="City is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<th align="right">
Region:</th>
<td>
</td>
<td>
<asp:TextBox ID="RegionTextBox"
runat="server" Text='<%# Bind("Region") %>' />
<asp:RequiredFieldValidator
ID="RegionRfv" runat="server"
ControlToValidate="RegionTextBox"
ErrorMessage="*" ToolTip="Region is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<th align="right">
Postal Code:</th>
<td>
</td>
<td>
<asp:TextBox ID="PostalCodeTextBox"
runat="server" Text='<%# Bind("PostalCode") %>' />
<asp:RequiredFieldValidator
ID="PostalCodeRfv"
runat="server" ControlToValidate="PostalCodeTextBox"
ErrorMessage="*" ToolTip="Postal code is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<th align="right">
Country:</th>
<td>
</td>
<td>
<asp:TextBox ID="CountryTextBox"
runat="server" Text='<%# Bind("Country") %>' />
<asp:RequiredFieldValidator
ID="CountryRfv" runat="server"
ControlToValidate="CountryTextBox"
ErrorMessage="*" ToolTip="Country is required"
ValidationGroup="UpdateCustomerVG" />
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
<asp:LinkButton ID="UpdateLinkButton"
CommandName="update"
ValidationGroup="UpdateCustomerVG"
Text="Update" runat="server" />
<asp:LinkButton ID="CancelLinkButton"
CommandName="cancel"
Text="Cancel" runat="server" />
</td>
</tr>
</table>
</asp:Panel>
</td>
</tr>
<tr>
<td colspan="2" style="font-size: 10px">
</td>
</tr>
</table>
</EditItemTemplate>
<ItemTemplate>
<table>
<tr>
<td colspan="2" style="font-size: 10px">
</td>
</tr>
<tr>
<td style="width: 5px;
background-color: #4682B4">
<asp:Panel ID="SidePanel"
Width="5px" runat="server" />
</td>
<td>
<asp:Panel ID="CustomerPanel"
runat="server" CssClass="CustomerPanel">
<table>
<tr>
<td style="width: 50px">
</td>
<td style="width: 5px">
</td>
<td style="width: 235px">
</td>
</tr>
<tr>
<td colspan="3">
<asp:Label ID="CompanyLabel"
Text='<%# Eval("CompanyName") %>'
runat="server" BackColor="DarkGray"
ForeColor="White" Width="290px"
Font-Bold="true" Style="vertical-align: middle;
padding: 2px 4px 4px 2px" />
</td>
</tr>
<tr>
<th align="right">
Contact:</th>
<td>
</td>
<td>
<asp:Label ID="ContactLabel"
Text='<%# Eval("ContactName") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Title:</th>
<td>
</td>
<td>
<asp:Label ID="ContactTitleLabel"
Text='<%# Eval("ContactTitle") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Phone:</th>
<td>
</td>
<td>
<asp:Label ID="PhoneLabel"
Text='<%# Eval("Phone") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Fax:</th>
<td>
</td>
<td>
<asp:Label ID="FaxLabel"
Text='<%# Eval("Fax") %>'
runat="server" />
</td>
</tr>
<tr>
<td colspan="3">
<asp:CheckBox ID="FavouriteCustomerCheckBox"
runat="server" Text="Favourite"
TextAlign="Right" />
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
<asp:LinkButton ID="DetailLinkButton"
CommandName="select"
Text="Detail" runat="server" />
<asp:LinkButton ID="EditLinkButton"
CommandName="Edit"
Text="Edit" runat="server" />
<asp:LinkButton ID="OrderLinkButton"
OnClientClick='<%# GetClientClick(Eval("CustomerID")) %>'
Text="Show Orders"
runat="server" />
</td>
</tr>
</table>
</asp:Panel>
</td>
</tr>
<tr>
<td colspan="2" style="font-size: 10px">
</td>
</tr>
</table>
</ItemTemplate>
<SelectedItemTemplate>
<table>
<tr>
<td colspan="2" style="font-size: 10px">
</td>
</tr>
<tr>
<td style="width: 5px;
background-color: #4682B4">
<asp:Panel ID="SidePanel"
Width="5px" runat="server" />
</td>
<td>
<asp:Panel ID="CustomerPanel"
runat="server" CssClass="CustomerPanel">
<table>
<tr>
<td style="width: 50px">
</td>
<td style="width: 5px">
</td>
<td style="width: 235px">
</td>
</tr>
<tr>
<td colspan="3">
<asp:Label ID="CompanyLabel"
Text='<%# Eval("CompanyName") %>'
runat="server" BackColor="DarkGray"
ForeColor="White" Width="290px"
Font-Bold="true" Style="vertical-align: middle;
padding: 2px 4px 4px 2px" />
</td>
</tr>
<tr>
<th align="right">
Contact:</th>
<td>
</td>
<td>
<asp:Label ID="ContactLabel"
Text='<%# Eval("ContactName") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Title:</th>
<td>
</td>
<td>
<asp:Label ID="ContactTitleLabel"
Text='<%# Eval("ContactTitle") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Phone:</th>
<td>
</td>
<td>
<asp:Label ID="PhoneLabel"
Text='<%# Eval("Phone") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Fax:</th>
<td>
</td>
<td>
<asp:Label ID="FaxLabel"
Text='<%# Eval("Fax") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Address:</th>
<td>
</td>
<td>
<asp:Label ID="AddressLabel"
Text='<%# Eval("Address") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
City:</th>
<td>
</td>
<td>
<asp:Label ID="CityLabel"
Text='<%# Eval("City") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Region:</th>
<td>
</td>
<td>
<asp:Label ID="RegionLabel"
Text='<%# Eval("Region") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Postal Code:</th>
<td>
</td>
<td>
<asp:Label ID="PostalCodeLabel"
Text='<%# Eval("PostalCode") %>'
runat="server" />
</td>
</tr>
<tr>
<th align="right">
Country:</th>
<td>
</td>
<td>
<asp:Label ID="CountryLabel"
Text='<%# Eval("Country") %>'
runat="server" />
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
<asp:LinkButton ID="SummaryLinkButton"
CommandName="summary"
Text="Summary" runat="server" />
<asp:LinkButton ID="EditLinkButton"
CommandName="Edit"
Text="Edit" runat="server" />
</td>
</tr>
</table>
</asp:Panel>
</td>
</tr>
<tr>
<td colspan="2" style="font-size: 10px">
</td>
</tr>
</table>
</SelectedItemTemplate>
</asp:DataList>
The following code snippet illustrates the SqlDataSource setup.
<asp:SqlDataSource ID="CustomerSqlDataSource"
runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT * FROM [Customers] WHERE [CompanyName] LIKE '%' + @CompanyName + '%' OR @CompanyName = '-1'"
UpdateCommand="UPDATE [Customers] SET [CompanyName] = @CompanyName, [ContactName] = @ContactName, [ContactTitle] = @ContactTitle, [Address] = @Address, [City] = @City, [Region] = @Region, [PostalCode] = @PostalCode, [Country] = @Country, [Phone] = @Phone, [Fax] = @Fax WHERE [CustomerID] = @CustomerID"
DeleteCommand="DELETE FROM [Customers] WHERE [CustomerID] = @CustomerID"
InsertCommand="INSERT INTO [Customers] ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax]) VALUES (@CustomerID, @CompanyName, @ContactName, @ContactTitle, @Address, @City, @Region, @PostalCode, @Country, @Phone, @Fax)">
<UpdateParameters>
<asp:Parameter Name="CompanyName"
Type="String" />
<asp:Parameter Name="ContactName"
Type="String" />
<asp:Parameter Name="ContactTitle"
Type="String" />
<asp:Parameter Name="Address"
Type="String" />
<asp:Parameter Name="City"
Type="String" />
<asp:Parameter Name="Region"
Type="String" />
<asp:Parameter Name="PostalCode"
Type="String" />
<asp:Parameter Name="Country"
Type="String" />
<asp:Parameter Name="Phone"
Type="String" />
<asp:Parameter Name="Fax"
Type="String" />
<asp:Parameter Name="CustomerID"
Type="String" />
</UpdateParameters>
<