1.3. Enhancing the Output of a Tabular Display

Problem

You need to display data from a database in a way that lets you organize and enhance the output beyond the confines of the DataGrid control’s default tabular display. Selecting and editing the data are not important, nor is navigating through the data.

Solution

Use a Repeater control with templates and then bind the data to the control.

In the .aspx file, add a Repeater control and the associated templates for displaying the data.

In the code-behind class for the page, use the .NET language of your choice to:

  1. Open a connection to the database.

  2. Build a query string, and read the desired data from the database using an OleDbCommand and OleDbDataReader.

  3. Assign the data source to the Repeater control and bind it.

Figure 1-2 shows the appearance of a typical Repeater in a browser. Example 1-4 through Example 1-6 show the .aspx and code-behind files for an application that produces this result.

Using templates with Repeater control display output

Figure 1-2. Using templates with Repeater control display output

Discussion

When your primary aim is to organize and enhance the output beyond the confines of the DataGrid control’s default tabular display, the Repeater control is a good choice because, unlike a DataGrid, it has associated templates that allow you to use virtually any HTML to format the displayed data. It also has the advantage of being relatively lightweight and easy to use. When using Repeater, however, there are a handful of nuances you should know about that can make life easier and, in one instance, enhance performance.

Example 1-4 shows one of the most common approaches to using the Repeater control, which is to place the asp:Repeater element in a table and use its HeaderTemplate, ItemTemplate, and AlternatingItemTemplate attributes to format the displayed data as rows in the table.

A HeaderTemplate is used to define the header row of the table. In this example, the header is straight HTML with a single table row and three columns.

An ItemTemplate formats the even-numbered rows of data, while an AlternatingItemTemplate formats the odd-numbered rows. For both templates, a single row in the table is defined with the same three columns defined in the header template. In each of the three columns, data-binding statements (described later) define the data to be placed in each of the columns. The only differences between ItemTemplate and AlternatingItemTemplate are the color schemes and stylesheet classes used to output the rows. If you do not need to output the data using alternating styles, then omit the AlternatingItemTemplate attribute.

The data from the database is bound to the cells in the templates using the DataBinder.Eval method. The Title field is placed in the first column, the ISBN field is placed in the second column, and the Publisher field is placed in the third column:

DataBinder.Eval(Container.DataItem, "Title")
DataBinder.Eval(Container.DataItem, "ISBN")
DataBinder.Eval(Container.DataItem, "Publisher")

Tip

If the header is pure HTML with no data binding required, it is more efficient to remove the HeaderTemplate attribute and place the header HTML before the asp:Repeater tag. By moving the header outside of the asp:Repeater tag, the creation of several server-side controls is eliminated, which reduces the time required to render the page and improves performance.

    <table width="100%" border="2" bordercolor="#000080"
          bgcolor="#FFFFE0"
          style="border-style:solid;
          border-collapse:collapse;">
      <thead bgcolor="#000080" class="TableHeader">
                          <tr>
                            <th align="center">Title</th>
                            <th align="center">ISBN</th>
                            <th align="center">Publisher</th>
                          </tr>
                        </thead>
      <asp:Repeater id=repBooks runat="server">
         ...
      </asp:Repeater>
    </table>

