2011-03-14 10 views
5

ja stara się znalezienie odpowiedniego rozwiązania impletmenting sortowania i przywoławcza dla siatki danych WPF które odpowiada MVVM P & P.MVVM przywoławczy i sortowania

Poniższy przykład ilustruje skutecznego sposobu wprowadzania stronicowania, która następuje MVVM praktyki, ale realizacja niestandardowych sortowania (co jest wymagane raz zaimplementować stronicowania) nie wynika MVVM:

http://www.eggheadcafe.com/tutorials/aspnet/8a2ea78b-f1e3-45b4-93ef-32b2d802ae17/wpf-datagrid-custom-pagin.aspx

obecnie mam DataGrid związany z CollectionViewSource (zdefiniowane w XAML z GroupDescriptions i SortDescritpt jony) związane z ObservableCollection w moim ViewModel. Natychmiast po zaimplementowaniu stronicowania przez ograniczenie liczby elementów, które DataGrid pobiera na stronę, łamie ono sortowanie zdefiniowane w kolekcji CollectionViewSource, ponieważ sortuje tylko podzbiór elementów. Jakie jest najlepsze podejście w ramach MVVM do wdrażania stronicowania i sortowania?

Dzięki,

Aaron

Odpowiedz

12

The drugi dzień napisałem klasę PagingController pomóc z stronicowania, więc proszę bardzo:

trzeba będzie posprzątać źródeł nieco b ecause do uzupe trochę wykorzystania umów MS Code one odwoływać się trochę (bardzo podstawowy) rzeczy użytkową z Prism itp

próbkę użytkowania (kodzie - 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(); 
    } 
} 

próbki Wykorzystanie (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> 

Krótkie wyjaśnienie:

Jak widać, ViewModel nie naprawdę dużo. Utrzymuje zbiór elementów stanowiących bieżącej strony i naraża CollectionView (dla wiązania danych) oraz PagingController do widoku. Wtedy wszystko robi to aktualizować elementy danych w kolekcji (a co za tym idzie w CollectionView) za każdym razem PagingController wskazuje, że coś się zmieniło. Oczywiście oznacza to, że trzeba się sposób, że dany indeks początkowy, rozmiar strony i SortDescription[] powraca plasterek danych opisanych przez tych parametrów. Jest to część logiki biznesowej i nie uwzględniłem tutaj kodu.

Na stronie XAML cała praca odbywa się poprzez wiązanie się z PagingController.Wyeksponowałem tutaj pełną funkcjonalność (przyciski powiązane z poleceniami Pierwszy/Poprzedni/Następny/Ostatni, bezpośrednie wiązanie z TextBox do i wiązanie z ScrollBar do CurrentPage). Zazwyczaj nie używasz wszystkiego w tym samym czasie.

+0

Dziękuję Jon, bardzo docenione! – Aaron

+0

Czy to działa dla DataGrid, która zmienia rozmiar (i tym samym zmienia ilość widocznych elementów?) –

+0

@ChrisKlepeis: Nie tak jak podano, ale możesz powiązać z 'PageSize' i zarejestrować się w' PropertyChanged' na nim, więc nie widzę Oczywiście pager nie miał na celu sprawnego pokrycia tej sprawy, więc perf nie będzie tak dobry, jak mógłby być. – Jon

4

Należy użyć właściwości zbierania typu ListCollectionView w ViewModel, i wiążą starcie do niego. W ten sposób definicja CollectionView nie byłaby widoczna w Widoku, lecz w ViewModelu (tam, gdzie należy), a to pomogłoby ci wykonać wszystkie manipulacje, które chcesz z łatwością w ViewModelu (czy to stronicowanie, sortowanie czy filtrowanie)

+2

Dzięki za odpowiedź Elad! – Aaron

+1

To jest świetna odpowiedź. Dzięki! –