In this article I will explain with an example, how to implement Paging using Skip and Take functions in LINQ in Windows Forms (WinForms) Application using C# and VB.Net.
 
 
Form Design
The following Form consists of a DataGridView and a Panel control.
Paging using Skip and Take functions in LINQ using C# and VB.Net
 
 
Entity Framework Model
Once the Entity Framework is configured and connected to the database table, the Model will look as shown below.
Note: For beginners in Windows Forms and Entity Framework, please refer my article Entity Framework Database First Approach in Windows Forms using C# and VB.Net. It covers all the information needed for connecting and configuring Entity Framework.
 
Paging using Skip and Take functions in LINQ using C# and VB.Net
 
 
Implementing Paging in DataGridView
Inside the Form Load event, the BindGrid function is called.
Inside the BindGrid function, the records from the Customers table of the Northwind database are fetched using DataReader (SqlDataReader).
The SqlDataReader is then loaded into a DataTable and finally the DataTable is used to populate the DataGridView.
Note: For more details about populating the DataGridView control using DataReader, please refer my article, Populate (Bind) DataGridView using DataReader in Windows Forms (WinForms) Application using C# and VB.Net.
 
Initially the value of the PageSize is set to 5 and the PageIndex is set as 1. The value of the RecordCount Output parameter and PageIndex are passed to the PopulatePager method (discussed later).
C#
int PageSize = 5;
privatevoid Form1_Load(object sender, EventArgse)
{
    //Set AutoGenerateColumns False
    dataGridView1.AutoGenerateColumns = false;
 
    //Set Columns Count
    dataGridView1.ColumnCount = 3;
 
    //Add Columns
    dataGridView1.Columns[0].Name = "CustomerID";
    dataGridView1.Columns[0].HeaderText = "Customer Id";
    dataGridView1.Columns[0].DataPropertyName = "CustomerID";
 
    dataGridView1.Columns[1].HeaderText = "Contact Name";
    dataGridView1.Columns[1].Name = "Name";
    dataGridView1.Columns[1].DataPropertyName = "ContactName";
 
    dataGridView1.Columns[2].Name = "Country";
    dataGridView1.Columns[2].HeaderText = "Country";
    dataGridView1.Columns[2].DataPropertyName = "Country";
 
    this.BindGrid(1);
}
 
publicvoid BindGrid(int startIndex)
{
    using (NORTHWINDEntities entities = new NORTHWINDEntities())
    {
        List<Customer> customers = (from customer in entities.Customers
                                    select customer)
                                    .OrderBy(customer => customer.CustomerID)
                                    .Skip((startIndex - 1) * PageSize)
                                    .Take(PageSize).ToList();
        dataGridView1.DataSource = customers;
        this.PopulatePager(entities.Customers.Count(), startIndex);
    }
}
 
VB.Net
Private PageSize As Integer = 5
Private Sub Form1_Load(ByVal sender AsObject, ByVal e As EventArgs) Handles Me.Load
    dataGridView1.AutoGenerateColumns = False
    dataGridView1.ColumnCount = 3
    dataGridView1.Columns(0).Name = "CustomerID"
    dataGridView1.Columns(0).HeaderText = "Customer Id"
    dataGridView1.Columns(0).DataPropertyName = "CustomerID"
 
    dataGridView1.Columns(1).HeaderText = "Contact Name"
    dataGridView1.Columns(1).Name = "Name"
    dataGridView1.Columns(1).DataPropertyName = "ContactName"
 
    dataGridView1.Columns(2).Name = "Country"
    dataGridView1.Columns(2).HeaderText = "Country"
    dataGridView1.Columns(2).DataPropertyName = "Country"
 
    Me.BindGrid(1)
EndSub
 
Public Sub BindGrid(ByVal startIndex As Integer)
    Using entities As NORTHWINDEntities = New NORTHWINDEntities()
        Dim customers As List(Of Customer) = (From customer In entities.Customers _
                                              Select customer) _
                                              .OrderBy(Function(customer) customer.CustomerID) _
                                              .Skip((startIndex - 1) * PageSize) _
                                              .Take(PageSize).ToList()
        dataGridView1.DataSource = customers
        Me.PopulatePager(entities.Customers.Count(), startIndex)
    End Using
End Sub
 
 
Populating the Pager
The PopulatePager method accepts the count of the total records present in the Table and the current PageIndex.
Then, some calculations are done to find the first and the last page of the pager and then a list of possible pages is generated by adding objects of the Page class to the Generic List collection.
Finally, a loop is executed and for each Page present in the collection, its corresponding dynamic Button control is added to the Panel control.
Note: For more details about creating dynamic controls in Windows Applications, please refer my article, Add Dynamic Button controls Click event handlers in Windows Forms (WinForms) Application.
 