The Page_Load method in the code-behind, shown in Example 1-5 (VB) and Example 1-6 (C#), opens a connection to the database, reads the data from the database using an OleDbCommand and an OleDbDataReader object, binds the data reader to the Repeater control, and then performs the necessary cleanup.

See Also

Recipe 1.6 for another example of using a template with a tabular control

Example 1-4. Templates with Repeater control (.aspx)

<%@ Page Language="vb" AutoEventWireup="false" 
         Codebehind="CH01TemplatesWithRepeaterVB.aspx.vb" 
         Inherits="ASPNetCookbook.VBExamples.CH01TemplatesWithRepeaterVB" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>Templates with Repeater</title>
    <link rel="stylesheet" href="css/ASPNetCookbook.css">
  </head>
  <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">
    <form id="frmData" method="post" runat="server">
      <table width="100%" cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td align="center">
            <img src="images/ASPNETCookbookHeading_blue.gif">
          </td>
        </tr>
        <tr>
          <td class="dividerLine">
            <img src="images/spacer.gif" height="6" border="0"></td>
        </tr>
      </table>
      <table width="90%" align="center" border="0">
        <tr>
          <td><img src="images/spacer.gif" height="10" border="0"></td>
        </tr>
        <tr>
          <td align="center" class="PageHeading">
              Templates With Repeater (VB)</td>
        </tr>
        <tr>
          <td><img src="images/spacer.gif" height="10" border="0"></td>
        </tr>
        <tr>
          <td align="center">
              <!-- Create a table within the cell to provide localized 
                   customization for the book list -->
            <table width="100%" border="2" bordercolor="#000080" 
                   bgcolor="#FFFFE0" 
                   style="border-style:solid;border-collapse:collapse;">
              <asp:Repeater id=repBooks runat="server">
                                  <HeaderTemplate>
                                    <thead bgcolor="#000080" class="TableHeader">
                                      <tr>
                                        <th align="center">Title</th>
                                        <th align="center">ISBN</th>
                                        <th align="center">Publisher</th>
                                      </tr>
                                    </thead>
                                  </HeaderTemplate>
                                  <ItemTemplate>
                                    <tr bordercolor="#000080" class="TableCellNormal">
                                      <td><%# DataBinder.Eval(Container.DataItem, "Title") %>
                                      </td>
                                      <td align="center">
                                        <%# DataBinder.Eval(Container.DataItem, "ISBN") %>
                                      </td>
                                      <td align="center">
                                        <%# DataBinder.Eval(Container.DataItem, "Publisher") %>
                                      </td>
                                    </tr>
                                  </ItemTemplate>
                                  <AlternatingItemTemplate>
                                    <tr bordercolor="#000080" bgcolor="#FFFFFF" 
                                        class="TableCellAlternating">
                                      <td><%# DataBinder.Eval(Container.DataItem, "Title") %>
                                      </td>
                                      <td align="center">
                                        <%# DataBinder.Eval(Container.DataItem, "ISBN") %>
                                      </td>
                                      <td align="center">
                                        <%# DataBinder.Eval(Container.DataItem, "Publisher") %>
                                      </td>
                                    </tr>
                                  </AlternatingItemTemplate>
                                </asp:Repeater>
            </table>
          </td>
        </tr>
      </table>
    </form>
  </body>
</html>

Example 1-5. Templates with Repeater control code-behind (.vb)

Option Explicit On 
Option Strict On
'-----------------------------------------------------------------------------
'
'   Module Name: CH01TemplatesWithRepeaterVB.aspx.vb
'
'   Description: This class provides the code behind for
'                CH01TemplatesWithRepeaterVB.aspx
'
'*****************************************************************************
Imports Microsoft.VisualBasic
Imports System.Configuration
Imports System.Data
Imports System.Data.OleDb

Namespace ASPNetCookbook.VBExamples
  Public Class CH01TemplatesWithRepeaterVB
    Inherits System.Web.UI.Page

    'controls on form
    Protected repBooks As System.Web.UI.WebControls.Repeater

    '*************************************************************************
    '
    '   ROUTINE: Page_Load
    '
    '   DESCRIPTION: This routine provides the event handler for the page load
    '                event.  It is responsible for initializing the controls
    '                on the page.
    '
    '-------------------------------------------------------------------------
    Private Sub Page_Load(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) _
                Handles MyBase.Load
      Dim dbConn As OleDbConnection
      Dim dCmd As OleDbCommand
      Dim dReader As OleDbDataReader
      Dim strConnection As String
      Dim strSQL As String

      If (Not Page.IsPostBack) Then
        Try
          'get the connection string from web.config and open a connection 
                            'to the database
                            strConnection = _
                                ConfigurationSettings.AppSettings("dbConnectionString")
                            dbConn = New OleDbConnection(strConnection)
                            dbConn.Open( )

                            'build the query string and get the data from the database
                            strSQL = "SELECT Title, ISBN, Publisher " & _
                                     "FROM Book " & _
                                     "ORDER BY Title"
                            dCmd = New OleDbCommand(strSQL, dbConn)
                            dReader = dCmd.ExecuteReader( )

                            'set the source of the data for the repeater control and bind it
                            repBooks.DataSource = dReader
                            repBooks.DataBind( )

        Finally
          'cleanup
          If (Not IsNothing(dReader)) Then
            dReader.Close( )
          End If

          If (Not IsNothing(dbConn)) Then
            dbConn.Close( )
          End If
        End Try
      End If
    End Sub  'Page_Load
  End Class  'CH01TemplatesWithRepeaterVB
End Namespace

Example 1-6. Templates with Repeater control code-behind (.cs)

//----------------------------------------------------------------------------
//
//   Module Name: CH01TemplatesWithRepeaterCS.aspx.cs
//
//   Description: This class provides the code behind for
//                CH01TemplatesWithRepeaterCS.aspx
//
//****************************************************************************
using System;
using System.Configuration;
using System.Data;
using System.Data.OleDb;

namespace ASPNetCookbook.CSExamples
{
  public class CH01TemplatesWithRepeaterCS : System.Web.UI.Page
  {
    // controls on form
    protected System.Web.UI.WebControls.Repeater repBooks;
    
    //************************************************************************
    //
    //   ROUTINE: Page_Load
    //
    //   DESCRIPTION: This routine provides the event handler for the page
    //                load event.  It is responsible for initializing the
    //                controls on the page.
    //
    //------------------------------------------------------------------------
    private void Page_Load(object sender, System.EventArgs e)
    {
      OleDbConnection dbConn = null;
      OleDbCommand dCmd = null;
      OleDbDataReader dReader = null;
      String strConnection = null;
      String strSQL = null;

      if (!Page.IsPostBack)
      {
        try
        {
          // get the connection string from web.config and open a connection 
                            // to the database
                            strConnection = 
                                ConfigurationSettings.AppSettings["dbConnectionString"];
                            dbConn = new OleDbConnection(strConnection);
                            dbConn.Open( );

                            // build the query string and get the data from the database
                            strSQL = "SELECT Title, ISBN, Publisher " +
                                     "FROM Book " +
                                     "ORDER BY Title";
                            dCmd = new OleDbCommand(strSQL, dbConn);
                            dReader = dCmd.ExecuteReader( );

                            // set the source of the data for the repeater control and bind it
                            repBooks.DataSource = dReader;
                            repBooks.DataBind( );
        }

        finally
        {
          // cleanup
          if (dReader != null)
          {
            dReader.Close( );
          }

          if (dbConn != null)
          {
            dbConn.Close( );
          }
        }  // finally
      }
    }  // Page_Load
  }  // CH01TemplatesWithRepeaterCS
}

Get ASP.NET Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.