1.8. Adding First/Last Navigation to a DataGrid

Problem

You need to display data from a database in a table, but the database has more rows than will fit on a single page, and you want to use first/last buttons along with next/previous buttons for navigation.

Solution

Use a DataGrid control, add first/last and next/previous buttons (with event handlers for each one), and then bind the data to it.

In the .aspx file:

  1. Add a DataGrid control to the .aspx file.

  2. Add a row below the DataGrid with first/last and next/previous buttons for navigation.

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

  1. Create a routine that binds a dataset to the DataGrid in the usual fashion.

  2. For each of the four buttons, create an event handler to handle the button’s click event, perform the requisite page navigation, and rebind the data.

Figure 1-8 shows the appearance of a typical DataGrid within a browser with first/last and next/previous buttons for navigation. Example 1-20 through Example 1-22 show the .aspx and code-behind files for an application that produces this result.

DataGrid with first/last and next/previous navigation output

Figure 1-8. DataGrid with first/last and next/previous navigation output

Discussion

The main theme of this recipe is to provide an alternative to the DataGrid control’s default pagination controls and, at the same time, handle the custom paging. Setting the PagerStyle-Visible attribute to False makes the pager invisible in a DataGrid control, allowing you to implement your own user interface for the pagination controls. (The pager is the element on the DataGrid control that allows you to link to other pages when paging is enabled.) When the pager is invisible, some appearance-related attributes for the pager are not required and can therefore be eliminated, specifically PagerStyle-Position, PagerStyle-HorizontalAlign, PagerStyle-NextPageText, and PagerStyle-PrevPageText. Adding a row below the DataGrid to hold the four navigation buttons (Next, Prev, First, and Last) is also a key ingredient.

In the application we have developed for this recipe, we added four event handler routines to the code-behind to handle the click events for the four buttons, a strategy you might find handy for your application as well. The event handlers simply alter the current page index for the grid (CurrentPageIndex), as appropriate, and rebind the data.

Tip

To improve performance, the event handlers check to see if the page really needs changing and rebinding prior to changing the current page index value. For example, the btnPrev_ServerClick handler checks to see if CurrentPageIndex is greater than zero before subtracting one from it.

To improve performance still further, you could add the following code to the end of the bindData method to disable the appropriate buttons when no action would be taken on the server call—for example, disabling the First and Prev buttons when the first page is displayed. This would avoid an unnecessary trip to the server.

Dim pageIndex as Integer = dgBooks.CurrentPageIndex
If (pageIndex = 0) Then
  btnFirst.Disabled = True
Else
  btnFirst.Disabled = False
End If

If (pageIndex = dgBooks.PageCount - 1) then
  btnLast.Disabled = True
Else
  btnLast.Disabled = False
End If

See Also

The sidebar Event Handlers in Recipe 1.7

Example 1-20. DataGrid with first/last navigation (.aspx)

<%@ Page Language="vb" AutoEventWireup="false" 
         Codebehind="CH01DatagridWithFirstLastNavVB.aspx.vb" 
         Inherits="ASPNetCookbook.VBExamples.CH01DatagridWithFirstLastNavVB" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>Datagrid With First/Last Navigation</title>
    <link rel="stylesheet" href="css/ASPNetCookbook.css">
  </head>
  <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">
    <form id="frmDatagrid" 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">
            DataGrid With First/Last and Next/Previous Navigation (VB)
          </td>
        </tr>
        <tr>
          <td><img src="images/spacer.gif" height="10" border="0"></td>
        </tr>
        <tr>
          <td align="center">
            <asp:DataGrid 
                                id="dgBooks" 
                                runat="server" 
                                BorderColor="000080" 
                                BorderWidth="2px"
                                AutoGenerateColumns="False"
                                width="100%"
                                AllowPaging="True"
                                PageSize="5"
                                PagerStyle-Visible="False">

                                <HeaderStyle 
                                  HorizontalAlign="Center" 
                                  ForeColor="#FFFFFF" 
                                  BackColor="#000080" 
                                  Font-Bold=true
                                  CssClass="TableHeader" /> 

                                <ItemStyle
                                  BackColor="#FFFFE0" 
                                  cssClass="TableCellNormal" />

                                <AlternatingItemStyle 
                                  BackColor="#FFFFFF" 
                                  cssClass="TableCellAlternating" />
                                

                                <Columns>
                                  <asp:BoundColumn HeaderText="Title" DataField="Title" />
                                  <asp:BoundColumn HeaderText="ISBN" DataField="ISBN" 
                                                   ItemStyle-HorizontalAlign="Center" />
                                  <asp:BoundColumn HeaderText="Publisher" DataField="Publisher" 
                                                   ItemStyle-HorizontalAlign="Center" />
                                </Columns>
                              </asp:DataGrid>
          </td>
        </tr>
        <tr>
          <td align="center">
            <table width="40%" border="0">
              <tr>
                <td align="center">
                  <input id="btnFirst" runat="server" type="image"
                                           src="images/buttons/button_first.gif">
                </td>
                <td align="center">
                  <input id="btnPrev" runat="server" type="image"
                                           src="images/buttons/button_prev.gif">
                </td>
                <td align="center">
                  <input id="btnNext" runat="server" type="image"
                                           src="images/buttons/button_next.gif">
                </td>
                <td align="center">
                  <input id="btnLast" runat="server" type="image"
                                           src="images/buttons/button_last.gif">
                </td>
              </tr>
            </table>
          </td>
        </tr>
      </table>
    </form>
  </body>
