Silverlight DataGrid – A Simple Pager Control

by Dean 11. February 2009 10:39

I love the fact that in Silverlight you can get all of your data onto the datagrid at the same time, rather than having to used a paged control in ASP.NET. However I’ve found that some users really want the data paging to remain, which means that I’ve got to roll may own DataGrid paging control.

I know there are a few example out there, but I wanted to create a control that was a simple as possible but covered all of the major bases – so as little ‘code-behind’ as possible, and all the styling done in Blend.

So this is what I came up with:

Screenshot

 

pagergrid

 

Here’s the XAML

 

<Grid x:Name="LayoutRoot" Background="White" Width="Auto" 
      Height="Auto" HorizontalAlignment="Left" VerticalAlignment="Top" 
      Margin="10,10,10,10">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" 
                    VerticalAlignment="Top">
        <TextBlock Text="Page 1 of 10 (Total 100 items)" x:Name="Total" 
                    HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <TextBlock Text="Page Size" Margin="10,0,0,0" 
                    HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <ComboBox Name="PageSize" SelectionChanged="PageSizeChanged" 
                    Margin="3,3,3,3" HorizontalAlignment="Center" 
                    VerticalAlignment="Center" />
    </StackPanel>
    <data:DataGrid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                    DataContext="{Binding Mode=OneWay, 
                        Source={StaticResource PersonCollectionDS}}" 
                    ItemsSource="{Binding}" x:Name="MainGrid" 
                    CanUserSortColumns="False" Grid.Row="1" />
    <Border Margin="0,3,0,3" Padding="5,5,5,5" BorderBrush="Gray" 
                    BorderThickness="1,1,1,1" Grid.Row="2">
        <StackPanel Height="Auto" HorizontalAlignment="Center" 
                    VerticalAlignment="Top" Width="Auto" x:Name="Pager" 
                    Orientation="Horizontal">
            <Button Content="&lt;&lt;" Margin="0,0,3,0" x:Name="FirstButton" 
                    Click="GoFirst"/>
            <Button Content="&lt;" Margin="0,0,3,0" x:Name="BackButton" 
                    Click="GoBack"/>
            <TextBlock Text="Page" Margin="3,0,0,0" HorizontalAlignment="Center" 
                    VerticalAlignment="Center"/>
            <ComboBox Name="PageSelector" Margin="3,0,0,0" 
                      SelectionChanged="PageChanged"/>
            <Button Content="&gt;" Margin="3,0,0,0" 
                    x:Name="ForwardButton" Click="GoForward"/>
            <Button Content="&gt;&gt;" Margin="3,0,0,0"
                    x:Name="LastButton" Click="GoLast"/>
        </StackPanel>
    </Border>
</Grid>

 

And Here’s the code-behind

 

public partial class Page : UserControl
{
    private readonly PersonCollection masterCollection = 
        new PersonCollection();
    private int pageSize = 10;
    private int currentPage;
    private int maxPage;
 
    public Page()
    {
        InitializeComponent();
        Loaded += PageLoaded;
    }
 
    private void PageLoaded(object sender, RoutedEventArgs e)
    {
        // this line just creates test data - ignore;
        masterCollection.BuildTestData(1000,1000);
 
        masterCollection.CollectionChanged += (s, a) => SetPageData();
        SetPageSize();
        PageSize.ItemsSource = new List<int>(new[] {10, 25, 50});
        PageSize.SelectedIndex = 0;
        SetPageData();
    }
 
    private void SetPageSize()
    {
        maxPage = (int)Math.Ceiling((double)masterCollection.Count 
            / (double)pageSize);
        for (var i = 1; i <= maxPage; i++)
            PageSelector.Items.Add(i);
    }
 
    private void SetPageData()
    {
        MainGrid.DataContext = masterCollection
            .OrderBy(p => p.Name)
            .Skip(pageSize * currentPage)
            .Take(pageSize);
        BackButton.IsEnabled = FirstButton.IsEnabled = currentPage > 0;
        ForwardButton.IsEnabled = LastButton.IsEnabled = 
            currentPage+1 < maxPage;
        Total.Text = string.Format("Page {0} of {1} (Total : {2})", 
            currentPage+1, maxPage, masterCollection.Count);
        PageSelector.SelectedIndex = currentPage;
    }
 
    private void GoBack(object sender, RoutedEventArgs e)
    {
        currentPage--;
        SetPageData();
    }
 
    private void GoForward(object sender, RoutedEventArgs e)
    {
        currentPage++;
        SetPageData();
    }
 
    private void GoLast(object sender, RoutedEventArgs e)
    {
        currentPage = maxPage-1;
        SetPageData();
    }
 
    private void GoFirst(object sender, RoutedEventArgs e)
    {
        currentPage = 0;
        SetPageData();
    }
 
    private void PageChanged(object sender, 
        SelectionChangedEventArgs e)
    {
        currentPage = (int)PageSelector.SelectedItem-1;
        SetPageData();
    }
 
    private void PageSizeChanged(object sender, 
        SelectionChangedEventArgs e)
    {
        pageSize = (int) PageSize.SelectedItem;
        currentPage = 0;
        SetPageSize();
        SetPageData();
    }
}

 

As you can see, it’s pretty simple stuff.

Because the Silverlight DataGrid doesn't expose the built-in column sorting events, implementing sorting on the columns is a little more tricky – you’d have to re-template the headers and include a button who’s click event can invoke a custom sorting algorithm, which would be easy enough to implement should you want.

Any comments ? let me know.

(Source Files Below)

DemoPager.zip

Dean

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

DataBinding | Silverlight

Comments

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading



Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010 ButtonChrome.com