Creating a Custom DataGrid Paging Control

As a web developer, you may have come across situations in which you wish you were not stuck with the default paging system provided with the ASP.NET DataGrid. But, at the same time, not having to write a custom DataGrid control or relying on a third-party DataGrid control would have made life much easier.

The simplest way to overcome this would be, quite simply, to have your own paging control, which you can use in conjunction with the existing DataGrid. In this article, I will show you how to write a custom paging control, such as (but definitely not limited to) the one shown here:

In the image shown above, note that the blue 'footer' bar and the paging navigation controls below it are what constitute the paging control. The rest of it is simply the ASP.NET DataGrid.

And now, you start. You will be:

  1. Creating the paging control
  2. Creating a simple webform to use the control
  3. Creating a stored procedure that allows paging

1. Creating the Paging Control

Because you want to make this as customizable as possible, you will create a web user control. In Visual Studio, add a new web user control to your project and name it PagingControl.ascx.

On this page, create a table with two rows. In the first row, place a centered label that will display the current page number; in the second row, place three labels, a textbox, and a button for the purpose of paging navigation. You are not limited, of course, to the textbox;you even can have a dropdown there, but for the sake of simplicity, just use a textbox.

<table cellSpacing="0" cellPadding="0" width="100%" border="0">
   <tr>
      <td align="center" id="tdFooterDisplay" runat="server"
          height="5">
         <asp:Label ID="lblCurrentPageNumber"
                    Runat="server"></asp:Label>
      </td>
   </tr>
   <tr>
      <td align="right">
      <asp:label id="lblPage" Runat="server"></asp:label>
      & <asp:textbox id="txtPageNumber" Runat="server"
                     Width="20"></asp:textbox>
      & <asp:label id="lblOf" Runat="server"></asp:label>
      & <asp:label id="lblTotalPages" Runat="server"></asp:label>
      <asp:button id="btnGo" Runat="server"></asp:button>
      <!-- We need to ensure that only numbers are entered -->
      <asp:RegularExpressionValidator
         Text="*"
         ControlToValidate="txtPageNumber"
         id="rePageNumber"
         runat="server"
         ValidationExpression="\d+"></asp:RegularExpressionValidator>
      <!-- We need to ensure that the textbox is not left blank -->
      <asp:RequiredFieldValidator 
         Text="*"
         ControlToValidate="txtPageNumber"
         ID="rqPageNumber"
         Runat="server"></asp:RequiredFieldValidator>
      </td>

   </tr>
</table>

You now create the code to make this control work. Of importance will be the event you must raise so that it can be handled on the web page that will use this control. Start by declaring a delegate and an event for it.

Public Delegate Sub PageChangedEventHandler(ByVal sender As Object, _
   ByVal e As DataNavigatorEventArgs)

Public Event PageChanged As PageChangedEventHandler

Create a sub that will do the actual raising of the event.

Protected Sub OnPageChanged(ByVal args As DataNavigatorEventArgs)

   RaiseEvent PageChanged(Me, args)

End Sub

Notice that this sub expects an object of type DataNavigatorEventArgs. This object will contain information pertinent to navigation, so you will come to this later. Because the 'Go' button in your control is what will raisw the event, you write that as well.

Private Sub btnGo_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles btnGo.Click

   Dim args As New DataNavigatorEventArgs
   args.CurrentPage = Integer.Parse(Me.txtPageNumber.Text)
   args.TotalPages  = Integer.Parse(Me.lblTotalPages.Text)
   OnPageChanged(args)
   Me.lblCurrentPageNumber.Text = args.CurrentPage.ToString()
End Sub

The purpose of DataNavigatorEventArgs should be clearer by now, and so should its structure. Add a class to your solution, called DataNavigatorEventArgs, and place this code there.

Public Class DataNavigatorEventArgs
   Inherits EventArgs


   Private m_iCurrentPage As Integer
   Private m_iTotalPages As Integer

   Public Sub New()

   End Sub

   Public Property CurrentPage() As Integer
      Get
         Return m_iCurrentPage
      End Get
      Set(ByVal Value As Integer)
         m_iCurrentPage = Value
      End Set
   End Property

   Public Property TotalPages() As Integer
      Get
         Return m_iTotalPages
      End Get
      Set(ByVal Value As Integer)
         m_iTotalPages = Value
      End Set
   End Property


End Class

To make your control more developer friendly, you also expose a few properties for specifying the current page, the total number of pages, CSS class names to use, and so on. These properties are given values in the page load event for the control. You can find the rest of the code for PagingControl.ascx.vb in the sample accompanying this article, but a few important properties are shown here.

Public Property CurrentPage() As Integer
   Get
      Return _intCurrentPage
   End Get
   Set(ByVal Value As Integer)
      _intCurrentPage = Value

   End Set
End Property

Public Property TotalPages() As Integer
   Get
      Return _intTotalPages

   End Get
   Set(ByVal Value As Integer)
      _intTotalPages = Value

   End Set
End Property

The control is now ready.

Creating a Custom DataGrid Paging Control

2. Creating a Simple Webform to Use the Control

But you're not done yet. Using it on your page will require a few extra lines of code. Start by placing an ASP.NET datagrid on your page in a table cell, with the paging control you just created in the table row below it. Ensure that you set the DataGrid's AllowPaging property to true, and the DataGrid's PagerStyle's Visible property to false, because you want to use your own.

<table cellSpacing="0" cellPadding="0" width="100%" border="0">
   <tr>
      <td class="dataGridGeneralStyle">
      <asp:datagrid CssClass="dataGridGeneralStyle"
         id="DataGrid1"
         runat="server"
         Width="100%" AllowPaging="True">
         <HeaderStyle CssClass="dataGridHeaderStyle"></HeaderStyle>
         <PagerStyle Visible="False" NextPageText=""
                     PrevPageText=""></PagerStyle>
         </asp:datagrid>
      </td>
   </tr>
   <tr>
      <td class="customPagingStyle">
      <uc1:pagingcontrol id="PagingControl1"
                         runat="server"></uc1:pagingcontrol>
      </td>
   </tr>
</table>

Binding the grid to your data will be done pretty much the way you've always done it, with one minor difference: You will handle the PagingControl's PageChanged event and make a call to bind the datagrid from there.

Private Sub PagingControl1_PageChanged(ByVal sender As Object, _
   ByVal e As DataNavigatorEventArgs) _
   Handles PagingControl1.PageChanged

   Me.PagingControl1.CurrentPage = e.CurrentPage
   BindGrid()

End Sub

The BindGrid method is what makes the call to the stored procedure that returns your data to you. The BindGrid method also will use the current page number of the PagingControl to determine what set of data it needs from the database, without having to return all rows. This is more efficient. You will get to this method in the next section.

3. Creating a Stored Procedure that Allows Paging

Because a lot of you may not know how to get paged data from SQL Server, I thought I might as well add this to the article. This stored procedure is self explanatory in that it creates a temporary table holding all the Employees from the Northwind database, ordered by their last names and an identity field. The identity field is very important because it is what allows you to do the paging and to return the correct rows from the temporary table.

The stored procedure's code is also included in the solution accompanying this article. It takes three parameters:

  • @CurrentPage: The current page number whose data you want.
  • @Pagesize: The number of records to return per page.
  • @TotalRecords (output variable): The total number of records in the entire table.

Your BindGrid() method makes a call to this stored procedure.

'Specify values for the parameters required by the stored procedure
   Dim param As SqlParameter = cmd.Parameters.Add("@CurrentPage", _
      SqlDbType.Int)
   param.Direction = ParameterDirection.Input
   param.Value = PagingControl1.CurrentPage

   param = cmd.Parameters.Add("@PageSize", SqlDbType.Int)
   param.Direction = ParameterDirection.Input
   param.Value = PageSize

   param = cmd.Parameters.Add("@TotalRecords", SqlDbType.Int)
   param.Direction = ParameterDirection.Output

   'Call the stored procedure and get the return value
   Dim da As SqlDataAdapter = New SqlDataAdapter(cmd)
   Dim ds As DataSet        = New DataSet
   da.Fill(ds)
   totalCount = CInt(cmd.Parameters("@TotalRecords").Value)

PageSize is a class level variable on your page that you've initialized from the web.config file because you want to be flexible. You then take the totalCount variable and use it to calculate the number of pages.

'Using the total records returned, calculate the number of pages
   If (totalCount Mod PageSize) = 0 Then
      PagingControl1.TotalPages = totalCount / PageSize
   Else
      If (totalCount < PageSize) Then
         PagingControl1.TotalPages = 1
      Else
         PagingControl1.TotalPages = (totalCount / PageSize) + 1
      End If
   End If

4. Run It!

The sample that accompanies this article contains the complete code to make this work, including some CSS styles to make the grid more pleasing, and the rest of the code that I haven't shown here. You may need to change the connection string for your own instance of SQL Server, but once you do that, the sample should be ready to go.

The control is customizable and does not have to be the way I've shown you here. A good idea would be to replace the textbox with a drop-down list and handle its event as well, but you are left with that as an exercise.

And they lived happily ever after.



About the Author

SM Altaf

Mendhak is a web developer and a Microsoft MVP who works with ASP.NET and PHP among the usual array[] of web technologies. He is also rumored to be a three eyed frog, but the evidence is lacking. He can be contacted via his website, www.mendhak.com.


Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • It's hardly surprising that half of small businesses fail within the first 1-5 years. It's not easy to launch a new product, single-handedly manage everything from IT to accounting, fend off the competition, and grow a customer base – all at the same time – even with a great concept. Offering awesome customer service can make the difference between a startup that flies and a startup that dies. Read this white paper to learn nine ways customer support can help you beat the competition and grow your …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds