GridView with DataPager in ASP.NET 3.5


To page through data in a control that implements the IPageableItemContainer interface, DataPager control can be used. GridView has its own paging and does not implement IPageableItemContainer interface. ListView is the only control that works with DataPager.

The DataPager control supports built-in paging user interface (UI). NumericPagerField object enables users to select a page of data by page number. NextPreviousPagerField object enables users to move through pages of data one page at a time, or to jump to the first or last page of data. The size of the pages of data is set by using the PageSize property of the DataPager control. One or more pager field objects can be used in a single DataPager control. Custom paging UI can be created by using the TemplatePagerField object. In the TemplatePagerField template, the DataPager control is referenced by using the Container property which provides access to the properties of the DataPager control. These properties include the starting row index, the page size, and the total number of rows currently bound to the control.

So let's begin extending the GridView with the IPageableItemContainer interface.

Define a new class as below
/// <summary>

/// DataPagerGridView is a custom control that implements GrieView and IPageableItemContainer

/// </summary>

public class DataPagerGridView : GridView, IPageableItemContainer

{
}

MaximumRows will be equal to the PageSize property
/// <summary>

/// IPageableItemContainer's MaximumRows  = PageSize property

/// </summary>

int IPageableItemContainer.MaximumRows

{

    get { return this.PageSize; }

}

StartRowIndex can be calculated from the PageSize and PageIndex properties
/// <summary>

/// IPageableItemContainer's StartRowIndex = PageSize * PageIndex properties

/// </summary>

int IPageableItemContainer.StartRowIndex

{

    get { return this.PageSize * this.PageIndex; }

}

The SetPageProperties method is called by the DataPager control every time that the control must update the page-related properties. When implemented by a class, the SetPageProperties method must internally update the MaximumRows and StartRowIndex properties by using the values of the maximumRows and startRowIndex parameters. So set the Grid with appropriate parameters and bind to right chunk of data.
/// <summary>

/// Set the control with appropriate parameters and bind to right chunk of data.

/// </summary>

/// <param name="startRowIndex"></param>

/// <param name="maximumRows"></param>

/// <param name="databind"></param>

void IPageableItemContainer.SetPageProperties(int startRowIndex, int maximumRows, bool databind)

{

    int newPageIndex = (startRowIndex / maximumRows);

    this.PageSize = maximumRows;

    if (this.PageIndex != newPageIndex)

    {

        bool isCanceled = false;

        if (databind)

        {

            //  create the event arguments and raise the event

            GridViewPageEventArgs args = new GridViewPageEventArgs(newPageIndex);

            this.OnPageIndexChanging(args);

            isCanceled = args.Cancel;

            newPageIndex = args.NewPageIndex;

        }

        //  if the event wasn't cancelled change the paging values

        if (!isCanceled)

        {

            this.PageIndex = newPageIndex;

            if (databind)

                this.OnPageIndexChanged(EventArgs.Empty);

        }

        if (databind)

            this.RequiresDataBinding = true;

    }

}

For the DataPager to render the correct number of page buttons and enable/disable them, it needs to know the total number of rows and the Page Size. But this information is with the GridView and not known to the DataPager.As the GridView control inherits from CompositeDataboundControl which contains a variant of the CreateChildControls method that also takes in a property indicating whether the control is being bound to data or simply re-rendered. The GridView uses this method to bind to its data source and here we can place a trigger for the TotalRowCountAvailable event to be raised. Call base control's CreateChildControls method and determine the number of rows in the source then fire off the event with the derived data and then we return the original result.
protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)

{

    int rows = base.CreateChildControls(dataSource, dataBinding);

    //  if the paging feature is enabled, determine the total number of rows in the datasource

    if (this.AllowPaging)

    {

    //  if we are databinding, use the number of rows that were created, otherwise cast the datasource to an Collection and use that as the count

    int totalRowCount = dataBinding ? rows : ((ICollection)dataSource).Count;

    //  raise the row count available event

    IPageableItemContainer pageableItemContainer = this as IPageableItemContainer;

    this.OnTotalRowCountAvailable(new PageEventArgs(pageableItemContainer.StartRowIndex,pageableItemContainer.MaximumRows,totalRowCount));

    //  make sure the top and bottom pager rows are not visible

    if (this.TopPagerRow != null)

        this.TopPagerRow.Visible = false;

    if (this.BottomPagerRow != null)

        this.BottomPagerRow.Visible = false;

    }

    return rows
}

 That's all you are done, put the control on aspx page and use DataPager with GridView Contol.