Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

Paging in DataGridView

3.19/5 (14 votes)
28 Mar 2009CPOL6 min read 1   7.7K  
Enable paging on a DataGridView control in VS 2005.

Screenshot - form.jpg

Introduction

This article provides a way to programmatically implement paging in a Windows DataGridView control. To my knowledge, there is no such functionality currently existing in the standard DataGridView control.

Background

A few months ago, I was put on a project to help out with the work load. Deadlines were looming and the extra help was needed. The form I had to code was a query form that listed various log tables in the database. The user could then select one of these log tables from a dropdown menu and the events captured by the selected log table was displayed in a DataGridView control. This part of the coding was easy, but there seemed to be just one problem. Sometimes these log tables were really large, containing hundreds even thousands of lines of entries. The customer wanted only to display a set amount of entries at a time and be able to page to the next, previous, last, and first pages of the grid.

I was then faced with trying to make a DataGridView control pageable. At first I thought that this task would be easy enough, but the more I researched it, the more I realised that there was no built-in functionality for making a DataGridView control pageable. I had to therefore come up with my own solution to extend the DataGridView control to include paging. The article below outlines a very basic Windows Form containing a Windows Toolstrip control with four buttons labeled First, Previous, Next, and Last. It also contains a DataGridView control and a BindingSource control.

A great idea for this project is to create your own custom control inheriting the base class for a DataGridView control and just extending its functionality to include paging, but for simplicity's sake, I have done the quick and dirty version by just adding the code in the form. Perhaps in a future article I will outline the steps to create your own custom control that inherits from the DataGridView control.

Using the code

Before we look at the code, do the following:

  • Create a new C# Windows Application with Visual Studio 2005
  • Drag a DataGridView control on to the Windows Form and call it dgNames
  • Drag a BindingSource control on to the form
  • Drag a Toolstrip control on to the form
  • On the Toolstrip control, create four buttons using the dropdown menu provided by the control
  • In the Properties of each button, set the DisplayStyle of each button to Text
  • Set the buttons' text to First, Previous, Next, and Last, respectively
  • Name the buttons as follows:
    • First = tsbFirst
    • Previous = tsbPrevious
    • Next = tsbNext
    • Last = tsbLast

Now that we have done this, let's look at the code.

Our Data Class

Usually you would read the data from a database via some sort of class. For simplicity's sake, I created a class called clsData that returns a dataset of hardcoded values. But you would need to use a class that reads the data you want to display in the DataGridView from some sort of data source. The following code is the code for the class used to return our dummy data.

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace GridviewPaging
{
    class clsData
    {
        public static DataSet GetData()
        {
            DataSet ds = new DataSet();

            try
            {
                ds.Tables.Add(GetTable());
                return ds;
            }
            catch (Exception ex)
            {
                String msg = ex.Message;
                return null;
            }
            finally
            {

            }
        }

        private static DataTable GetTable()
        {
            // Use the MakeTable function below to create a new table.
            DataTable dt;
            dt = MakeTable();
                        
            try
            {
                int i = 0;
                String Name = "Name";
                String LastName = "LastName";
                
                DataRow dr;
                

                for (i = 0; i <= 1000; i++)
                {
                    
                    // Once a table has been created, use the 
                    // NewRow to create a DataRow.
                    dr = dt.NewRow();

                    // Then add the new row to the collection.
                    dr["Fname"] = i + " " + Name;
                    dr["LName"] = i + " " + LastName;

                    
                    //// Then add the new row to the collection.
                    dt.Rows.Add(dr);
                }

                return dt;

            }
            catch (Exception ex)
            {
                String msg = ex.Message;
                return null;
            }
            finally
            {

            }
        }

        private static DataTable MakeTable()
        {
            // Create a new DataTable titled 'Names.'
            DataTable namesTable = new DataTable("Names");

            // Add three column objects to the table.
            DataColumn idColumn = new DataColumn();
            idColumn.DataType = System.Type.GetType("System.Int32");
            idColumn.ColumnName = "RecordID";
            idColumn.AutoIncrement = true;
            namesTable.Columns.Add(idColumn);

            DataColumn fNameColumn = new DataColumn();
            fNameColumn.DataType = System.Type.GetType("System.String");
            fNameColumn.ColumnName = "Fname";
            fNameColumn.DefaultValue = "Fname";
            namesTable.Columns.Add(fNameColumn);

            DataColumn lNameColumn = new DataColumn();
            lNameColumn.DataType = System.Type.GetType("System.String");
            lNameColumn.ColumnName = "LName";
            namesTable.Columns.Add(lNameColumn);

            // Create an array for DataColumn objects.
            DataColumn[] keys = new DataColumn[1];
            keys[0] = idColumn;
            namesTable.PrimaryKey = keys;


            // Return the new DataTable.
            return namesTable;
        }
    }
}

