1.9. Adding Direct Page Navigation to a DataGrid

Problem

You need to display data in a table, but the database that stores it has more rows than can fit on a single page, and you want to allow the user to select the page to display.

Solution

The simplest solution is to use a DataGrid control and its PagerStyle-Mode and PagerStyle-PageButton attributes to enable page selection. This approach produces output like that shown in Figure 1-9. To create an application that employs this approach, start by implementing Recipe 1.7 with the changes to the DataGrid tag shown here:

  PagerStyle-Mode="NumericPages"
  PagerStyle-PageButtonCount="5"
Output of simple solution to DataGrid direct paging

Figure 1-9. Output of simple solution to DataGrid direct paging

A more flexible solution is to hide the pager provided by the DataGrid control and implement your own user interface for the pagination controls. This approach allows the user to, for example, input a page number in a text box and then click a button to display the data, as shown in Figure 1-10. Example 1-23 through Example 1-25 show the .aspx and code-behind files for an application that produces this result.

Custom direct page navigation with a DataGrid output

Figure 1-10. Custom direct page navigation with a DataGrid output

Discussion

In the simple solution, setting the PagerStyle-Mode attribute to NumericPages causes the DataGrid to be rendered with page number buttons for navigating through the grid. The PagerStyle-ButtonCount attribute defines the number of “page buttons” that are output. If more pages are available than can be displayed, an ellipsis (...) is displayed at the end(s) of the page buttons containing additional pages. As shown in Figure 1-9, additional pages of data are available beyond page 5. Clicking on the ellipsis will update the data in the DataGrid and display the next block of available pages for navigation. In our example, clicking on the ellipsis will cause page 6 to be displayed in the DataGrid and pages 6-10 will be available for direct navigation.

The more flexible solution enables paging in the grid but, with the code shown next, hides the pager provided by the DataGrid. Enabling pagination is required in order to have the DataGrid provide the infrastructure needed to perform the paging. Hiding the pager provides you with the ability to implement your own user interface for the pagination controls.

AllowPaging="True"
PageSize="5"
PagerStyle-Visible="False">

The pagination controls provided in our example consist of a label to display the current page information, a text box to allow the user to enter the desired page number, and a button to initiate the page change. These controls are placed below the DataGrid in a row of the table containing the grid.

Like many of the previous examples in this chapter, the code-behind’s bindData method queries the database to fill a DataSet. Additionally, with the following code, it updates the label used to display the “page x of y” information and to prompt the user to enter a page number.

               Discussion
lblPager.Text = "Displaying Page " & _
                CStr(dgBooks.CurrentPageIndex + 1) & " of " & _
                CStr(dgBooks.PageCount) & _
                ", Enter Desired Page Number:"

Discussion
lblPager.Text = "Displaying Page " +
                Convert.ToString(dgBooks.CurrentPageIndex + 1) + 
                " of " + Convert.ToString(dgBooks.PageCount) +
                ", Enter Desired Page Number:";

The btnDisplayPage_Click method in the code-behind provides the server-side event handler for the button click event. This method retrieves from the text box the page number entered by the user and decrements it by 1, sets the CurrentPageIndex for the DataGrid, and rebinds the data. The page number must be decremented by 1 because the DataGrid pages are zero-based.

The pagination controls we provide here are relatively simple. But, as you can imagine, virtually any user interface can be constructed using HTML and tied into the DataGrid pagination functionality.

Tip

Production code should include validation of the page number entered by the user. This can be implemented using a RangeValidator control as described in Recipe 2.2.

See Also

Recipe 1.7 and Recipe 1.8 for implementing first/last and next/previous page navigation

Example 1-23. Custom direct page navigation with a DataGrid (.aspx)

<%@ Page Language="vb" AutoEventWireup="false" 
         Codebehind="CH01DatagridWithDirectPageNavVB2.aspx.vb" 
         Inherits="ASPNetCookbook.VBExamples.CH01DatagridWithDirectPageNavVB2" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>DataGrid With Direct Page Navigation 2</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">
            DataGrid Using Custom Direct Page 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="70%" border="0">
              <tr>
                <td><asp:Label id="lblPager" runat="server" 
                                                 CssClass="PagerText" /></td>
                                  <td><asp:TextBox id="txtNewPageNumber" runat="server" 
                                                   Width="40" /></td>
                                  <td><asp:Button id="btnDisplayPage" runat="server" 
                                                  Text="Update" /></td>
              </tr>
            </table>
          </td>
        </tr>
      </table>
    </form>
  </body>
