ASP.NET GridView with Custom Paging UI

Posted by: Malcolm Sheridan , on 6/26/2009, in Category ASP.NET
Views: 150274
Abstract: The following article demonstrates how to customise how the paging is displayed in the GridView control.
ASP.NET GridView with Custom Paging UI
 
The GridView is a great web control when you want to display data from the database. Out of the box it has built-in paging, sorting and a multitude of events that you can control. Recently I thought about the paging aspect of the control and thought about how you could display the page numbers as something other than numbers, such as letters. Well here’s the answer! This code has not been requested by any of my customers but I thought it would be cool to try it out!
The trick to making this work is once the data has been bound to the GridView, you need to create the paging manually. This can be achieved by getting a reference to the BottomPagerRow property. The BottomPagerRow property represents the bottom pager row in a GridView. Once you have that reference you can create custom paging. For this example I’ll be connecting to the Northwind database. If you don’t have a copy of it, you can go here to download it.
To begin with open Visual Studio 2008 and choose File > New > Web > ASP.NET Web Application. 
Open the Default.aspx page and add a GridView control to the page. Click on the Smart Tag and in the Choose Data Source option choose <New data source...>
 
Choose_NewDataSource
 
Choose Database as the data source and let the name as chosen by Visual Studio. 
 
Database
 
Click OK. In the following screen choose your connection string and click Next:
 
DataConnection
 
After that select CustomerID, CompanyName, ContactName, ContactTitle, Address and City from the Customers table and click Next and then Finish after that:
 
Configure_Select_Statement
 
Now that after we have defined the data, we need to open the Default.aspx page and add a PagerTemplate to the GridView. The PagerTemplate allows you to customise the look and feel of the paging that will be displayed. Your code for the GridView will look like the following:
 
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" OnPageIndexChanging="GridView1_PageIndexChanging"
        OnDataBound="GridView1_DataBound" AutoGenerateColumns="False" DataKeyNames="CustomerID"
        DataSourceID="SqlDataSource1">
        <Columns>
            <asp:BoundField DataField="CustomerID" HeaderText="CustomerID" ReadOnly="True" SortExpression="CustomerID" />
            <asp:BoundField DataField="CompanyName" HeaderText="CompanyName" SortExpression="CompanyName" />
            <asp:BoundField DataField="ContactName" HeaderText="ContactName" SortExpression="ContactName" />
           <asp:BoundField DataField="ContactTitle" HeaderText="ContactTitle" SortExpression="ContactTitle" />
            <asp:BoundField DataField="Address" HeaderText="Address" SortExpression="Address" />
            <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
        </Columns>
        <PagerTemplate>
            <table width="100%">
                <tr>
                    <td style="text-align: right">
                        <asp:PlaceHolder ID="PlaceHolder1" runat="server" />
                    </td>
                </tr>
            </table>
        </PagerTemplate>
    </asp:GridView>
 
In the code above I have created a PagerTemplate. Inside I have created a simple HTML table that contains a PlaceHolder control. I am using a PlaceHolder because I want to dynamically add LinkButton controls to the PagerTemplate.
 
That’s it for the UI. Now we need to create the code that runs our custom paging. There are two events you need to hook into to make this work. They are the DataBound and the PageIndexChanging events. Handling the PageIndexChanging event is critical when you’re creating custom paging. Without it the GridView will not know which page to display to the user and throw an exception. Below is the code that creates and handles the paging:
 
C#
 
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{           
      GridView1.PageIndex = e.NewPageIndex;                     
}
 
protected void GridView1_DataBound(object sender, EventArgs e)
{  
      SetPaging();
}
 
private void SetPaging()
{
      GridViewRow row = GridView1.BottomPagerRow;
      int alphaStart = 65;
           
      for (int i = 1; i < GridView1.PageCount; i++)
      {               
            LinkButton btn = new LinkButton();
            btn.CommandName = "Page";
            btn.CommandArgument = i.ToString();
 
            if (i == GridView1.PageIndex + 1)
            {
                  btn.BackColor = Color.BlanchedAlmond;
            }
 
            btn.Text = Convert.ToChar(alphaStart).ToString();
            btn.ToolTip = "Page " + i.ToString();
            alphaStart++;
PlaceHolder place = row.FindControl("PlaceHolder1") as PlaceHolder;
            place.Controls.Add(btn);
 
            Label lbl = new Label();
            lbl.Text = " ";
            place.Controls.Add(lbl);
      }
}
 
VB.NET
 
Protected Sub GridView1_PageIndexChanging(ByVal sender As Object, ByVal e As GridViewPageEventArgs)
      GridView1.PageIndex = e.NewPageIndex
End Sub
 
Protected Sub GridView1_DataBound(ByVal sender As Object, ByVal e As EventArgs)
      SetPaging()
End Sub
 