Our Main Form

If the code segments below don't make much sense now, don't worry. I have included the full code for the Windows Form at the end of this article.

At the top of the code window of our Windows Form, make sure you have these using statements:

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

I am also using the following namespace: namespace GridviewPaging.

I have also added a few variables global to this form to enable the paging of the DataGridView control. Add the following variables:

C#
private string NavClicked = "";
private string RecordID1 = "";
private string RecordID2 = "";
//We need this dataset to enable paging
private DataSet dsTemp = new DataSet();
int CurrentPage = 1;

Just below these variables, add the following enumerator. This determines which button was clicked.

C#
private enum NavButton
{
    First = 1,
    Next = 2,
    Previous = 3,
    Last = 4,
}

In the Form1_Load event, add the following code:

C#
private void Form1_Load(object sender, EventArgs e)
{
    //Get the data for the selected table and populate the Grid
    DataSet ds = new DataSet();
    ds = GridviewPaging.clsData.GetData();

    //Persist the Table Data to enable paging.
    dsTemp = ds;

    //If the dataset contains rows
    if (ds.Tables[0].Rows.Count > 0)
    {
        //Send to our Fill Grid method
        fillDataGrid_dtgBrowse(ds);
    }
    else
    {
        bindingSource1.DataSource = null;
        bindingSource1.Clear();
        dgNames.DataSource = bindingSource1;
    }
}

In the Form1_Load event, we are doing the following:

  • We are instantiating a new DataSet called ds.
  • We are setting ds equal to the DataSet returned by the GetData method in our clsData class.
  • We are setting another DataSet called dsTemp equal to ds to enable the persistence of data.
  • If our DataSet ds contains any data, we fill our DataGridView with this data.
  • If no data is returned, we clear the DataGridView.

We will now use two methods to enable paging. These methods are fillDataGrid_dtgBrowse and DeterminePageBoundaries. These methods are very well commented, so I didn't go into much detail in explaining what they do. The comments in the code do this.

fillDataGrid_dtgBrowse

C#
#region fillDataGrid_dtgBrowse
        
private void fillDataGrid_dtgBrowse(DataSet dtsTableData)
{
    try
    {
        Cursor = Cursors.WaitCursor;
        
        //Set the BindingSource's DataSource to the DataSet Parameter passed to it.
        bindingSource1.DataSource = dtsTableData.Tables[0];

        //Determine the page boundaries
        DeterminePageBoundaries(dtsTableData);
        //Now that we have the boundaries, filter the bindingsource.
        //This has the following effect as the following Query:
        //select * from [LogTable] where RecordID greater or = 10 and RecordID less or = 12
        bindingSource1.Filter = "RecordID >= " + RecordID1 + " and RecordID <= " + RecordID2;
        //Set the Grid's DataSource to the BindingSource. This populates the grid with data.
        dgNames.DataSource = bindingSource1;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        Cursor = Cursors.Default;
    }
}
#endregion

The fillDataGrid_dtgBrowse method simply does the binding of the data to the DataGridView control. Next we have the method DeterminePageBoundaries. We need to know the boundaries of the pages to enable the paging in the DataGridView.

DeterminePageBoundaries

C#
#region DeterminePageBoundaries
private void DeterminePageBoundaries(DataSet dsPages)
{
    int TotalRowCount = dsPages.Tables[0].Rows.Count;
    //This is the maximum rows to display on a page.
    //So we want paging to be implemented at 100 rows a page
    int pageRows = 100;
    int pages = 0;

    //If the rows per page are less than the total row count do the following:
    if (pageRows < TotalRowCount)
    {
        //If the Modulus returns > 0 then there should be another page.
        if ((TotalRowCount % pageRows) > 0)
        {
            pages = ((TotalRowCount / pageRows) + 1);
        }
        else
        {
            //There is nothing left after the Modulus, so the pageRows divide exactly...
            //...into TotalRowCount leaving no rest, thus no extra page needs to be added.
            pages = TotalRowCount / pageRows;
        }
    }
    else
    {
        //If the rows per page are more than the total
        //row count, we will obviously only ever have 1 page
        pages = 1;
    }


    //We now need to determine the LowerBoundary and UpperBoundary in order to correctly...
    //...determine the Correct RecordID's to use in the bindingSource1.Filter property.
    int LowerBoundary = 0;
    int UpperBoundary = 0;

    //We now need to know what button was clicked, if any (First, Last, Next, Previous)
    switch (NavClicked)
    {
        case "First":
            //First clicked, the Current Page will always be 1
            CurrentPage = 1;
            //The LowerBoundary will thus be ((50 * 1) - (50 - 1)) = 1
            LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));

            //If the rows per page are less than the total row count do the following:
            if (pageRows < TotalRowCount)
            {
                UpperBoundary = (pageRows * CurrentPage);
            }
            else
            {
                //If the rows per page are more than the total row count do the following:
                //There is only one page, so get the total row count as an UpperBoundary
                UpperBoundary = TotalRowCount;
            }

            //Now using these boundaries, get the appropriate RecordID's (min & max)...
            //...for this specific page.
            //Remember, .NET is 0 based, so subtract 1 from both boundaries
            RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]["RecordID"].ToString();
            RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]["RecordID"].ToString();

            break;

        case "Last":
            //Last clicked, the CurrentPage will always be = to the variable pages
            CurrentPage = pages;
            LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));
            //The UpperBoundary will always be the sum total of all the rows
            UpperBoundary = TotalRowCount;
            //Now using these boundaries, get the appropriate RecordID's (min & max)...
            //...for this specific page.
            //Remember, .NET is 0 based, so subtract 1 from both boundaries
            RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]["RecordID"].ToString();
            RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]["RecordID"].ToString();

            break;

        case "Next":
            //Next clicked
            if (CurrentPage != pages)
            {
                //If we arent on the last page already, add another page
                CurrentPage += 1;
            }

            LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));

            if (CurrentPage == pages)
            {
                //If we are on the last page, the UpperBoundary
                //will always be the sum total of all the rows
                UpperBoundary = TotalRowCount;
            }
            else
            {
                //Else if we have a pageRow of 50 and
                //we are on page 3, the UpperBoundary = 150
                UpperBoundary = (pageRows * CurrentPage);
            }

            //Now using these boundaries, get the appropriate RecordID's (min & max)...
            //...for this specific page.
            //Remember, .NET is 0 based, so subtract 1 from both boundaries
            RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]["RecordID"].ToString();
            RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]["RecordID"].ToString();

            break;

        case "Previous":
            //Previous clicked
            if (CurrentPage != 1)
            {
                //If we aren't on the first page already, subtract 1 from the CurrentPage
                CurrentPage -= 1;
            }
            //Get the LowerBoundary
            LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));

            if (pageRows < TotalRowCount)
            {
                UpperBoundary = (pageRows * CurrentPage);
            }
            else
            {
                UpperBoundary = TotalRowCount;
            }

            //Now using these boundaries, get the appropriate RecordID's (min & max)...
            //...for this specific page.
            //Remember, .NET is 0 based, so subtract 1 from both boundaries
            RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]["RecordID"].ToString();
            RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]["RecordID"].ToString();

            break;

        default:
            //No button was clicked.
            LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));

            //If the rows per page are less than the total row count do the following:
            if (pageRows < TotalRowCount)
            {
                UpperBoundary = (pageRows * CurrentPage);
            }
            else
            {
                //If the rows per page are more than the total row count do the following:
                //Therefore there is only one page,
                //so get the total row count as an UpperBoundary
                UpperBoundary = TotalRowCount;
            }

            //Now using these boundaries, get the appropriate RecordID's (min & max)...
            //...for this specific page.
            //Remember, .NET is 0 based, so subtract 1 from both boundaries
            RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]["RecordID"].ToString();
            RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]["RecordID"].ToString();

            break;
    }

}
#endregion