</html>

Example 1-21. DataGrid with first/last navigation code-behind (.vb)

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

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

    'controls on form
    Protected WithEvents dgBooks As System.Web.UI.WebControls.DataGrid
                      Protected WithEvents btnFirst As System.Web.UI.HtmlControls.HtmlInputImage
                      Protected WithEvents btnPrev As System.Web.UI.HtmlControls.HtmlInputImage
                      Protected WithEvents btnNext As System.Web.UI.HtmlControls.HtmlInputImage
                      Protected WithEvents btnLast As System.Web.UI.HtmlControls.HtmlInputImage

    '************************************************************************
    '
    '   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

      If (Not Page.IsPostBack) Then
        bindData( )

      End If
    End Sub  'Page_Load

    '*************************************************************************
    '
    '   ROUTINE: btnFirst_ServerClick
    '
    '   DESCRIPTION: This routine provides the event handler for the first
    '                button click event.  It is responsible for setting the 
    '                page index to the first page and rebinding the data.
    '-------------------------------------------------------------------------
    Private Sub btnFirst_ServerClick(ByVal sender As Object, _
                                  ByVal e As System.Web.UI.ImageClickEventArgs) _
                                  Handles btnFirst.ServerClick

                        'set new page index and rebind the data
                        If (dgBooks.CurrentPageIndex > 0) Then
                          dgBooks.CurrentPageIndex = 0
                          bindData( )
                        End If
                      End Sub  'btnFirst_ServerClick

    '*************************************************************************
    '
    '   ROUTINE: btnPrev_ServerClick
    '
    '   DESCRIPTION: This routine provides the event handler for the previous
    '                button click event.  It is responsible for setting the 
    '                page index to the previous page and rebinding the data.
    '-------------------------------------------------------------------------
    Private Sub btnPrev_ServerClick(ByVal sender As Object, _
                                  ByVal e As System.Web.UI.ImageClickEventArgs) _
                                  Handles btnPrev.ServerClick

                        'set new page index and rebind the data
                        If (dgBooks.CurrentPageIndex > 0) Then
                          dgBooks.CurrentPageIndex -= 1
                          bindData( )
                        End If
                      End Sub  'btnPrev_ServerClick

    '*************************************************************************
    '
    '   ROUTINE: btnNext_ServerClick
    '
    '   DESCRIPTION: This routine provides the event handler for the next
    '                button click event.  It is responsible for setting the 
    '                page index to the next page and rebinding the data.
    '-------------------------------------------------------------------------
    Private Sub btnNext_ServerClick(ByVal sender As Object, _
                                  ByVal e As System.Web.UI.ImageClickEventArgs) _
                                  Handles btnNext.ServerClick

                        'set new page index and rebind the data
                        If (dgBooks.CurrentPageIndex < dgBooks.PageCount - 1) Then
                          dgBooks.CurrentPageIndex += 1
                          bindData( )
                        End If
                      End Sub  'btnNext_ServerClick

    '*************************************************************************
    '
    '   ROUTINE: btnLast_ServerClick
    '
    '   DESCRIPTION: This routine provides the event handler for the last
    '                button click event.  It is responsible for setting the 
    '                page index to the last page and rebinding the data.
    '-------------------------------------------------------------------------
    Private Sub btnLast_ServerClick(ByVal sender As Object, _
                              ByVal e As System.Web.UI.ImageClickEventArgs) _
                              Handles btnLast.ServerClick

                        'set new page index and rebind the data
                        If (dgBooks.CurrentPageIndex < dgBooks.PageCount - 1) Then
                          dgBooks.CurrentPageIndex = dgBooks.PageCount - 1
                          bindData( )
                        End If
                      End Sub  'btnLast_ServerClick

    '*************************************************************************
    '
    '   ROUTINE: bindData
    '
    '   DESCRIPTION: This routine queries the database for the data to 
    '                displayed and binds it to the datagrid
    '-------------------------------------------------------------------------
    Private Sub bindData( )
      Dim dbConn As OleDbConnection
      Dim da As OleDbDataAdapter
      Dim dSet As DataSet
      Dim strConnection As String
      Dim strSQL As String

      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"
        da = New OleDbDataAdapter(strSQL, dbConn)
        dSet = New DataSet
        da.Fill(dSet)

        'set the source of the data for the datagrid control and bind it
        dgBooks.DataSource = dSet
        dgBooks.DataBind( )

      Finally
        'cleanup
        If (Not IsNothing(dbConn)) Then
          dbConn.Close( )
        End If
      End Try
    End Sub  'bindData
  End Class  'CH01DatagridWithFirstLastNavVB