Each dynamic Button is assigned a click event handler, when the Button is clicked the value of its Name is passed as PageIndex parameter to the BindGrid function, which populates the DataGridView with the new set of records.
C#
private void PopulatePager(int recordCount, int currentPage)
{
    List<Page> pages = new List<Page>();
    int startIndex, endIndex;
    int pagerSpan = 5;
 
    //Calculate the Start and End Index of pages to be displayed.
    double dblPageCount = (double)((decimal)recordCount / Convert.ToDecimal(PageSize));
    int pageCount = (int)Math.Ceiling(dblPageCount);
    startIndex = currentPage > 1 && currentPage + pagerSpan - 1 < pagerSpan ? currentPage : 1;
    endIndex = pageCount > pagerSpan ? pagerSpan : pageCount;
    if (currentPage > pagerSpan % 2)
    {
        if (currentPage == 2)
        {
            endIndex = 5;
        }
        else
        {
            endIndex = currentPage + 2;
        }
    }
    else
    {
        endIndex = (pagerSpan - currentPage) + 1;
    }
 
    if (endIndex - (pagerSpan - 1) > startIndex)
    {
        startIndex = endIndex - (pagerSpan - 1);
    }
 
    if (endIndex > pageCount)
    {
        endIndex = pageCount;
        startIndex = ((endIndex - pagerSpan) + 1) > 0 ? (endIndex - pagerSpan) + 1 : 1;
    }
 
    //Add the First Page Button.
    if (currentPage > 1)
    {
        pages.Add(new Page { Text = "First", Value = "1" });
    }
 
    //Add the Previous Button.
    if (currentPage > 1)
    {
        pages.Add(new Page { Text = "<<", Value = (currentPage - 1).ToString() });
    }
 
    for (int i = startIndex; i <= endIndex; i++)
    {
        pages.Add(new Page { Text = i.ToString(), Value = i.ToString(), Selected = i == currentPage });
    }
 
    //Add the Next Button.
    if (currentPage < pageCount)
    {
        pages.Add(new Page { Text = ">>", Value = (currentPage + 1).ToString() });
    }
 
    //Add the Last Button.
    if (currentPage != pageCount)
    {
        pages.Add(new Page { Text = "Last", Value = pageCount.ToString() });
    }
 
    //Clear existing Pager Buttons.
    pnlPager.Controls.Clear();
 
    //Loop and add Buttons for Pager.
    int count = 0;
    foreach (Page page in pages)
    {
        Button btnPage = new Button();
        btnPage.Location = new System.Drawing.Point(38 * count, 5);
        btnPage.Size = new System.Drawing.Size(35, 20);
        btnPage.Name = page.Value;
        btnPage.Text = page.Text;
        btnPage.Enabled = !page.Selected;
        btnPage.Click += new System.EventHandler(this.Page_Click);
        pnlPager.Controls.Add(btnPage);
        count++;
    }
}
 
private void Page_Click(object sender, EventArgs e)
{
    Button btnPager = (sender as Button);
    this.BindGrid(int.Parse(btnPager.Name));
}
 
public class Page
{
    public string Text { get; set; }
    public string Value { get; set; }
    public bool Selected { get; set; }
}
 
VB.Net
Private Sub PopulatePager(ByVal recordCount As Integer, ByVal currentPage As Integer)
    Dim pages As List(Of Page) = New List(Of Page)()
    Dim startIndex, endIndex As Integer
    Dim pagerSpan As Integer = 5
    Dim dblPageCount As Double = CDbl((CDec(recordCount) / Convert.ToDecimal(PageSize)))
    Dim pageCount As Integer = CInt(Math.Ceiling(dblPageCount))
    startIndex = If(currentPage > 1 AndAlso currentPage + pagerSpan - 1 < pagerSpan, currentPage, 1)
    endIndex = If(pageCount > pagerSpan, pagerSpan, pageCount)
 
    If currentPage > pagerSpan Mod 2 Then
 
        If currentPage = 2 Then
            endIndex = 5
        Else
            endIndex = currentPage + 2
        End If
    Else
        endIndex = (pagerSpan - currentPage) + 1
    End If
 
    If endIndex - (pagerSpan - 1) > startIndex Then
        startIndex = endIndex - (pagerSpan - 1)
    End If
 
    If endIndex > pageCount Then
        endIndex = pageCount
        startIndex = If(((endIndex - pagerSpan) + 1) > 0, (endIndex - pagerSpan) + 1, 1)
    End If
 
    If currentPage > 1 Then
        pages.Add(New Page With {
            .Text = "First",
            .Value = "1"
        })
    End If
 
    If currentPage > 1 Then
        pages.Add(New Page With {
            .Text = "<<",
            .Value = (currentPage - 1).ToString()
        })
    End If
 
    For i As Integer = startIndex To endIndex
        pages.Add(New Page With {
            .Text = i.ToString(),
            .Value = i.ToString(),
            .Selected = i = currentPage
        })
    Next
 
    If currentPage < pageCount Then
        pages.Add(New Page With {
            .Text = ">>",
            .Value = (currentPage + 1).ToString()
        })
    End If
 
    If currentPage <> pageCount Then
        pages.Add(New Page With {
            .Text = "Last",
            .Value = pageCount.ToString()
        })
    End If
 
    pnlPager.Controls.Clear()
    Dim count As Integer = 0
 
    ForEach page As Page In pages
        Dim btnPage As Button = New Button()
        btnPage.Location = New System.Drawing.Point(38 * count, 5)
        btnPage.Size = New System.Drawing.Size(35, 20)
        btnPage.Name = page.Value
        btnPage.Text = page.Text
        btnPage.Enabled = Not page.Selected
        AddHandler btnPage.Click, New System.EventHandler(AddressOf Me.Page_Click)
        pnlPager.Controls.Add(btnPage)
        count += 1
    Next
End Sub
 
Private Sub Page_Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim btnPager As Button = (TryCast(sender, Button))
    Me.BindGrid(Integer.Parse(btnPager.Name))
End Sub
 
Public Class Page
    Public Property Text As String
    Public Property Value As String
    Public Property Selected As Boolean
End Class
 
 
Screenshot
Paging using Skip and Take functions in LINQ using C# and VB.Net
 
 
Downloads