Click here to Skip to main content
15,884,592 members
Articles / Desktop Programming / WPF

WPF Pagination for DataGrid

Rate me:
Please Sign up or sign in to vote.
3.09/5 (6 votes)
15 Jun 2016CPOL2 min read 78.7K   2.5K   13   4
Add pagination to DataGrid

  

Introduction

I am new to WPF and was trying to find out if there is any built in pagination control, but to my surprise I found that there is no pagination control in WPF. I browsed a lot and finally after hours of browsing, this article came to me as a saviour (http://www.codeproject.com/Articles/20463/DataView-Paging-in-WPF). But still, I had to make a lot of changes to the code to make things work for me. So I thought of writing an article to save time for my community. So here I come with an article on WPF pagination on Datagrid.

Pagination code that I wrote is quite handy, you can use this code in other situations too. This is how my pagination control looks like:

Image 1

Background

This article is a reference to http://www.codeproject.com/Articles/20463/DataView-Paging-in-WPF. The only difference is that I have added a combobox to display the number of records and used LINQ queries.

Let's Get Started

My design is quite simple, I have used one datagrid, one label, one combobox and few buttons for designing the window.

This is how my XAML code looks like for Datagrid:

XML
<DataGrid x:Name="dataGrid" Grid.Row ="1" 
HorizontalAlignment="Left" Margin="51,32,0,0" 
VerticalAlignment="Top" AutoGenerateColumns="True"  
CanUserSortColumns="False" 
IsReadOnly="False" ColumnWidth="*" />

Here is the XAML code for the pagination controls:

Image 2

XML
<Button Height="23" HorizontalAlignment="Left"  
Name="btnFirst" VerticalAlignment="Bottom" Width="40" 
Content="&lt;&lt;" Click="btnFirst_Click" Opacity="0.75"/>
<Button Height="23"  VerticalAlignment="Bottom" 
Name="btnPrev" Width="40" Click="btnPrev_Click" 
Opacity="0.75" Content="&lt;"/>
<Label x:Name="lblpageInformation" HorizontalContentAlignment="Center" 
HorizontalAlignment="Left" Height="30" Width="100" 
VerticalContentAlignment="Center" VerticalAlignment="Bottom"/>
<Button Height="23" HorizontalAlignment="Right" 
Name="btnNext" VerticalAlignment="Bottom" Width="40" 
Content="&gt;" Click="btnNext_Click" Opacity="0.75"/>
<Button Height="23" HorizontalAlignment="Right"  
VerticalAlignment="Bottom" Width="40" Name="btnLast" 
Click="btnLast_Click" Opacity="0.75" Content="&gt;&gt;"/>
<ComboBox x:Name="cbNumberOfRecords" HorizontalAlignment="Left"  
VerticalAlignment="Bottom" Width="120"  SelectedIndex="0" 
SelectionChanged="cbNumberOfRecords_SelectionChanged" Opacity="0.75"/>

And in the code behind file, I declared the below variables and enum.

So, the value of the variable numberOfRecPerPage will be assigned from the combobox.

C#
int pageIndex = 1;
private int numberOfRecPerPage;
private enum PagingMode { First = 1, Next = 2, Previous = 3, Last = 4, PageCountChange = 5 };

I am using a model class Student with the below fields:

C#
public class Student
{
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public uint Age { get; set; }
}

This is how I randomly generated the data to populate into the data grid.

C#
private List<object> GetData()
 {
     List<object> genericList = new List<object>();
     Student studentObj;
     Random randomObj = new Random();
     for (int i = 0; i < 1000; i++)
     {
         studentObj = new Student();
         studentObj.FirstName = "First " + i;
         studentObj.MiddleName = "Middle " + i;
         studentObj.LastName = "Last " + i;
         studentObj.Age = (uint)randomObj.Next(1, 100);

         genericList.Add(studentObj);
     }
     return genericList;
 }

Here, I am binding the data to the data grid itemsource. Here, I used Linq query to display the records based on the variable numberOfRecPerPage. So suppose initially you want to display only 10 records per page, with the below code, you can achieve this:

C#
List<object> myList = GetData();
dataGrid.ItemsSource = myList.Take(numberOfRecPerPage);
int count = myList.Take(numberOfRecPerPage).Count();
lblpageInformation.Content = count + " of " + myList.Count;

How To Make Pagination Work

So on click of the pagination buttons, the Navigate method will do the magic of navigating from one page to another or from the first page to the last page. The code below is pretty simple. I have used LINQ queries to do all the magic of querying out the data based on the pagination control click.

C#
    private void Navigate(int mode)
        {
            int count;
            switch (mode)
            {
                case (int)PagingMode.Next:
                    btnPrev.IsEnabled = true;
                    btnFirst.IsEnabled = true;
                    if (myList.Count >= (pageIndex * numberOfRecPerPage))
                    {
                        if (myList.Skip(pageIndex * 
                        numberOfRecPerPage).Take(numberOfRecPerPage).Count() == 0)
                        {
                            dataGrid.ItemsSource = null;
                            dataGrid.ItemsSource = myList.Skip((pageIndex * 
                            numberOfRecPerPage) - numberOfRecPerPage).Take(numberOfRecPerPage);
                            count = (pageIndex * numberOfRecPerPage) + 
                            (myList.Skip(pageIndex * 
                            numberOfRecPerPage).Take(numberOfRecPerPage)).Count();
                        }
                        else
                        {
                            dataGrid.ItemsSource = null;
                            dataGrid.ItemsSource = myList.Skip(pageIndex * 
                            numberOfRecPerPage).Take(numberOfRecPerPage);
                            count = (pageIndex * numberOfRecPerPage) + 
                            (myList.Skip(pageIndex * 
                            numberOfRecPerPage).Take(numberOfRecPerPage)).Count();
                            pageIndex++;
                        }
                      
                        lblpageInformation.Content = count + " of " + myList.Count;                       
                    }

                    else
                    {
                        btnNext.IsEnabled = false;
                        btnLast.IsEnabled = false;
                    }

                    break;
                case (int)PagingMode.Previous:
                    btnNext.IsEnabled = true;
                    btnLast.IsEnabled = true;
                    if (pageIndex > 1)
                    {
                        pageIndex -= 1;
                        dataGrid.ItemsSource = null;
                        if (pageIndex == 1)
                        {
                            dataGrid.ItemsSource = myList.Take(numberOfRecPerPage);
                            count = myList.Take(numberOfRecPerPage).Count();
                            lblpageInformation.Content = count + " of " + myList.Count;
                        }
                        else
                        {
                            dataGrid.ItemsSource = myList.Skip
                            (pageIndex * numberOfRecPerPage).Take(numberOfRecPerPage);
                            count = Math.Min(pageIndex * numberOfRecPerPage, myList.Count);
                            lblpageInformation.Content = count + " of " + myList.Count;
                        }
                    }
                    else
                    {
                        btnPrev.IsEnabled = false;
                        btnFirst.IsEnabled = false;
                    }
                    break;

                case (int)PagingMode.First:
                    pageIndex = 2;
                    Navigate((int)PagingMode.Previous);
                    break;
                case (int)PagingMode.Last:
                    pageIndex = (myList.Count / numberOfRecPerPage);
                    Navigate((int)PagingMode.Next);
                    break;

                 case (int)PagingMode.PageCountChange:
                    pageIndex = 1;
                    numberOfRecPerPage = Convert.ToInt32(cbNumberOfRecords.SelectedItem);
                    dataGrid.ItemsSource = null;
                    dataGrid.ItemsSource = myList.Take(numberOfRecPerPage);
                    count = (myList.Take(numberOfRecPerPage)).Count();
                    lblpageInformation.Content = count + " of " + myList.Count;
                    btnNext.IsEnabled = true;
                    btnLast.IsEnabled = true;
                    btnPrev.IsEnabled = true;
                    btnFirst.IsEnabled = true;
                    break;
            }
        }

Now my Navigate method is ready. Let's go ahead and make this work. Oh wait, we didn't call the method on button click. Here is the code to call the Navigate method from the pagination button clicks.

C#
private void btnFirst_Click(object sender, System.EventArgs e)
        {
            Navigate((int)PagingMode.First);
        }

private void btnNext_Click(object sender, System.EventArgs e)
        {
            Navigate((int)PagingMode.Next);

        }

private void btnPrev_Click(object sender, System.EventArgs e)
        {
            Navigate((int)PagingMode.Previous);

        }

private void btnLast_Click(object sender, System.EventArgs e)
        {
            Navigate((int)PagingMode.Last);
        }

private void cbNumberOfRecords_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Navigate((int)PagingMode.PageCountChange);
        }