End Namespace

Example 1-22. DataGrid with first/last navigation code-behind (.cs)

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

namespace ASPNetCookbook.CSExamples
{
  public class CH01DatagridWithFirstLastNavCS : System.Web.UI.Page
  {
    protected System.Web.UI.HtmlControls.HtmlInputImage btnFirst;
                      protected System.Web.UI.HtmlControls.HtmlInputImage btnPrev;
                      protected System.Web.UI.HtmlControls.HtmlInputImage btnNext;
                      protected System.Web.UI.HtmlControls.HtmlInputImage btnLast;
                      protected System.Web.UI.WebControls.DataGrid dgBooks;

    //************************************************************************
    //
    //   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)
    {
      // wire in the button click events
                        this.btnFirst.ServerClick +=
                          new System.Web.UI.ImageClickEventHandler(this.btnFirst_ServerClick);
                        this.btnPrev.ServerClick +=
                          new System.Web.UI.ImageClickEventHandler(this.btnPrev_ServerClick);
                        this.btnNext.ServerClick +=
                          new System.Web.UI.ImageClickEventHandler(this.btnNext_ServerClick);
                        this.btnLast.ServerClick +=
                          new System.Web.UI.ImageClickEventHandler(this.btnLast_ServerClick);

      if (!Page.IsPostBack)
      {
        bindData( );

      }
    }  // Page_Load

    //************************************************************************
    //
    //   ROUTINE: btnFirst_ServerClick
    //
    //   DESCRIPTION: This routine provides the event handler for the first
    //                button click event.  It is responsible for setting the
    //                page index to the first page and rebinding the data.
    //------------------------------------------------------------------------
    private void btnFirst_ServerClick(Object sender,
                                                        System.Web.UI.ImageClickEventArgs e)
                      {
                        // set new page index and rebind the data
                        if (dgBooks.CurrentPageIndex > 0)
                        {
                          dgBooks.CurrentPageIndex = 0;
                          bindData( );
                        }
                      }  //btnFirst_ServerClick

    //************************************************************************
    //
    //   ROUTINE: btnPrev_ServerClick
    //
    //   DESCRIPTION: This routine provides the event handler for the previous
    //                button click event.  It is responsible for setting the
    //                page index to the previous page and rebinding the data.
    //------------------------------------------------------------------------
    private void btnPrev_ServerClick(Object sender,
                                                       System.Web.UI.ImageClickEventArgs e)
                      {
                        // set new page index and rebind the data
                        if (dgBooks.CurrentPageIndex > 0)
                        {
                          dgBooks.CurrentPageIndex -= 1;
                          bindData( );
                        }
                      }  //btnPrev_ServerClick

    //************************************************************************
    //
    //   ROUTINE: btnNext_ServerClick
    //
    //   DESCRIPTION: This routine provides the event handler for the next
    //                button click event.  It is responsible for setting the
    //                page index to the next page and rebinding the data.
    //------------------------------------------------------------------------
    private void btnNext_ServerClick(Object sender,
                                                       System.Web.UI.ImageClickEventArgs e)
                      {
                        // set new page index and rebind the data
                        if (dgBooks.CurrentPageIndex < dgBooks.PageCount - 1)
                        {
                          dgBooks.CurrentPageIndex += 1;
                          bindData( );
                        }
                      }  //btnNext_ServerClick

    //************************************************************************
    //
    //   ROUTINE: btnLast_ServerClick
    //
    //   DESCRIPTION: This routine provides the event handler for the last
    //                button click event.  It is responsible for setting the
    //                page index to the last page and rebinding the data.
    //------------------------------------------------------------------------
    private void btnLast_ServerClick(Object sender,
                                                       System.Web.UI.ImageClickEventArgs e)
                      {
                        // set new page index and rebind the data
                        if (dgBooks.CurrentPageIndex < dgBooks.PageCount - 1)
                        {
                          dgBooks.CurrentPageIndex = dgBooks.PageCount - 1;
                          bindData( );
                        }
                      }  //btnLast_ServerClick

    //************************************************************************
    //
    //   ROUTINE: bindData
    //
    //   DESCRIPTION: This routine queries the database for the data to
    //                displayed and binds it to the repeater
    //------------------------------------------------------------------------
    private void bindData( )
    {
      OleDbConnection dbConn = null;
      OleDbDataAdapter da = null;
      DataSet dSet = null;
      String strConnection = null;
      String strSQL =null;

      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";
        da = new OleDbDataAdapter(strSQL, dbConn);
        dSet = new DataSet( );
        da.Fill(dSet);

        // set the source of the data for the datagrid control and bind it
        dgBooks.DataSource = dSet;
        dgBooks.DataBind( );
      }  // try

      finally
      {
        //clean up
        if (dbConn != null)
        {
          dbConn.Close( );
        }
      }  // finally
    }  // bindData
  }  // CH01DatagridWithFirstLastNavCS
}

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.