Il altro giorno ho scritto una classe PagingController
per aiutare con paginazione, così qui si va:
si dovrà ripulire le fonti un po 'b ecause la fanno un certo uso di contratti MS codice, fanno riferimento alcune cose di utilità (veramente di base) da Prisma, ecc
campione Uso (codebehind - ViewModel.cs
):
private const int PageSize = 20;
private static readonly SortDescription DefaultSortOrder = new SortDescription("Id", ListSortDirection.Ascending);
private readonly ObservableCollection<Reservation> reservations = new ObservableCollection<Reservation>();
private readonly CollectionViewSource reservationsViewSource = new CollectionViewSource();
public ViewModel()
{
this.reservationsViewSource.Source = this.reservations;
var sortDescriptions = (INotifyCollectionChanged)this.reservationsViewSource.View.SortDescriptions;
sortDescriptions.CollectionChanged += this.OnSortOrderChanged;
// The 5000 here is the total number of reservations
this.Pager = new PagingController(5000, PageSize);
this.Pager.CurrentPageChanged += (s, e) => this.UpdateData();
this.UpdateData();
}
public PagingController Pager { get; private set; }
public ICollectionView Reservations
{
get { return this.reservationsViewSource.View; }
}
private void UpdateData()
{
var currentSort = this.reservationsViewSource.View.SortDescriptions.DefaultIfEmpty(DefaultSortOrder).ToArray();
// This is the "fetch the data" method, the implementation of which
// does not directly interest us for this example.
var data = this.crsService.GetReservations(this.Pager.CurrentPageStartIndex, this.Pager.PageSize, currentSort);
this.reservations.Clear();
this.reservations.AddRange(data);
}
private void OnSortOrderChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add) {
this.UpdateData();
}
}
campione Uso (XAML - View.xaml
):
<DataGrid ... ItemSource="{Binding Reservations}" />
<!-- all the rest is UI to interact with the pager -->
<StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="4">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="Webdings" />
<Setter Property="Width" Value="60" />
<Setter Property="Margin" Value="4,0,4,0" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="4,0,4,0" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="4,0,4,0" />
<Setter Property="Width" Value="40" />
</Style>
</StackPanel.Resources>
<Button Content="9" Command="{Binding Path=Pager.GotoFirstPageCommand}" />
<Button Content="3" Command="{Binding Path=Pager.GotoPreviousPageCommand}" />
<TextBlock Text="Page" />
<TextBox Text="{Binding Path=Pager.CurrentPage, ValidatesOnExceptions=True}" />
<TextBlock Text="{Binding Path=Pager.PageCount, StringFormat=of {0}}" />
<Button Content="4" Command="{Binding Path=Pager.GotoNextPageCommand}" />
<Button Content=":" Command="{Binding Path=Pager.GotoLastPageCommand}" />
</StackPanel>
<ScrollBar Orientation="Horizontal" Minimum="1" Maximum="{Binding Path=Pager.PageCount}" Value="{Binding Path=Pager.CurrentPage}"/>
</StackPanel>
breve spiegazione:
Come vedi, il ViewModel non fa molto. Mantiene una collezione di elementi che rappresentano la pagina corrente e espone un CollectionView
(per l'associazione dei dati) e uno PagingController
alla vista. Quindi tutto ciò che fa è aggiornare gli elementi di dati nella raccolta (e di conseguenza nello CollectionView
) ogni volta che lo PagingController
indica che qualcosa è cambiato. Ovviamente ciò significa che è necessario un metodo che, dato un indice iniziale, una dimensione di pagina e un SortDescription[]
restituisca la porzione di dati descritta da questi parametri. Questo fa parte della tua logica aziendale e non ho incluso il codice per questo qui.
Sul lato XAML tutto il lavoro viene eseguito legando allo PagingController
.Ho esposto qui le funzionalità complete (pulsanti associati ai comandi Prima/Prec/Prossima/Ultima, associazione diretta di uno TextBox
a CurrentPage
e il binding di uno ScrollBar
a CurrentPage
). In genere non lo userai allo stesso tempo.
Grazie Jon, molto apprezzato! – Aaron
Funzionerebbe per un DataGrid che si ridimensiona (e quindi modifica la quantità di elementi visibili? –
@ChrisKlepeis: non come dato ma puoi associare a 'PageSize' e iscriverti a' PropertyChanged' su di esso, quindi non vedo Ovviamente il cercapersone non è stato concepito per coprire in modo efficiente questo caso, quindi il perf non sarà il migliore possibile – Jon