</html>

Example 1-24. Custom direct page navigation with a DataGrid code-behind (.vb)

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

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

    'controls on form
    Protected WithEvents dgBooks As System.Web.UI.WebControls.DataGrid
    Protected lblPager As System.Web.UI.WebControls.Label
    Protected txtNewPageNumber As System.Web.UI.WebControls.TextBox
    Protected WithEvents btnDisplayPage As System.Web.UI.WebControls.Button

    '*************************************************************************
    '
    '   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: btnDisplayPage_Click
    '
    '   DESCRIPTION: This routine provides the event handler for the display
    '                page button click event of the datagrid.  It is 
    '                responsible for setting the page index to the entered 
    '                page and rebinding the data.
    '-------------------------------------------------------------------------
    Private Sub btnDisplayPage_Click(ByVal sender As Object, _
                                                       ByVal e As System.EventArgs) _
                              Handles btnDisplayPage.Click

                        'set new page index and rebind the data
                        'NOTE: The page numbers used by the datagrid control are 0 based
                        '      so adjust the user enter page number to be 0 based
                        dgBooks.CurrentPageIndex = CInt(txtNewPageNumber.Text) - 1
                        bindData( )
                      End Sub  'btnDisplayPage_Click

    '*************************************************************************
    '
    '   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 OleDb.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( )

        'update label on custom pager to show current page and total pages
        lblPager.Text = "Displaying Page " & _
                                          CStr(dgBooks.CurrentPageIndex + 1) & " of " & _
                                          CStr(dgBooks.PageCount) & _
                                          ", Enter Desired Page Number:"

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

  End Class  'CH01DatagridWithDirectPageNavVB2
End Namespace

Example 1-25. Custom direct page navigation with a DataGrid code-behind (.cs)

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

namespace ASPNetCookbook.CSExamples
{
  public class CH01DatagridWithDirectPageNavCS2 : System.Web.UI.Page
  {
    // controls on form
    protected System.Web.UI.WebControls.DataGrid dgBooks;
    protected System.Web.UI.WebControls.Label lblPager;
    protected System.Web.UI.WebControls.TextBox txtNewPageNumber;
    protected System.Web.UI.WebControls.Button btnDisplayPage;

    //************************************************************************
    //
    //   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 display page click event
      this.btnDisplayPage.Click += 
        new System.EventHandler(this.btnDisplayPage_Click);

      if (!Page.IsPostBack)
      {
        bindData( );
      }
    }  // Page_Load

    //************************************************************************
    //
    //   ROUTINE: btnDisplayPage_Click
    //
    //   DESCRIPTION: This routine provides the event handler for the display
    //                page button click event of the datagrid.  It is
    //                responsible for setting the page index to the entered
    //                page and rebinding the data.
    //------------------------------------------------------------------------
    private void btnDisplayPage_Click(Object sender,
                        System.EventArgs e)
                      {
                        //set new page index and rebind the data
                        //NOTE: The page numbers used by the datagrid control are 0 based
                        //      so adjust the user enter page number to be 0 based
                        dgBooks.CurrentPageIndex = Convert.ToInt32(txtNewPageNumber.Text) - 1;
                        bindData( );
                      }  //btnDisplayPage_Click

    //************************************************************************
    //
    //   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, "Table");

        // set the source of the data for the datagrid control and bind it
        dgBooks.DataSource = dSet;
        dgBooks.DataBind( );
  
        //update label on custom pager to show current page and total pages
        lblPager.Text = "Displaying Page " +
                                          Convert.ToString(dgBooks.CurrentPageIndex + 1) +
                                          " of " + Convert.ToString(dgBooks.PageCount) +
                                          ", Enter Desired Page Number:";
      }  // try

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

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.