Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I paginate a WPF DataGrid?

People also ask

How do I filter DataGrid?

To filter items in a DataGridAdd a handler for the CollectionViewSource. Filter event. In the Filter event handler, define the filtering logic. The filter will be applied every time the view is refreshed.

How do I add a DataGrid toolbox?

Right Click the Toolbox. Select "Choose Items...". In the WPF Components Tab, in the Filter Textbox type DataGrid. From there you can add it to the Toolbox.

How do I import data from Excel to WPF DataGrid?

How to import the data from excel to WPF DataGrid (SfDataGrid)? You can read the data from Excel using IWorkSheet. ExportDataTable method and convert the data to a DataTable collection in WPF DataGrid (SfDataGrid). You can then set the DataTable collection as ItemsSource of SfDataGrid.

Can user add rows DataGrid WPF?

WPF DataGrid (SfDataGrid) provides built-in row called AddNewRow. It allows user to add a new row to underlying collection.


The code project article above is quite good for getting this done with ADO tables. While for most applications, it is likely to work great, and is easy to understand, there is a more "WPF-zen-like" way to do it as well, and that would be using CollectionViews. The advantage of using a CollectionView compared to the example above is that it is a bit more general in terms of what data you're putting in your grid (not that you can't make that example more general), and it fits in well with the general WPF databinding model. It gives you a place to support common operations like sorting, grouping, etc, if you need those.

I put together a very short example of a barely working PagingCollectionView bound to the .NET 4.0 DataGrid control. While the example itself is pretty trivial, it shows you at least how to get started, as you have a proxy around the actual collection of data on which you can execute simple operations like MoveToNextPage and MoveToPreviousPage.

Here's the C# for both the Window event handling and the PagingCollectionView:

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;

namespace GridPagingExample
{
    public partial class MainWindow : Window
    {
        private readonly PagingCollectionView _cview;

        public MainWindow()
        {
            InitializeComponent();
            this._cview = new PagingCollectionView(
                new List<object>
                {
                    new { Animal = "Lion", Eats = "Tiger" },
                    new { Animal = "Tiger", Eats =  "Bear" },
                    new { Animal = "Bear", Eats = "Oh my" },
                    new { Animal = "Wait", Eats = "Oh my isn't an animal" },
                    new { Animal = "Oh well", Eats = "Who is counting anyway" },
                    new { Animal = "Need better content", Eats = "For posting on stackoverflow" }
                },
                2
            );
            this.DataContext = this._cview;
        }

        private void OnNextClicked(object sender, RoutedEventArgs e)
        {
            this._cview.MoveToNextPage();
        }

        private void OnPreviousClicked(object sender, RoutedEventArgs e)
        {
            this._cview.MoveToPreviousPage();
        }
    }

    public class PagingCollectionView : CollectionView
    {
        private readonly IList _innerList;
        private readonly int _itemsPerPage;

        private int _currentPage = 1;

        public PagingCollectionView(IList innerList, int itemsPerPage)
            : base(innerList)
        {
            this._innerList = innerList;
            this._itemsPerPage = itemsPerPage;
        }

        public override int Count
        {
            get 
            { 
                if (this._innerList.Count == 0) return 0;
                if (this._currentPage < this.PageCount) // page 1..n-1
                {
                    return this._itemsPerPage;
                }
                else // page n
                {
                    var itemsLeft = this._innerList.Count % this._itemsPerPage;
                    if (0 == itemsLeft)
                    {
                        return this._itemsPerPage; // exactly itemsPerPage left
                    }
                    else
                    {
                        // return the remaining items
                        return itemsLeft;
                    }
                }
            }
        }

        public int CurrentPage
        {
            get { return this._currentPage; }
            set
            {
                this._currentPage = value;
                this.OnPropertyChanged(new PropertyChangedEventArgs("CurrentPage"));
            }
        }

        public int ItemsPerPage { get { return this._itemsPerPage; } }

        public int PageCount
        {
            get 
            { 
                return (this._innerList.Count + this._itemsPerPage - 1) 
                    / this._itemsPerPage; 
            }
        }

        private int EndIndex
        {
            get
            {
                var end = this._currentPage * this._itemsPerPage - 1;
                return (end > this._innerList.Count) ? this._innerList.Count : end;
            }
        }

        private int StartIndex
        {
            get { return (this._currentPage - 1) * this._itemsPerPage; }
        }

        public override object GetItemAt(int index)
        {
            var offset = index % (this._itemsPerPage); 
            return this._innerList[this.StartIndex + offset];
        }

        public void MoveToNextPage()
        {
            if (this._currentPage < this.PageCount)
            {
                this.CurrentPage += 1;
            }
            this.Refresh();
        }

        public void MoveToPreviousPage()
        {
            if (this._currentPage > 1)
            {
                this.CurrentPage -= 1;
            }
            this.Refresh();
        }
    }
}

Here's the XAML for the window:

<Window x:Class="GridPagingExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Grid.Row="0">
            <Label Grid.Row="0" Margin="2">
                <Label.Content>
                    <Binding Path="CurrentPage">
                        <Binding.StringFormat>Current Page: {0}</Binding.StringFormat>
                    </Binding>
                </Label.Content>
            </Label>
            <Button Content="Next" Click="OnNextClicked" Margin="2"/>
            <Button Content="Previous" Click="OnPreviousClicked" Margin="2"/>
        </StackPanel>
        <DataGrid ItemsSource="{Binding}" Grid.Row="1">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Animal" Width="*" Binding="{Binding Animal}"/>
                <DataGridTextColumn Header="Eats" Width="*" Binding="{Binding Eats}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

You could build out this CollectionView to support more functionality, some trivial, like MoveToLastPage and MoveToFirstPage, and some that will take some more thought about how you want it to behave, such as sorting. Hope it is helpful.