Come posso impostare il paging in un wpf DataGrid
?Come posso impaginare un DataGrid WPF?
risposta
L'articolo di progetto di codice sopra è abbastanza buono per ottenere questo fatto con tabelle ADO. Mentre per la maggior parte delle applicazioni, è probabile che funzioni alla grande, ed è facile da capire, c'è anche un modo più "WPF-zen-like" per farlo, e che utilizzerebbe CollectionViews. Il vantaggio di usare CollectionView rispetto all'esempio sopra è che è un po 'più generico in termini di dati che stai inserendo nella tua griglia (non che non puoi rendere quell'esempio più generale), e si adatta bene con il modello di base dati WPF generale. Ti dà un posto per supportare operazioni comuni come l'ordinamento, il raggruppamento, ecc., Se ne hai bisogno.
Ho messo insieme un brevissimo esempio di PagingCollectionView che funziona a fatica associato al controllo DataGrid di .NET 4.0. Anche se l'esempio in sé è piuttosto banale, ti mostra almeno come iniziare, dato che hai un proxy attorno alla raccolta effettiva di dati su cui puoi eseguire operazioni semplici come MoveToNextPage e MoveToPreviousPage.
Ecco il C# sia per la gestione degli eventi della finestra e il 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();
}
}
}
Ecco il codice XAML per la finestra:
<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>
Si potrebbe costruire questo CollectionView per supportare più funzionalità, un po ' banale, come MoveToLastPage e MoveToFirstPage, e alcuni che prenderanno ancora un po 'di pensiero su come si desidera che si comporti, come l'ordinamento. Spero che sia utile
Inoltre, Silverlight ha uno di questi: http://msdn.microsoft.com/en -us/library/system.windows.data.pagedcollectionview (v = vs.95) .aspx, quindi considerare questo con Reflector potrebbe anche essere un esempio molto utile da cui partire. In bocca al lupo! – timmyl
+100 uomo! Grazie!!!! –
Questo codice sembra perdere una parte cruciale: come rendere il datagrid solo mostrare ItemsPerPage invece di tutti gli elementi, giusto? – newman
Controllare questo [post] (http://www.codeproject.com/KB/WPF/WPF_Paging.aspx) nella codeproject – Shoban