Private Sub SetPaging()
      Dim row As GridViewRow = GridView1.BottomPagerRow
       Dim alphaStart As Integer = 65
 
       For i As Integer = 1 To GridView1.PageCount - 1
             Dim btn As New LinkButton()
                  btn.CommandName = "Page"
                  btn.CommandArgument = i.ToString()
 
                  If i = GridView1.PageIndex + 1 Then
                        btn.BackColor = Color.BlanchedAlmond
                  End If
 
                  btn.Text = Convert.ToChar(alphaStart).ToString()
                  btn.ToolTip = "Page " & i.ToString()
                  alphaStart += 1
Dim place As PlaceHolder = TryCast(row.FindControl("PlaceHolder1"), PlaceHolder)
                  place.Controls.Add(btn)
 
                  Dim lbl As New Label()
                  lbl.Text = " "
                  place.Controls.Add(lbl)
       Next i
End Sub
 
The main piece of code is the SetPaging method. This method is called once the GridView has been data bound. Firstly the code gets a reference to the paging row by the BottomPagerRow property. Next a LinkButton is created. This is created because the GridView will accept special parameters via the CommandName and CommandArgument properties. The CommandName must be set to Page but the CommandArgument can be one of the following values:
 
  • Integer Value – Navigates to the page number
  • Next – Navigates to the next page
  • Prev - Navigates to the previous page
  • Last – Navigates to the last page
  • First – Navigates to the first page
 
I am setting the CommandArgument to the index of the row. This way whenever a user clicks pages through the data, the GridView will know which page to display. And finally instead of showing numbers I am displaying letters of the alphabet. The letter A starts at 65, so I have created a variable called alphaStart to 65. To turn a number into an ascii value you can use the Convert.ToChar(alphaStart).ToString() code. For each row in the GridView I am incrementing the value of alphaStart, so that 1 will equal A, 2 will equal B etc. Once the LinkButton has been created, it is added to the PlaceHolder controls collection. The result is paging with letters.
 
Query_Result
 
This example might not be used in the real world, but I found it fun trying to work out how to make this work. Hopefully you’ll find some useful bits of information in here too.

Note: If you want to see other tips and tricks related to GridView Paging, check out another article by Suprotim Some Tips and Tricks while Using ASP.NET GridView Paging

The entire source code of this article can be downloaded from here
Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Malcolm Sheridan is a Microsoft awarded MVP in ASP.NET, a Telerik Insider and a regular presenter at conferences and user groups throughout Australia and New Zealand. Being an ASP.NET guy, his focus is on web technologies and has been for the past 10 years. He loves working with ASP.NET MVC these days and also loves getting his hands dirty with jQuery and JavaScript. He also writes technical articles on ASP.NET for SitePoint and other various websites. Follow him on twitter @malcolmsheridan


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by Madhu on Monday, June 29, 2009 8:02 AM
Thanks for the post, but I got an issue

I loaded the grid on page_load neglecting the postback everything went fine, but when I restricted the code in page_load to not ispostback, the event (grid_PageIndexChanging) is not raised and my paging controls are gone
Comment posted by Malcolm Sheridan on Monday, June 29, 2009 7:26 PM
@Madhu
Are you using the code from the sample?
Comment posted by Madhu on Tuesday, June 30, 2009 10:45 AM
@Malcolm
Mine is different from the sample, I have some IList & Databind calls

Actually I didn’t understood the following code in that sample - "if (IsPostBack){ SetPaging(); }"
As per the things I referred the above code might be workaround because on postback the dynamically generated link buttons are not available, if this is the case I got that working by doing the same on postback

Kindly correct if I am going wrong, Thanks for the early reply
Comment posted by Malcolm Sheridan on Tuesday, June 30, 2009 8:09 PM
@Madhu
Because the paging is dynamic, it needs to be recreated on postbacks.  That is why that code is there.
Comment posted by James Smith on Friday, July 3, 2009 9:03 AM
i couldn't understand the reason to use letters.  what does it do?  when i click on "B" or "D", the display does not start with "B" or "D".  could you explain?  thank you.
Comment posted by James Smith on Friday, July 3, 2009 11:04 AM
i couldn't understand the reason to use letters.  what does it do?  when i click on "B" or "D", the display does not start with "B" or "D".  could you explain?  thank you.
Comment posted by Malcolm Sheridan on Friday, July 3, 2009 5:56 PM
@James Smith
Hi James.  This was just an example of how you can customize the paging in a GridView.  Instead of letters you could display images, or anything else.
Comment posted by Wissam Bishouty on Saturday, September 12, 2009 1:40 AM
Greetings,
Thank you for the useful article.
I think that you have an rror in the article in the line :
I am setting the CommandArgument to the index of the row
so it should be I am setting the CommandArgument to the index of the page.

Regards.
Comment posted by Send me the password.........! on Sunday, September 13, 2009 1:14 PM
Send me the password.........!
Comment posted by gxm on Monday, September 14, 2009 3:32 AM
I code it,but it did not work.when I click the alpha, the page control disappear, and the gridview is still at the first page.But after I add SetPaging() in Page_Load, and change SetPaging() in GridView1_DataBound to "if (IsPostBack) SetPaging();".Then it works! Why?
the code is as follows:
        protected void Page_Load(object sender, EventArgs e)
        {
            SetPaging();
        }
        protected void GridView1_DataBound(object sender, EventArgs e)
        {
            if (IsPostBack) SetPaging();
        }
The other is the same.Can someone tell the reason.Thanks!
Comment posted by Gary on Sunday, September 20, 2009 10:29 PM
This is an excellent article Malcolm. Very useful for situations where the dataset is not too large. Nice of you to include both C# and VB code. Works great - thanks much!
Comment posted by Nisha on Wednesday, October 7, 2009 10:44 AM
As gyx(above) said same thing happened with me but why i did not understand ?
Comment posted by Ranveer Rajput on Thursday, January 7, 2010 4:51 AM
hello ,
i have face a ploblem - gridview having paging i have dropdown to each dropdown item i have fill gridview  \but after page size i will call page index which is filled by default fillgrid fn.. but i consider a conditon base (ddl.sel.i.text==-value-)
but the problems is that index is go to 2 or 3...... etc. pos not load at begin condition.
please help...., thanks RV...
Comment posted by Tom Y on Tuesday, January 26, 2010 1:32 PM
Question: I brought over some .net 2005 code that does something very similar to this example. But When I run it in 2008, the paging doesnt work. A click on any of the page numbers at the bottom of the gridview takes me to the last page. There is no use of "setpaging" used either in the 2005 version. Any thoughts?
Comment posted by Tom Y on Tuesday, January 26, 2010 1:35 PM
Correct myself. There is no bottom pager row  in my 2005 code
Comment posted by Muruganantham Durairaj on Tuesday, May 11, 2010 3:08 AM
It is really useful. I was in need of changing <a> tag's appearance using CSS. By checking "BottomPagerRow" property here. I done like below. Thanks.

    protected void gridView_DataBound(object sender, EventArgs e)
    {
        GridViewRow pagerRow = gridView.BottomPagerRow;
        if (pagerRow != null)
        {
            pagerRow.Attributes.Add("class", "myCssClassToApply");
        }
    }

Comment posted by TPS on Wednesday, September 8, 2010 9:20 AM
My pager row (ie A-ZA-Z) is displaying twice and I can't figure out why. All the links work fine and the code behaves the way it should, it's just doubled. Any ideas?
Comment posted by Sandeep Mittal on Tuesday, January 11, 2011 2:01 AM
Refer to this link
http://itdeveloperzone.blogspot.com/2011/01/custom-paging-in-grid-view.html
Comment posted by haidear howareyou on Thursday, May 5, 2011 7:29 AM
hi yenakku onnum theriyathu so nee yenna panuviyo yenakku theriyathu ozhunga padichitu nalla workpannanum sariya po poi velaya paru ok bye...... varata
Comment posted by dsfdf on Thursday, May 5, 2011 7:30 AM
sdfdfdfdf
Comment posted by Hours on Wednesday, August 24, 2011 9:02 AM
GridViewRow row = grdClaim.BottomPagerRow

row is null.
Comment posted by kamal saxena on Thursday, September 22, 2011 3:35 AM
thanks
Comment posted by c-chavez on Wednesday, October 12, 2011 7:22 PM
The reason why you have to insert this code

protected void Page_Load(object sender, EventArgs e)
        {
            SetPaging();
        }

is because when the click event is fired, the SetPaging() will be called and the CommandName "Page" will be associated to your controls. If you don't do this, the command will never be associated and it will become a regular link just like any other. Actually you only need to call the method SetPaging() if it's a postback.

Hope this helps.
Comment posted by Chandraprakash mourya on Monday, November 21, 2011 3:56 AM
thanks
Comment posted by shakir on Thursday, December 1, 2011 3:47 AM
hi malcom. i tried this code in master page. i am using timer in my master page to keep the session alive but the problem is even i am filling the form in one page and the allowpaging method executes on its own in other page. why is this happening i dint understand. Thanks in advance..
Comment posted by Keith B on Friday, October 26, 2012 3:39 AM
As Malcolm himself comments, this technique is just an example of what can be done with the Paging area of the grid. IT DOES NOT filter the data to show those rows that start with the letter you clicked on.
Comment posted by alexander on Thursday, December 6, 2012 12:45 AM
thanks, but in the loop use less than or equal: for (int i = 1; i <= GridView1.PageCount; i++)

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel