When displaying large amounts of data in a custom application built on Microsoft Dynamics CRM, it can be beneficial to use paging to improve user experience and the speed of the application. WPF controls like ListViews and GridViews don’t come with a generic paging control, so it’s the developer’s responsibility to either create one or find a freely available version online.


Paging can be done simply and effectively, as you can see in our PowerGlobalSearch add-on.

Here, we’ll demonstrate how to create a generic WPF paging control that can be used in any project. We’ll cover not only how to create the control, but also how to use it as well!

First, we’ll mock up what we want the control to look like. We want something simply that can fulfill our need and be reusable later on. We’ll add the following controls:

  • ‘First Page’ button
  • ‘Next Page’ button
  • ‘Previous Page’ button
  • ‘Last Page’ button
  • A visual element showing us what our current page index is
  • A visual element showing us how many pages we have available

Heading over into Visual Studio, we can create a new solution or project and a new class library:

Getting started with WPF paging control

To our new project, we’ll add a new WPF User Control:

We’ll end up with simple looking control that looks like this:

By using the following markup:

<UserControl x:Class="PagingControl.PagingControl"
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
            <Button Name="btnFirstPage" Content="&lt;&lt;" Click="btnFirstPage_Click"/>
            <Button Name="btnPreviousPage" Content="&lt;" Click="btnPreviousPage_Click"/>
            <Label Name="lblPageIndex" Content="{Binding ElementName=root,
                Path=PageIndex, UpdateSourceTrigger=PropertyChanged}" Width="Auto"/>
            <Label Content="of"/>
            <Label Name="lblNumberOfPages" Content="{Binding ElementName=root,
                Path=NumberOfPages, UpdateSourceTrigger=PropertyChanged}" Width="Auto"/>
            <Button Name="btnNextPage" Content="&gt;" Click="btnNextPage_Click"/>
            <Button Name="btnLastPage" Content="&gt;&gt;" Click="btnLastPage_Click"/>

You can tell by looking at it that it’s a pretty simple control. You can always use custom styling or modification of the content of the buttons to get the look that you’re going for.

Now, since we’ll be keeping track of both a page index and a number of pages, we’ll need to add a couple of dependency properties and fields. We’ll jump into the code behind and add our dependencies first:

public static readonly DependencyProperty PageIndexProperty =
       DependencyProperty.Register("PageIndex", typeof(int), typeof(PagingControl));

public static readonly DependencyProperty NumberOfPagesProperty =
DependencyProperty.Register("NumberOfPages", typeof(int), typeof(PagingControl));

These dependency properties give us a way to update values on the control as they change for our data set. We’ll also create a couple of public fields so that these values can be accessed at any time from the control:

public int PageIndex
get { return Int32.Parse(GetValue(PageIndexProperty).ToString()); }
set { SetValue(PageIndexProperty, value); }

public int NumberOfPages
get { return Int32.Parse(GetValue(NumberOfPagesProperty).ToString()); }
set { SetValue(NumberOfPagesProperty, value); }

Since the setup for each of the buttons will be the same, we’ll just show how to wire one of them up. We’ll take the ‘Next Page’ button as our example. You’ll notice in our XAML that we already filled out an event name for our Click Event:

<Button Name="btnNextPage" Content="&gt;" Click="btnNextPage_Click"/>

Let’s add that event to our code behind:

private void btnLastPage_Click(object sender, RoutedEventArgs e){}

Now, what to do with this event? Well, we want to expose the event to whatever application requires it, so we’ll have to create a public event and an event handler:

public event RoutedEventHandler NextPage
add { AddHandler(NextPageClick, value); }
remove { RemoveHandler(NextPageClick, value); }

public static readonly RoutedEvent NextPageClick = EventManager.RegisterRoutedEvent(
"Next", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(PagingControl));

There! With that done, we’re now ready to create an instance of it for our data control. We’ll just mock up a simple view so you can see what it will look like:

And here’s the code behind:

<Window x:Class="SplashPOC.MainWindow"
        Title="MainWindow" Width="350" Height="200">
            <ColumnDefinition />
            <ColumnDefinition Width="115"/>
            <RowDefinition Height="30"/>
        <ListView x:Name="lstData"  Height="Auto" Width="Auto" HorizontalContentAlignment="Stretch"
                  VerticalContentAlignment="Stretch" ItemsSource="{Binding Path=BlogViewModel}"
                  AutomationProperties.Name="Blog List" SelectionMode="Single" Grid.Column="0" Grid.ColumnSpan="2">
                <GridView AllowsColumnReorder="False">
                    <GridViewColumn Header="PowerObjects">
                                <Label Content="Hello"/>
                    <GridViewColumn Header="Is"/>
                    <GridViewColumn Header="Awesome"/>
        <pc:PagingControl Name="pcPager" Grid.Column="1" Grid.Row="1"/>

You can see we’ve simply added a ListView to our Window as well added our control to the page. In our code behind, we first create a reference to the control’s assembly:


And then instantiated the control at the bottom of our page:

<pc:PagingControl Name="pcPager" Grid.Column="1" Grid.Row="1"/>

Keeping the idea of MVVM alive, we’ll now create a ViewModel that correlates to our View. We’ve created a class called PagingViewModel, but you can call it whatever you like. Your new class should inherit the INotifyPropertyChanged interface, and implement it as follows:

public class PagingViewModel : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;

Now we’ll create two private fields:

private int _numberOfPages;
private int _pageIndex;

Let’s create a method to raise our new PropertyChanged event if we change one of these values:

protected void OnPropertyChanged(string name)
var handler = PropertyChanged;
if (handler != null)
           handler(this, new PropertyChangedEventArgs(name));

Now, we can utilize the OnPropertyChanged method to fire off the event in some public access methods:

public int PageIndex
           return _pageIndex;
           _pageIndex = value;

public int NumberOfPages
           return _numberOfPages;
           _numberOfPages = value;

Now, whenever we change the value of our field, an event will be triggered to notify our control that it needs to render its appearance. All that’s left is to tie our exposed event handler on the control to an action on our ViewModel. First we’ll add the NextPage event to our XAML:

<pc:PagingControl Name="pcPager" Grid.Column="1" Grid.Row="1" NextPage="Paging_NextPage"/>

In our Paging_NextPage method, we’d then make a service call against our ViewModel that would get new data and set those fields on our ViewModel, which would in turn fire off an event telling our control to re-render. Here are some placeholders for what it might look like:

private void Paging_NextPage(object sender, RoutedEventArgs e)

On the Window control and this on the ViewModel:

public void GetData()
var dataReturned = _service.GetDataFromService();
       NumberOfPages = dataReturned.PageCount;
       PageIndex = dataReturned.PageIndex;

Now you have a working paging control that can be used for any project!

In addition to custom web applications built on Microsoft Dynamics CRM, PowerObjects helps companies and non-profit organizations build custom screens and online portals.

Happy CRM’ing!

Avatar for Joe D365

Joe D365

Joe D365 is a Microsoft Dynamics 365 superhero who runs on pure Dynamics adrenaline. As the face of PowerObjects, Joe D365’s mission is to reveal innovative ways to use Dynamics 365 and bring the application to more businesses and organizations around the world.