Lastly, we need to add code to the click events for our Next, Previous, First, and Last buttons. After you've done this, the rest is a piece of old tackie.

Button click events

C#
#region Page through DataGridView
        
private void tsbFirst_Click(object sender, EventArgs e)
{
    try
    {
        NavClicked = NavButton.First.ToString();
        fillDataGrid_dtgBrowse(dsTemp);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        Cursor = Cursors.Default;
    }
}

// Jump to the previous record in the DataGridView
private void tsbPrevious_Click(object sender, EventArgs e)
{
    try
    {
        NavClicked = NavButton.Previous.ToString();
        fillDataGrid_dtgBrowse(dsTemp);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        Cursor = Cursors.Default;
    }
}
        
// Jump to the next record in the DataGridView
private void tsbNext_Click(object sender, EventArgs e)
{
    try
    {
        NavClicked = NavButton.Next.ToString();
        fillDataGrid_dtgBrowse(dsTemp);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        Cursor = Cursors.Default;
    }
}

// Jump to the last record in the DataGridView
private void tsbLast_Click(object sender, EventArgs e)
{
    try
    {
        NavClicked = NavButton.Last.ToString();
        fillDataGrid_dtgBrowse(dsTemp);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        Cursor = Cursors.Default;
    }
}
#endregion

After you have added the click events for the buttons on your form, your code should look like this:

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;


namespace GridviewPaging
{
    public partial class frmMain : Form
    {
        private string NavClicked = "";
        private string RecordID1 = "";
        private string RecordID2 = "";
        //We need this dataset to enable paging
        private DataSet dsTemp = new DataSet();
        int CurrentPage = 1;

        private enum NavButton
        {
            First = 1,
            Next = 2,
            Previous = 3,
            Last = 4,
        }

        public frmMain()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
            //Get the data for the selected table and populate the Grid
            DataSet ds = new DataSet();
            ds = GridviewPaging.clsData.GetData();

            //Persist the Table Data to enable paging.
            dsTemp = ds;

            //If the dataset contains rows
            if (ds.Tables[0].Rows.Count > 0)
            {
                //Send to our Fill Grid method
                fillDataGrid_dtgBrowse(ds);
            }
            else
            {
                bindingSource1.DataSource = null;
                bindingSource1.Clear();
                dgNames.DataSource = bindingSource1;
            }
        }

        #region fillDataGrid_dtgBrowse
        