Woohooo! All done. Let's consolidate all the code. So here is the code for XAML and code behind file.

C#

Code-behind file:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace DataGridSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        int pageIndex = 1;
        private int numberOfRecPerPage;
        //To check the paging direction according to use selection.
        private enum PagingMode 
        { First = 1, Next = 2, Previous = 3, Last = 4, PageCountChange = 5 };

        List<object> myList = new List<object>();

        public MainWindow()
        {
            InitializeComponent();
            cbNumberOfRecords.Items.Add("10");
            cbNumberOfRecords.Items.Add("20");
            cbNumberOfRecords.Items.Add("30");
            cbNumberOfRecords.Items.Add("50");
            cbNumberOfRecords.Items.Add("100");
            cbNumberOfRecords.SelectedItem = 10;
            WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
            this.Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            myList = GetData();
            dataGrid.ItemsSource = myList.Take(numberOfRecPerPage);
            int count = myList.Take(numberOfRecPerPage).Count();
            lblpageInformation.Content = count + " of " + myList.Count;
        }


        private List<object> GetData()
        {
            List<object> genericList = new List<object>();
            Student studentObj;
            Random randomObj = new Random();
            for (int i = 0; i < 1000; i++)
            {
                studentObj = new Student();
                studentObj.FirstName = "First " + i;
                studentObj.MiddleName = "Middle " + i;
                studentObj.LastName = "Last " + i;
                studentObj.Age = (uint)randomObj.Next(1, 100);

                genericList.Add(studentObj);
            }
            return genericList;
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        #region Pagination 
        private void btnFirst_Click(object sender, System.EventArgs e)
        {
            Navigate((int)PagingMode.First);
        }

        private void btnNext_Click(object sender, System.EventArgs e)
        {
            Navigate((int)PagingMode.Next);

        }

        private void btnPrev_Click(object sender, System.EventArgs e)
        {
            Navigate((int)PagingMode.Previous);

        }

        private void btnLast_Click(object sender, System.EventArgs e)
        {
            Navigate((int)PagingMode.Last);
        }

        private void cbNumberOfRecords_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Navigate((int)PagingMode.PageCountChange);
        }

        private void Navigate(int mode)
        {
            int count;
            switch (mode)
            {
                case (int)PagingMode.Next:
                    btnPrev.IsEnabled = true;
                    btnFirst.IsEnabled = true;
                    if (myList.Count >= (pageIndex * numberOfRecPerPage))
                    {
                        if (myList.Skip(pageIndex * 
                        numberOfRecPerPage).Take(numberOfRecPerPage).Count() == 0)
                        {
                            dataGrid.ItemsSource = null;
                            dataGrid.ItemsSource = myList.Skip((pageIndex * 
                            numberOfRecPerPage) - numberOfRecPerPage).Take(numberOfRecPerPage);
                            count = (pageIndex * numberOfRecPerPage) + 
                            (myList.Skip(pageIndex * 
                            numberOfRecPerPage).Take(numberOfRecPerPage)).Count();
                        }
                        else
                        {
                            dataGrid.ItemsSource = null;
                            dataGrid.ItemsSource = myList.Skip(pageIndex * 
                            numberOfRecPerPage).Take(numberOfRecPerPage);
                            count = (pageIndex * numberOfRecPerPage) + 
                            (myList.Skip(pageIndex * numberOfRecPerPage).Take(numberOfRecPerPage)).Count();
                            pageIndex++;
                        }
                      
                        lblpageInformation.Content = count + " of " + myList.Count;                       
                    }

                    else
                    {
                        btnNext.IsEnabled = false;
                        btnLast.IsEnabled = false;
                    }

                    break;
                case (int)PagingMode.Previous:
                    btnNext.IsEnabled = true;
                    btnLast.IsEnabled = true;
                    if (pageIndex > 1)
                    {
                        pageIndex -= 1;
                        dataGrid.ItemsSource = null;
                        if (pageIndex == 1)
                        {
                            dataGrid.ItemsSource = myList.Take(numberOfRecPerPage);
                            count = myList.Take(numberOfRecPerPage).Count();
                            lblpageInformation.Content = count + " of " + myList.Count;
                        }
                        else
                        {
                            dataGrid.ItemsSource = myList.Skip
                            (pageIndex * numberOfRecPerPage).Take(numberOfRecPerPage);
                            count = Math.Min(pageIndex * numberOfRecPerPage, myList.Count);
                            lblpageInformation.Content = count + " of " + myList.Count;
                        }
                    }
                    else
                    {
                        btnPrev.IsEnabled = false;
                        btnFirst.IsEnabled = false;
                    }
                    break;

                case (int)PagingMode.First:
                    pageIndex = 2;
                    Navigate((int)PagingMode.Previous);
                    break;
                case (int)PagingMode.Last:
                    pageIndex = (myList.Count / numberOfRecPerPage);
                    Navigate((int)PagingMode.Next);
                    break;

                  case (int)PagingMode.PageCountChange:
                    pageIndex = 1;
                    numberOfRecPerPage = Convert.ToInt32(cbNumberOfRecords.SelectedItem);
                    dataGrid.ItemsSource = null;
                    dataGrid.ItemsSource = myList.Take(numberOfRecPerPage);
                    count = (myList.Take(numberOfRecPerPage)).Count();
                    lblpageInformation.Content = count + " of " + myList.Count;
                    btnNext.IsEnabled = true;
                    btnLast.IsEnabled = true;
                    btnPrev.IsEnabled = true;
                    btnFirst.IsEnabled = true;
                    break;
            }
        }

        #endregion
    }
}

