How to do custom paging in GridView in ASP.Net 4.5

In this post I will discuss a new feature that has been introduced in ASP.Net 4.5 related to GridView server control. In ASP.Net 4.5, GridView control has been enhanced to allow custom paging. When you set AllowPaging property on your GridView, you do not have to do any thing extra to have Pager show up with the grid depending on the style you decide to use. There is not extra code required from your side to enable paging of data on GridView. But what this means is that when you change pages, GridView ends up calling you datasource every single time. This means all the data is being retrieved from the database for every page index change. That will hurt performance of your application as well as database if you are accessing a datasource that may have huge number of rows being fetched on every single request.

To deal with this web application performance issue, the obvious solution is that you only fetch data when it is needed and only fetch rows that you are required to server that page in GridView. To accomodate this GridView allows you to set the following properties to turn on custom paging.

  • AllowCustomPaging (Must set to true)
  • VirtualItemCount
  • AllowPaging (Must set to true)

As you can see that I have indicated two properties that must be set to true to allow GridView to enable custom paging. The following mark up shows how I set it up on my demo application.

        <asp:GridView ID="VirtualGridView" runat="server"
        AllowPaging="True" >

Just setting these two properties will not do the trick. If you do not do any thing else, you will observe following behavior.

  • GridView will only show 10 records (if there are more than 10 records in your data source). Default PageSize for GridView is 10.
  • The pager will not show even if you have more than 10 records in data source.

The above behavior does not mean that GridView is broken or there is bug. Since we have set AllowCustomPaging to true, a lot of responsibility shifts to the developer now. I guess it makes sense because you want to do custom paging anyways. Let's see what do we need to get this magic happen and improve performance of GridView and well as database.


This property allows you to tell GridView total record count that it should use when deciding how many pages are to be displayed in the pager. The value for this property does not have to be same as total number of records in your data source. This is very important part of custom paging because it helps in rendering the pager control. If you have a very large data source, you can set VirtualItemCount to some reasonable number and then change is based on user's behavior and action while the user is paging forward. If VirtualItemCount value is higher than PageSize value and you have records more than PageSize, then GridView will display the pager control.


You will need to handle this event for your GridView. In this event you will set PageIndex property of GridView to index new page index that user has asked for. And then fetch just the records for that page only. So if your page size is 20, you can just prepare data source with those 20 records only and then bind grid to that data source. Now you can see how custom paging allows you to minimize database calls and load by fetching just the required set of data.

Sample Code

Following is sample code from my demo application

ASPX tags

<asp:GridView ID="VirtualGridView" runat="server" AllowCustomPaging="true" 
    AllowPaging="True" AutoGenerateColumns="False"
     <asp:BoundField DataField="Title" HeaderText="Title" 
          SortExpression="Title" />
     <asp:BoundField DataField="Author" HeaderText="Author" 
          SortExpression="Author" />
   <PagerStyle HorizontalAlign="Right" />
   <PagerSettings Mode="Numeric" />

Code Behind

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;

namespace GridControl11
    public partial class _Default : Page
        private List<be_Posts> _allPosts;
        private List<be_Posts> _currentPagePosts;
        protected void Page_Load(object sender, EventArgs e)
            if (!IsPostBack)
                VirtualGridView.VirtualItemCount = _allPosts.Count;
                GetPageData(0, VirtualGridView.PageSize);

        private void BindGrid()
            VirtualGridView.DataSource = _currentPagePosts;
        protected void VirtualGrid_PageIndexChanging
             (object sender, GridViewPageEventArgs e)
            GetPageData(e.NewPageIndex, VirtualGridView.PageSize);
            VirtualGridView.PageIndex = e.NewPageIndex;

        private void GetPageData(int start, int count)
            _currentPagePosts = _allPosts.GetRange(start, count);

        protected void GetPosts()
            _allPosts = Session["AllPosts"] as List<be_Posts>;
            if (null == _allPosts)
                var dataModel = new ByteBlocksEntities();
                _allPosts = dataModel.be_Posts.ToList<be_Posts>();
                Session["AllPosts"] = _allPosts;

As you can see that I got all the records for my source right at page load time and put them in session. After that I am pnly fetching what I need for the page and not binding the whole list to GridView.




24.5 °C / 76.1 °F

weather conditions Haze

Monthly Posts

Blog Tags