Library tutorials & articles

Custom ASP.NET Datagrid Paging With Exact Count

The HTML Portion

In this part we'll look at the HTML content of the custom paging Web page and examine the other server-side subroutines and event handlers. In our HTML section we need a couple of label controls to display various bits of information, such as what page we are currently viewing, how many total records there are, etc. We also need a DataGrid, to which we are binding the database results to. Don't forget to put the DataGrid in a WebForm (a <form> tag with the runat="server" attribute specified). Finally, we need a series of LinkButton Web controls, to display our Prev/First Page and Next/Last Page links.

The content for the HTML section is as follows:

<html>
<body>
'For our recordcount and pagecount
<asp:Label id="lblPageCount" runat="server" /><br>
<asp:label id="RecordCount" runat="server" />

<form runat="server">
    <ASP:Datagrid id="pubs" runat="server"
                AllowPaging="True"
                AllowCustomPaging="False"
                Pagesize="10"
                PagerStyle-Visible = "False"
    />
    <%-- Display the First Page/Previous Page buttons --%>
    <asp:linkbutton id="Firstbutton" Text="<< 1st Page"
                    CommandArgument="0" runat="server"
                    onClick="PagerButtonClick"/>
    <asp:linkbutton id="Prevbutton" Text= ""
                    CommandArgument="prev" runat="server"
                    onClick="PagerButtonClick"/>
   
    <%-- Display the Next Page/Last Page buttons --%>
    <asp:linkbutton id="Nextbutton" Text= ""
                    CommandArgument="next" runat="server"
                    onClick="PagerButtonClick"/>
    <asp:linkbutton id="Lastbutton" Text="Last Page >>"
                    CommandArgument="last" runat="server"
                    onClick="PagerButtonClick"/>
    <br><br><br><br>
    Change Pagesize
    <asp:DropDownList id="ps" runat="server">
        <asp:ListItem>4</asp:ListItem>
        <asp:ListItem>5</asp:ListItem>
        <asp:ListItem>7</asp:ListItem>
        <asp:ListItem selected>10</asp:ListItem>
        <asp:ListItem>12</asp:ListItem>
        <asp:ListItem>15</asp:ListItem>
        <asp:ListItem>22</asp:ListItem>
    </asp:DropDownList>
   
    <asp:button text="Change Pagesize" runat="server" OnClick="RePage"/>
</form>
</body>
</html>

