Recipe 1.8 Adding First/Last Navigation to a DataGrid 1.8.1 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. 1.8.2 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: -
Add a DataGrid control to the .aspx file. -
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: -
Create a routine that binds a dataset to the DataGrid in the usual fashion. -
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. Figure 1-8. DataGrid with first/last and next/previous navigation output 1.8.3 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. | 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 | | 1.8.4 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 } |