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:
DataGridView – For displaying data.
Panel – For adding pager buttons.
Entity Framework Model
Once the
Entity Framework is configured and connected to the database table, the Model will look as shown below.
Property Class
The Class consists of following properties.
C#
public class Page
{
public string Text { get; set; }
public string Value { get; set; }
public bool Selected { get; set; }
}
VB.Net
Public Class Page
Public Property Text As String
Public Property Value As String
Public Property Selected As Boolean
End Class
Implementing Paging in DataGridView
First the value of the PageSize is set to 5.
Inside the Form Load event handler, the Name, HeaderText and DataPropertyName columns are set and the BindGrid method is called.
BindGrid
The BindGrid method accepts PageIndex as a parameter.
Inside the BindGrid method, the records are fetched from the
Customers table of Northwind database using
Entity Framework.
Then, a Generic List collection of Customer class object is created and LINQ query is executed.
The Paging is performed on the records using the Skip and Take functions.
Skip function
The Skip function accepts the Start Index from the set of records to fetched i.e. if Page Index is 1 then the Start Index will be (1 - 1) * 10 = 0.
Example: If Current Page Index is 1 and the Maximum Rows is 10, then the Start Index will be (1 - 1) * 10 = 0.
Take function
The Take function will fetch the rows based on the value of the PageSize variable.
The Generic List collection of Customer class object is assigned to the DataSource property of DataGridView.
Finally, the value of the RecordCount and PageIndex are passed to the PopulatePager method.
C#
int PageSize = 5;
private void Form1_Load(object sender, EventArgs e)
{
//Set AutoGenerateColumns False
dgvCustomers.AutoGenerateColumns = false;
//Set Columns Count
dgvCustomers.ColumnCount = 3;
//Add Columns
dgvCustomers.Columns[0].Name = "CustomerID";
dgvCustomers.Columns[0].HeaderText = "Customer Id";
dgvCustomers.Columns[0].DataPropertyName = "CustomerID";
dgvCustomers.Columns[1].HeaderText = "Contact Name";
dgvCustomers.Columns[1].Name = "Name";
dgvCustomers.Columns[1].DataPropertyName = "ContactName";
dgvCustomers.Columns[2].Name = "Country";
dgvCustomers.Columns[2].HeaderText = "Country";
dgvCustomers.Columns[2].DataPropertyName = "Country";
this.BindGrid(1);
}
public void 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();
dgvCustomers.DataSource = customers;
this.PopulatePager(entities.Customers.Count(), startIndex);
}
}
VB.Net
Private PageSize As Integer = 5
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
'Set AutoGenerateColumns False
dgvCustomers.AutoGenerateColumns = False
'Set Columns Count
dgvCustomers.ColumnCount = 3
'Add Columns
dgvCustomers.Columns(0).Name = "CustomerID"
dgvCustomers.Columns(0).HeaderText = "Customer Id"
dgvCustomers.Columns(0).DataPropertyName = "CustomerID"
dgvCustomers.Columns(1).HeaderText = "Contact Name"
dgvCustomers.Columns(1).Name = "Name"
dgvCustomers.Columns(1).DataPropertyName = "ContactName"
dgvCustomers.Columns(2).Name = "Country"
dgvCustomers.Columns(2).HeaderText = "Country"
dgvCustomers.Columns(2).DataPropertyName = "Country"
Me.BindGrid(1)
End Sub
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()
dgvCustomers.DataSource = customers
Me.PopulatePager(entities.Customers.Count(), startIndex)
End Using
End Sub
Populating the Pager
The PopulatePager method accepts the RecordCount and the current PageIndex.
Then, 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 FOR EACH loop is executed over Page class present in the collection, its corresponding dynamic Button control is added to the Panel control.
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++;
}
}
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
'Calculate the Start and End Index of pages to be displayed.
Dim dblPageCount As Double = CDbl((CDec(recordCount) / Convert.ToDecimal(PageSize)))
Dim pageCount As Integer = CInt(Math.Ceiling(dblPageCount))
startIndex = If(currentPage > 1AndAlso 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
'Add the First Page Button.
If currentPage > 1 Then
pages.Add(New Page With {
.Text = "First",
.Value = "1"
})
End If
'Add the Previous Button.
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
'Add the Next Button.
If currentPage < pageCount Then
pages.Add(New Page With {
.Text = ">>",
.Value = (currentPage + 1).ToString()
})
End If
'Add the Last Button.
If currentPage <> pageCount Then
pages.Add(New Page With {
.Text = "Last",
.Value = pageCount.ToString()
})
End If
'Clear existing Pager Buttons.
pnlPager.Controls.Clear()
'Loop and add Buttons for Pager.
Dim count As Integer = 0
For Each 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
Page Click
Each dynamic Button is assigned to a click event handler, when the Button is clicked the BindGrid method is called.
And the value of its Name is passed as PageIndex parameter which populates the DataGridView with the new set of records.
C#
private void Page_Click(object sender, EventArgs e)
{
Button btnPager = (sender as Button);
this.BindGrid(int.Parse(btnPager.Name));
}
VB.Net
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
Screenshot
Downloads