One of the first topics I searched for when working with the ASP.NET GridView control was how to page data with it. I quickly discovered that the GridView control has built-in paging capabilities. However, I wanted to customize my GridView pager. The built-in pager just didn't cut it for me. Not only did I want to customize the pager, I didn't want to have to define my pager template and wire everything in each time I used my GridView control because it would be used 100's of times.
In order to encapsulate the paging features I desire, I am going to make my own custom GridView control. In my pager I want the following:
1) A "Page X of Y" caption
2) Basic first, previous, next, and last navigation
3) A page selector drop down list so the user can jump to a page quickly
If you've used the GridView before, you may have utilized the built-in paging modes. I don't necessarily want to remove that functionality. I want to add to it. So what I am going to do is create a public property called "PagerType" where we can specify if we want to use the GridView's built-in paging or if we want to use our custom paging.
Public Class PagingGridView
Inherits GridView
Public Enum PagerTypes
Regular = 0
Custom = 1
End Enum
<DefaultValue(PagerTypes.Custom), Category("Paging"), Description("Indicates whether to use the built-in custom pager or not.")> _
Public Property PagerType() As PagerTypes
Get
If Not ViewState("PagerType") Is Nothing Then
Return DirectCast(ViewState("PagerType"), PagerTypes)
Else
Return PagerTypes.Custom
End If
End Get
Set(ByVal value As PagerTypes)
ViewState("PagerType") = value
End Set
End Property
From this code snippet we are inheriting from the GridView control, defining our 2 paging types (regular & custom), and we define our pager type property. In order for our pager to be initialized, we need to override the InitializePager method. What this method does is initialize the pager row when paging is enabled. We need to determine if we want to allow the GridView to use its built-in pager or if we need to use our custom pager. A simple select case statement will do the trick here.
Protected Overrides Sub InitializePager(ByVal row As System.Web.UI.WebControls.GridViewRow, ByVal columnSpan As Integer, ByVal pagedDataSource As System.Web.UI.WebControls.PagedDataSource)
Select Case Me.PagerType
Case PagerTypes.Custom
InitCustomPager(row, columnSpan, pagedDataSource)
Case Else
MyBase.InitializePager(row, columnSpan, pagedDataSource)
End Select
You'll notice that we have an InitCustomPager method we call to initialize our pager controls. I'm not going to post the code snippet for this. You can download the code and sift through it if you want. The things to note is the wiring of events. Our first, previous, next, and last image buttons throw a Command event and the drop down list throws a SelectedIndexChanged event. Our PagingGridView control will handle these events and fire a the OnPageIndexChanging event which can be handled by the page.
Protected Sub ddlPages_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim newPageIndex As Integer = CType(sender, DropDownList).SelectedIndex
OnPageIndexChanging(New GridViewPageEventArgs(newPageIndex))
End Sub
Protected Sub PagerCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.CommandEventArgs)
Dim curPageIndex As Integer = Me.PageIndex
Dim newPageIndex As Integer = 0
Select Case e.CommandName
Case "First"
newPageIndex = 0
Case "Previous"
If curPageIndex > 0 Then
newPageIndex = curPageIndex - 1
End If
Case "Next"
If Not curPageIndex = Me.PageCount Then
newPageIndex = curPageIndex + 1
End If
Case "Last"
newPageIndex = Me.PageCount
End Select
OnPageIndexChanging(New GridViewPageEventArgs(newPageIndex))
End Sub
Here are the even handlers for my image buttons and the page drop down list. You'll see that in each handler, I raise the OnPageIndexChanging event passing in the new page index to navigate to.
So let's use our new PagingGridView control. I'm going to dynamically create a DataTable object on the fly to bind my GridView to for this example. I also created some css and images to make the GridView look good. You can find them in the download package if you need them.
<cc1:PagingGridView ID="PagingGridView1" runat="server"
CssClass="paging_gridview" PageSize="5" AllowPaging="true" Width="400">
<RowStyle CssClass="paging_gridview_itm" />
<PagerStyle CssClass="paging_gridview_pgr" />
<HeaderStyle CssClass="paging_gridview_hdr" />
<AlternatingRowStyle CssClass="paging_gridview_aitm" />
</cc1:PagingGridView>
Here is the HTML markup for our new PagingGridView. Note that we enabled paging and set the page size to 5. We did not specify the pager type to custom because the default value is set to our custom pager. If we wanted to revert to the GridViews built-in paging, we would set PagerType="Regular". The only thing left to do is handle the OnPageIndexChanging to rebind our GridView to the new page via our code behind and that's it.
Private Sub PagingGridView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles PagingGridView1.PageIndexChanging
Me.PagingGridView1.PageIndex = e.NewPageIndex
PagingGridView1_DataBind()
End Sub
I hope you enjoyed this post. It definitely has improved developer productivity without having to define a pager template and wire in the controls everytime I use the GridView. The final screenshot of the PagingGridView is below.
GridViewPaging_Soln.zip (108.06 kb)