Note that in our DataGrid Web control we set the PagerStyle'sVisible property to False. This is because we are implementing our own paging solution, and don't want to use the default paging style supported by the DataGrid Web control. (For more information on paging database results using the DataGrid's built-in functionality, be sure to read: Paging Database Results in ASP.NET!) Also note that the four LinkButton controls all specify the server-side subroutine PagerButtonClick as the sub to be called when they are clicked; similarly, the "Change Pagesize" button has the RePage subroutine defined as its OnClick event handler.

The event handler for the four LinkButtons (PagerButtonClick) must display the appropriate page of data, be it the next page, the previous page, the first page, or the last page. Which page to display, of course, depends on what LinkButton the user clicked. The PagerButtonClick (shown below) uses the CommandArgument passed in from the LinkButton Web controls to determine which control was clicked, and then takes the appropriate action.

Sub PagerButtonClick(sender As Object, e As EventArgs)
'used by external paging UI
Dim arg As String = sender.CommandArgument
Select arg
    Case "next": 'The next Button was Clicked
        If (Pubs.CurrentPageIndex < (Pubs.PageCount - 1)) Then
            Pubs.CurrentPageIndex += 1
        End If
    Case "prev": 'The prev button was clicked
        If (Pubs.CurrentPageIndex > 0) Then
            Pubs.CurrentPageIndex -= 1
        End If
    Case "last": 'The Last Page button was clicked
        Pubs.CurrentPageIndex = (Pubs.PageCount - 1)
    Case Else:     'The First Page button was clicked
        Pubs.CurrentPageIndex = Convert.ToInt32(arg)
End Select
    'Now, bind the data!
    BindSQL()
End Sub

The RePage event handler, which is called when the "Change Pagesize" button is clicked, simply resets the DataGrid's CurrentPageIndex property back to 0 and rebinds the database data:

Sub Repage(sender As Object, e As EventArgs)
    Pubs.CurrentPageIndex = 0
    BindSQL()
End Sub

Finally, the last two server-side subroutines are two meager helper subroutines, Next_Buttons() and Prev_Buttons(), which display the correct text for each of the LinkButtons. These two subs, which are called from BindSQL(), can be seen below:

Sub Prev_Buttons()
Dim PrevSet As String
If Pubs.CurrentPageIndex+1 <> 1 and ResultCount <> -1 Then
    PrevSet = Pubs.PageSize
    PrevButton.Text = ("< Prev " & PrevSet)

    If Pubs.CurrentPageIndex+1 = Pubs.PageCount Then
    FirstButton.Text = ("<< 1st Page")
    End If
End If
End Sub

Sub Next_Buttons()
Dim NextSet As String
If Pubs.CurrentPageIndex+1 < Pubs.PageCount Then
    NextSet = Pubs.PageSize
    NextButton.Text = ("Next " & NextSet & " >")
End If
If Pubs.CurrentPageIndex+1 = Pubs.PageCount-1 Then
    Dim EndCount As Integer
    EndCount = ResultCount - (Pubs.PageSize * (Pubs.CurrentPageIndex+1))
    NextButton.Text = ("Next " & EndCount & " >")
End If
End Sub

Well, that's it! Be sure to view the complete code (on the next page), try out the live demo, and read up on the related articles! If you have any questions, please do not hesitate to email me!

Happy Programming!

This article was originally published on 4guysfromrolla.com.

AddThis

Comments

  1. 08 Jul 2005 at 17:18

    Hi, thanks, I appreciate your compliments.


    I have written another older article that I think should help. It's entitled- Drilldown Datagrid Searching with ASP.NET.


    This article demonstrates how to do a standard search, display the results in a datagrid, then further filter and search the datagrid itself and drilldown into the datagrid results themselves.


    So to merge the two, work off of the aforementioned article and incorporate the custom paging. All this should be no problem, and plenty to get you up and running.


    Also, for scalability purposes, read another article of mine here on DF - .NET Data Caching . Between the two you'll be able to provide some great functionality and performance.


    I hope this helps!


    - Jimmy Markatos

  2. 08 Jul 2005 at 15:56

    I loved your article on custom paging but would very much like to know how to apply it when you filter your initial data set to retreive specific records. I have a grid with 813 records sorted by user name. I have a search box in which a user can enter a name in order to filter the original dataset. If the search result in only 4 pages of records how can I page through that new set of records? Thanks in advance for any help and for the great article.

  3. 26 Oct 2003 at 20:00

    Check this site...


    I too was on the same quest and I've created a best practices reference site that covers many enterprise topics necessary to create large scale enterprise sites.

  4. 17 Oct 2003 at 05:38

    Hello,


    Tankete, I just have try what you are asking for a couple of days ago :


    The principe is simple : returning only a needed page from 50th to 60th records consists in querying this way :


    SELECT * TOP 60 ... WHERE NOT IN SELECT TOP 50 * WHERE [joining primarykeys]


    I have taken advices from Dino Esposito's MSDN articles, and have created a PageQuery function thats returns such a SQL statement, based on a normal SQL statement, primaryKey information, currentpageindex and pagesize.


    This sample of code uses a custompaged enabled datagrid called dg, with a access database that contains a "HugeTable" table with a "ID" primary key.


    Do not forget to enable custompaging to your datagrid


    Code:


       Private _Cx As OleDbConnection


       Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


           Cx = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Password="""";User ID=Admin;Data Source=C:\Inetpub\wwwroot\labo\app\db\pageddatagrid.mdb;Mode=Share Deny None;")


           If Not IsPostBack Then
               dg.DataBind()
               DataList1.DataBind()
           End If


       End Sub


       '


       Private Sub dg_DataBinding(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dg.DataBinding


           Dim sqlstr As String = PageQuery("SELECT * FROM HugeTable ORDER BY ID", "ID", dg.CurrentPageIndex, dg.PageSize)
           _Cx.Open()


           dg.VirtualItemCount = New OleDbCommand("SELECT COUNT(*) FROM HugeTable", _Cx).ExecuteScalar
           Dim dr As OleDbDataReader = New OleDbCommand(sqlstr, _Cx).ExecuteReader(CommandBehavior.CloseConnection)
           dg.DataSource = dr


       End Sub


       '
       '
       Private Function PageQuery(ByVal commandText As String, _
                                  ByVal primaryKey As String, _
                                  ByVal currentPageIndex As Integer, _
                                  ByVal pageSize As Integer) As String


           Dim SubQuery1_TopCount As Integer = IIf(currentPageIndex = 0, _
                                                   pageSize, _
                                                   currentPageIndex * pageSize + pageSize)


           Dim SubQuery1 As String = Replace(commandText, _
                                             "SELECT ", _
                                             String.Format("SELECT TOP {0} ", SubQuery1_TopCount))


           If currentPageIndex = 0 Then Return SubQuery1


           SubQuery1 = String.Format("({0}) AS T1", SubQuery1)


           Dim SubQuery2_TopCount As Integer = currentPageIndex * pageSize


           Dim SubQuery2 As String = Replace(commandText, _
                                             "SELECT ", _
                                             String.Format("SELECT TOP {0} ", SubQuery2_TopCount))


           SubQuery2 = String.Format("({0}) AS T2", SubQuery2)


           Dim MainQuery As String = String.Format("SELECT t1.* FROM {0} LEFT JOIN {1} ON T1.{2}= T2.{2} WHERE T2.{2} IS NULL", _
                                                   SubQuery1, _
                                                   SubQuery2, _
                                                   primaryKey)


           Return MainQuery


       End Function


       '


       Private Sub dg_PageIndexChanged(ByVal source As System.Object, ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) Handles dg.PageIndexChanged
           dg.CurrentPageIndex = e.NewPageIndex
           dg.DataBind()
       End Sub




    Hope it helps. For SQL server, the built query could be better implemented using subqueries instead of inner join, which is much more faster in access.


    Laurent.

  5. 16 Oct 2003 at 14:58

    I was hoping that you would address how to do paging with exact counts while NOT returning the entire dataset from the database, just the current page worth of data. Can you provide any information on how you would accomplish that? The current approach that I can think of does not perform as well as desired.

Leave a comment

Sign in or Join us (it's free).

Related discussion

Events coming up

  • Oct 14

    What’s New in Visual Studio 2008 Service Pack 1?

    Birmingham, United Kingdom

    “Service Pack? We’re calling it a Service Pack? Are you kidding??!?!” Visual Studio 2008 Service Pack 1 will release later in 2008 alongside .NET Framework V3.5 Service Pack 1 and, together, they represent a significant upgrade to Visual Studio 2008. There are enhancements across many areas of the .NET Framework such as data access, windows application development and web development and there are also corresponding changes in the development environment to support the new framework features.