XAML

Here is the XAML code:

XML
   <Window x:Class="DataGridSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DataGridSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="900">
    <Grid OpacityMask="#FF423535">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Grid.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF85BDD6" Offset="0"/>
                <GradientStop Color="#FF2F7B91" Offset="0.478"/>
                <GradientStop Color="#FF4492A8" Offset="0.973"/>
                <GradientStop Color="#FF72A6BF" Offset="0.227"/>
                <GradientStop Color="#FF2EA4C5" Offset="0.739"/>
            </LinearGradientBrush>
        </Grid.Background>
        <StackPanel Orientation="Horizontal" 
        HorizontalAlignment="Center">
            <Label Content="My Pagination Works" FontWeight="Bold" 
            FontSize="25" FontStretch="UltraExpanded" 
            BorderBrush="Black"/>
        </StackPanel>
        <DataGrid x:Name="dataGrid" Grid.Row ="1" 
        HorizontalAlignment="Left" Margin="51,32,0,0" 
        VerticalAlignment="Top" AutoGenerateColumns="True"  
        CanUserSortColumns="False" IsReadOnly="False" 
        ColumnWidth="*" />
        <Grid Grid.Row="2" >
            <StackPanel Orientation="Horizontal" 
            HorizontalAlignment="Center">
                <Button Height="23" HorizontalAlignment="Left"  
                Name="btnFirst" VerticalAlignment="Bottom" 
                Width="40" Content="&lt;&lt;" 
                Click="btnFirst_Click" Opacity="0.75"/>
                <Button Height="23"  VerticalAlignment="Bottom" 
                Name="btnPrev" Width="40" Click="btnPrev_Click" 
                Opacity="0.75" Content="&lt;"/>
                <Label x:Name="lblpageInformation" 
                HorizontalContentAlignment="Center" 
                HorizontalAlignment="Left" Height="30" 
                Width="100" VerticalContentAlignment="Center" 
                VerticalAlignment="Bottom"/>
                <Button Height="23" HorizontalAlignment="Right" 
                Name="btnNext" VerticalAlignment="Bottom" 
                Width="40" Content="&gt;" 
                Click="btnNext_Click" Opacity="0.75"/>
                <Button Height="23" HorizontalAlignment="Right"  
                VerticalAlignment="Bottom" Width="40" 
                Name="btnLast" Click="btnLast_Click" 
                Opacity="0.75" Content="&gt;&gt;"/>
                <ComboBox x:Name="cbNumberOfRecords" 
                HorizontalAlignment="Left"  VerticalAlignment="Bottom" 
                Width="120"  SelectedIndex="0" 
                SelectionChanged="cbNumberOfRecords_SelectionChanged" 
                Opacity="0.75"/>
            </StackPanel>
            <Grid Grid.Row="3">
                <StackPanel Orientation="Horizontal" 
                HorizontalAlignment="Center" Margin="412,62,430,-62">
                <Button Height="30" HorizontalAlignment="Center" 
                VerticalAlignment="Bottom" Name="btnCancel" 
                Width="50"  Opacity="0.75" 
                Content="Cancel" Click="btnCancel_Click"/>
            </StackPanel>
            </Grid>
        </Grid>
    </Grid>
</Window>

Points of Interest

I used Linq queries to query out the data and binded it to the DataGrid itemsource.

History

  • Article version 3.0

License

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


Written By
Software Developer
India India
I work for a reputed company in India. I love learning new technologies.

Comments and Discussions

 
BugYour problem is that this is not a good WPF implementation Pin
Clifford Nelson12-May-16 12:10
Clifford Nelson12-May-16 12:10 
GeneralRe: Your problem is that this is not a good WPF implementation Pin
Herman<T>.Instance15-Jun-16 21:58
Herman<T>.Instance15-Jun-16 21:58 
AnswerRe: Your problem is that this is not a good WPF implementation Pin
Clifford Nelson16-Jun-16 6:17
Clifford Nelson16-Jun-16 6:17 
SuggestionRemove binaries from download ZIP file Pin
Matt T Heffron15-Apr-16 13:32
professionalMatt T Heffron15-Apr-16 13:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.