The DataList Control

The DataList Control

If in the previous example you absentmindedly replaced Repeater with Data­List, your code would run perfectly and function in the same way. However, the two controls are not identical. DataList, which is a data bound control, offers you a full bag of new features, mostly in the area of graphical layout—in fact, its set of features begins where the set of features supported by the Repeater control ends. For example, it supports directional rendering in which items can flow horizontally or vertically, depending on the specified number of columns. DataList provides facilities to retrieve a key value associated with a current row in the data source and has built-in support for selection and editing. DataList also supports more templates and can fire more events than Repeater.

Basic data-binding operations that use DataList are similar to those that use Repeater. You use the DataSource property to bind the control to data and the DataBind method to refresh the user interface.

DataList1.DataSource = ds.Tables["EmpTable"];

In template code, you can access data bound information using both the DataBinder object and the Container.DataItem expression.

Templates Specific to DataList

The DataList control supports two templates that we haven’t yet discussed: SelectedItemTemplate and EditItemTemplate. SelectedItemTemplate controls how the selected item is displayed. You should use it only when you need to display other controls or apply a particular logic. When you want to change only the appearance of the selected item, resort to a simpler cascading style sheet (CSS) style set via the SelectedItemStyle property.

EditItemTemplate specifies the graphical template for the row currently being edited. If you don’t specify your own template, the standard template is used, which renders any data bound element by using text boxes. Note that the template defines the layout of the control only when in edit mode. Managing the user interaction, saving the edit, or canceling the edit operation must be handled separately. For each template, you can use special style tags to set all the CSS attributes that you need via a declaration. These style tags are <AlternatingItemStyle>, <ItemStyle>, <HeaderStyle>, <FooterStyle>, <SeparatorStyle>, <SelectedItemStyle>, and <EditItemStyle>. The following code assigns a white background to the items and a thick black border:

<ItemStyle BorderColor="black" BorderWidth=3 BackColor="white" />

You can also use style properties that have the same name as the style tags, as shown in this code:

DataList1.ItemStyle.BackColor = Color.White;
Events Specific to DataList

All iterative controls fire a generic ItemCommand event when a user clicks a link button or a push button, and this button is associated with a command name that is specified by the programmer. You use the command name within the ItemCommand event to recognize which button has actually been clicked. If these links and buttons are automatically generated during the execution of DataBind, it is especially difficult for you to assign a unique value to the OnClick event for each control. The next code example clarifies my point. The DataList control generates buttons based on the content of an array of strings.

<asp:DataList runat="server" id="DataList1" 

    <asp:linkbutton runat="server" CommandName="<%# Container.DataItem %>" 
        Text="<%# Container.DataItem %>" /> &nbsp;&nbsp;&nbsp;


The data source returned by the CreateDataSource function generates the output shown in Figure 1-5.

public ArrayList CreateDataSource()
    ArrayList a = new ArrayList();
    return a;
Figure 1-5
A button bar generated using DataList. The ItemCommand event is the only way you can handle the click event for buttons.

Within the body of the HandleItemCommand function, you can analyze the command name and decide the proper action to take.

void HandleItemCommand(Object sender, DataListCommandEventArgs e) 
    switch (e.CommandName)
        case "Search":
            statusbar.Text = "searching...";
        case "Execute":
            statusbar.Text = "executing...";
        case "Load":
            statusbar.Text = "loading...";

The full source for the CommandButtons.aspx application is available on the companion CD.

Special Command Names

The DataList control provides special support for five predefined command names: edit, update, delete, cancel, and select. Any link or button in a DataList control whose command name matches one of these five keywords receives special treatment from the control. The predefined events that fire when the user clicks buttons associated with these strings are listed in Table 1-5.

Table 1-5 Predefined Events of the DataList Control




Fires when a button named Cancel is clicked.


Fires when a button named Delete is clicked.


Fires when a button named Edit is clicked. When a user clicks the Edit button, the item automatically enters edit mode. Edit mode implies use of the Edit­Item template.


Fires when a button named Update is clicked.


Fires when a button named Select is clicked. Clicking a Select button automatically deselects the current item and selects the new item.

Edit mode and select mode are graphically rendered through their specific templates and CSS style.


Clicking a button named with a predefined keyword generates two events: first the generic ItemCommand event with the CommandName property set to the keyword and then the button-specific event (UpdateCommand).

Relating Graphical and Data Elements

To enable item selection and in-place editing, the DataList control has an internal mechanism that associates graphical items with corresponding elements in the data source. To retrieve this association, you set the DataKeyField property to the name of one data source field. The selected field must have content that allows you to uniquely identify the data item (a primary key). For example, if your data source is a table with information about a company’s employees, you could assign the employeeid field to DataKeyField, as shown here:

<asp:DataList runat="server" DataKeyField="employeeid">

After DataKeyField is set, the control ensures that the DataKeys collection contains all the field’s values for each item the control is currently displaying. You retrieve the key value based on the ordinal position of the item. For example, to obtain the key value of the currently selected item, you would do this:

int nEmployeeID = DataKeys[DataList1.SelectedIndex];

The following code example illustrates how to take advantage of the DataList control to create a “smart” list box, and Figure 1-6 shows the results. (The full source code for the SmartList.aspx application is available on the companion CD.) All items in the data source are rendered as a link button with the command name select. As you know, the DataList control provides special support for select. When the user clicks any of the selectable links, ASP.NET fires a SelectedIndexChanged event and updates the style of the clicked item according to the attributes set through the SelectedItemStyle tag. The appearance of the button is refreshed to reflect the new state. In response to the selection event, additional information about the employee is retrieved and displayed. A new button appears at the bottom of the page to let the user deselect any selected item.

When the page first loads, it retrieves only the fields needed to prepare the list of employees—that is, employeeid, firstname, and lastname. When the user clicks a link button, the DataList control is re-bound and an informative label appears with a message.

public void OnSearch(Object sender, EventArgs e)
    DataSet ds = new DataSet();

    String sConn = "server=localhost;uid=sa;Initial Catalog=Northwind;";
    String sText = "SELECT employeeid, firstname, lastname FROM Employees";
    sText += " WHERE employeeid >=" + tbEmpID.Text;
    SqlDataAdapter cmd = new SqlDataAdapter(sText, sConn);
    cmd.Fill(ds, "EmpTable");

    DataList1.DataSource = ds.Tables["EmpTable"].DefaultView;

    theLabel.Visible = true;
    theLabel.Text = "Click to read more.";

The DataList control has the following structure:

<asp:DataList runat="server" id="DataList1" 

<SelectedItemStyle BackColor="lightblue" />

    <h3>Northwind's Employees</h3>

    <asp:linkbutton runat="server" commandname="select"
        Text='<%# ((DataRowView)Container.DataItem)["employeeid"] + " - " + 
             ((DataRowView)Container.DataItem)["lastname"]  + ", " +
             ((DataRowView)Container.DataItem)["firstname"] %> ' />

<FooterTemplate> <hr> </FooterTemplate>

To retrieve additional information about the clicked item, you need to issue another query based on a key value. You retrieve the key value associated with the selected item by using the DataKeys array.

void HandleSelection(Object sender, EventArgs e)
    int nEmpID = (int) DataList1.DataKeys[DataList1.SelectedIndex];

    String sConn = "server=localhost;uid=sa;Initial Catalog=Northwind;";
    SqlConnection cn = new SqlConnection(sConn);

    String sText = "SELECT title, hiredate, country, notes FROM Employees";
    sText += " WHERE employeeid = " + nEmpID.ToString();
    SqlCommand cmd = new SqlCommand(sText, cn);

    SqlDataReader dr = cmd.ExecuteReader();

    theLabel.Text =  "<b>" + dr["title"] + "</b><br>"; 
    DateTime dtime = Convert.ToDateTime(dr["hiredate"]);
    theLabel.Text += "Hired on " + dtime.ToShortDateString() + " from " + 
                     dr["country"] + "<hr>"; 
    theLabel.Text += "<i>" + dr["Notes"] + "</i>"; 

    btnUnselect.Visible = true;

Using the SqlDataReader control instead of the DataSet control to retrieve data is more efficient when you have just one row to fetch. After the data has been successfully read, it gets properly formatted and the Unselect button is displayed.

Figure 1-6
The user interface of the application changes significantly when an employee name is selected. Additional information about the employee is retrieved and displayed, and a new button appears to let you deselect the currently selected item.

To enable the user to deselect an item, set the SelectedIndex property to -1.

void RemoveSelection(Object sender, EventArgs e)
    DataList1.SelectedIndex = -1;
    theLabel.Text = "Click to read more.";
    btnUnselect.Visible = false;

The DataList control and the panel that displays additional employee information are two cells of the same all-encompassing table. By using different settings for the layout properties of DataList, you can obtain a significantly altered design for the links without affecting the core of the code.

As the preceding code example illustrates, the DataList control is much more powerful than the Repeater control, but it is far from being perfect. It still lacks pagination, sorting, and powerful column-based rendering capabilities.