        // Fills the grid with the data from the DataSet
        private void fillDataGrid_dtgBrowse(DataSet dtsTableData)
        {
            try
            {
                Cursor = Cursors.WaitCursor;
                
                //Set the BindingSource's DataSource
                //to the DataSet Parameter passed to it.
                bindingSource1.DataSource = dtsTableData.Tables[0];

                //Determine the page boundaries
                DeterminePageBoundaries(dtsTableData);
                //Now that we have the boundaries, filter the bindingsource.
                //This has the following effect as the following Query:
                //select * from [LogTable] where RecordID >= 10 and RecordID <= 12
                bindingSource1.Filter = "RecordID >= " + RecordID1 + 
                                        " and RecordID <= " + RecordID2;
                //Set the Grid's DataSource to the BindingSource.
                //This populates the grid with data.
                dgNames.DataSource = bindingSource1;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
        #endregion

        #region DeterminePageBoundaries
        // This method will determine the correct
        // Page Boundaries for the RecordID's to filter by
        private void DeterminePageBoundaries(DataSet dsPages)
        {
            int TotalRowCount = dsPages.Tables[0].Rows.Count;
            //This is the maximum rows to display on a page.
            //So we want paging to be implemented at 100 rows a page
            int pageRows = 100;
            int pages = 0;

            //If the rows per page are less than
            //the total row count do the following:
            if (pageRows < TotalRowCount)
            {
                //If the Modulus returns > 0 then there should be another page.
                if ((TotalRowCount % pageRows) > 0)
                {
                    pages = ((TotalRowCount / pageRows) + 1);
                }
                else
                {
                    //There is nothing left after the Modulus,
                    //so the pageRows divide exactly...
                    //...into TotalRowCount leaving no rest,
                    //thus no extra page needs to be added.
                    pages = TotalRowCount / pageRows;
                }
            }
            else
            {
                //If the rows per page are more than the total
                //row count, we will obviously only ever have 1 page
                pages = 1;
            }


            //We now need to determine the LowerBoundary
            //and UpperBoundary in order to correctly...
            //...determine the Correct RecordID's
            //to use in the bindingSource1.Filter property.
            int LowerBoundary = 0;
            int UpperBoundary = 0;

            //We now need to know what button was clicked,
            //if any (First, Last, Next, Previous)
            switch (NavClicked)
            {
                case "First":
                    //First clicked, the Current Page will always be 1
                    CurrentPage = 1;
                    //The LowerBoundary will thus be ((50 * 1) - (50 - 1)) = 1
                    LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));

                    //If the rows per page are less than
                    //the total row count do the following:
                    if (pageRows < TotalRowCount)
                    {
                        UpperBoundary = (pageRows * CurrentPage);
                    }
                    else
                    {
                        //If the rows per page are more than
                        //the total row count do the following:
                        //There is only one page, so get
                        //the total row count as an UpperBoundary
                        UpperBoundary = TotalRowCount;
                    }

                    //Now using these boundaries, get the
                    //appropriate RecordID's (min & max)...
                    //...for this specific page.
                    //Remember, .NET is 0 based, so subtract 1 from both boundaries
                    RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]
                                              ["RecordID"].ToString();
                    RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]
                                              ["RecordID"].ToString();

                    break;

                case "Last":
                    //Last clicked, the CurrentPage will always be = to the variable pages
                    CurrentPage = pages;
                    LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));
                    //The UpperBoundary will always be the sum total of all the rows
                    UpperBoundary = TotalRowCount;
                    //Now using these boundaries, get the appropriate
                    //RecordID's (min & max)...
                    //...for this specific page.
                    //Remember, .NET is 0 based, so subtract 1 from both boundaries
                    RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]
                                              ["RecordID"].ToString();
                    RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]
                                              ["RecordID"].ToString();

                    break;

                case "Next":
                    //Next clicked
                    if (CurrentPage != pages)
                    {
                        //If we arent on the last page already, add another page
                        CurrentPage += 1;
                    }

                    LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));

                    if (CurrentPage == pages)
                    {
                        //If we are on the last page, the UpperBoundary
                        //will always be the sum total of all the rows
                        UpperBoundary = TotalRowCount;
                    }
                    else
                    {
                        //Else if we have a pageRow of 50 and we are
                        //on page 3, the UpperBoundary = 150
                        UpperBoundary = (pageRows * CurrentPage);
                    }

                    //Now using these boundaries, get the appropriate
                    //RecordID's (min & max)...
                    //...for this specific page.
                    //Remember, .NET is 0 based, so subtract 1 from both boundaries
                    RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]
                                              ["RecordID"].ToString();
                    RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]
                                              ["RecordID"].ToString();

                    break;

                case "Previous":
                    //Previous clicked
                    if (CurrentPage != 1)
                    {
                        //If we aren't on the first page already,
                        //subtract 1 from the CurrentPage
                        CurrentPage -= 1;
                    }
                    //Get the LowerBoundary
                    LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));

                    if (pageRows < TotalRowCount)
                    {
                        UpperBoundary = (pageRows * CurrentPage);
                    }
                    else
                    {
                        UpperBoundary = TotalRowCount;
                    }

                    //Now using these boundaries,
                    //get the appropriate RecordID's (min & max)...
                    //...for this specific page.
                    //Remember, .NET is 0 based, so subtract 1 from both boundaries
                    RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]
                                              ["RecordID"].ToString();
                    RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]
                                              ["RecordID"].ToString();

                    break;

                default:
                    //No button was clicked.
                    LowerBoundary = ((pageRows * CurrentPage) - (pageRows - 1));

                    //If the rows per page are less than
                    //the total row count do the following:
                    if (pageRows < TotalRowCount)
                    {
                        UpperBoundary = (pageRows * CurrentPage);
                    }
                    else
                    {
                        //If the rows per page are more than
                        //the total row count do the following:
                        //Therefore there is only one page,
                        //so get the total row count as an UpperBoundary
                        UpperBoundary = TotalRowCount;
                    }

                    //Now using these boundaries, get the
                    //appropriate RecordID's (min & max)...
                    //...for this specific page.
                    //Remember, .NET is 0 based, so subtract 1 from both boundaries
                    RecordID1 = dsPages.Tables[0].Rows[LowerBoundary - 1]
                                              ["RecordID"].ToString();
                    RecordID2 = dsPages.Tables[0].Rows[UpperBoundary - 1]
                                              ["RecordID"].ToString();

                    break;
            }

        }
        #endregion

        #region Page through DataGridView
        // Jump to the first record in the DataGridView
        private void tsbFirst_Click(object sender, EventArgs e)
        {
            try
            {
                NavClicked = NavButton.First.ToString();
                fillDataGrid_dtgBrowse(dsTemp);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
        
        // Jump to the previous record in the DataGridView
        private void tsbPrevious_Click(object sender, EventArgs e)
        {
            try
            {
                NavClicked = NavButton.Previous.ToString();
                fillDataGrid_dtgBrowse(dsTemp);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
       
        // Jump to the next record in the DataGridView
        private void tsbNext_Click(object sender, EventArgs e)
        {
            try
            {
                NavClicked = NavButton.Next.ToString();
                fillDataGrid_dtgBrowse(dsTemp);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
        
        // Jump to the last record in the DataGridView
        private void tsbLast_Click(object sender, EventArgs e)
        {
            try
            {
                NavClicked = NavButton.Last.ToString();
                fillDataGrid_dtgBrowse(dsTemp);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
        #endregion
    }
}

I hope that this will shed some light on how to make a DataGridView pageable. It is probably not the easiest method to accomplish this, but it worked very well for me. Download the source code and demo for the sample application and play around with it a bit.

Points of interest

The class clsData has some nice examples of how to create a datatable and add that datatable to a dataset. Somewhere sometime you might just need to do this, so have a look at the included class clsData as well.

Updates

  • 20 June 2007: I was going to post another article, extending this code into a user control that would include paging. However, after reading my article, topherino posted his own user control extending the DataGridView control to include paging. (See the Messages section below for the link to his article.) Check out his article for a DataGridView control that you simply drag and drop on to your form. It's a nicely written control and well worth using in your applications.
  • 3 July 2007: I have found a control in Visual Studio 2005 that provides more or less the functionality we need for paging. After you add a BindingSource control to your form, add a BindingNavigator control to the form as well. You set the BindingSource to your dataset, like this:
  • C#
    bindingSource1.DataSource = ds.Tables[0];

    Then you set your DataGridView's datasource to the BindingSource like this:

    C#
    dgNames.DataSource = bindingSource1;

    After you do this, you add the BindingNavigator control to the form and set its BindingSource property to your BindingSource (bindingSource1) that you added to your page. The BindingNavigator only allows you to advance one row at a time when you click the Next button. I do feel however that there might be a way to override this functionality and make it advance multiple rows at a time. Anyway, it's worth looking into. I haven't had time to look at this myself, but I'm sure that it could help others out there that only want to move one row at a time.

  • 28 March 2009: Fixed the article to display correctly in the Firefox browser.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)