2011-03-14 7 views
5

MVVM aşağıdaki disk belleği uygulamak için etkili bir yol göstermektedir uygulamalar, ancak (eğer disk belleği uygulamak kez gereklidir) tasnif özel uygulama MVVM takip etmez:MVVM sayfalama & sıralama MVVM P & P.</p> <p>aşağıdaki örneğe uygun bir WPF DataGrid için sıralama ve Çağrı impletmenting için yeterli bir çözüm bulunması ile mücadele ediyorum

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

Şu anda bir CollectionViewSource bağlı bir DataGrid (GroupDescriptions ve SortDescritpt ile XAML tanımladığınız

iyonlarım ViewModel'imdeki bir ObservableCollection'a bağlı. DataGrid'in sayfa başına aldığı öğelerin sayısını sınırlandırarak Paging özelliğini uyguladığınız anda, yalnızca öğelerin alt kümesini sıraladığı için, CollectionViewSource'da tanımlanan sıralamayı bozar. Çağrı ve Sıralama'yı uygulamak için MVVM altında en iyi yaklaşım nedir?

sayesinde

Aaron

cevap

12

Geçen gün ben disk belleği ile yardımcı olmak için PagingController sınıf yazdım, işte gidip:

sen biraz b kaynaklarını temizlemek zorunda kalacak (XAML

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(); 
    } 
} 

Kullanım örneği: - ecause vb onlar Prism bazı (gerçekten temel) yarar şeyler başvuru,

Kullanım örneği (ViewModel.cs codebehind) MS Kod Sözleşmeleri bazı faydalanmak - 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> 

kısa açıklaması:

Gördüğünüz gibi, ViewModel gerçekten çok şey yapmıyor. Geçerli sayfayı temsil eden öğelerin bir koleksiyonunu tutar ve Görünüm'e bir CollectionView (veri bağlama için) ve bir PagingController sergiler. Sonra tüm yaptığı, PagingController her şeyin değiştiğini belirtmesiyle, koleksiyondaki veri öğelerini (ve sonuç olarak CollectionView) günceller. Elbette bu, bir başlangıç ​​indeksi, bir sayfa boyutu ve SortDescription[], bu parametreler tarafından açıklanan veri dilimini döndüren bir yönteme ihtiyacınız olduğu anlamına gelir. Bu, iş mantığınızın bir parçası ve ben burada bunun için bir kod eklemedim.

XAML tarafında, tüm çalışmalar PagingController numaralı bağlantıya bağlanarak yapılır.Tam işlevselliği burada gösterdim (İlk/Önceki/Sonraki/Son komutları, TextBox'un CurrentPage numarasına doğrudan bağlanması ve ScrollBar'un CurrentPage'a bağlanması). Genel olarak tüm bunları aynı anda kullanamazsınız.

+0

Teşekkürler Jon, çok takdir! – Aaron

+0

Bu, yeniden boyutlandırılan (ve bu nedenle görünür elemanların miktarını değiştiren bir DataGrid için çalışır mı? –

+0

@ChrisKlepeis: Verilen gibi değil ama PageSize'e bağlanıp "PropertyChanged" için kayıt olabilirsiniz, bu yüzden göremiyorum Tabii ki çağrı cihazı etkin bir şekilde bu vakayı kapsamıyordu, bu yüzden o kadar iyi olmayacaktı, – Jon

4

Sen ViewModel tip ListCollectionView koleksiyonu özelliğini kullanın ve ona Izgara bağlamak gerekir. Bu şekilde CollectionView tanımı Görünümde değil, ViewModel'de (nerede aittir) yer almaz ve bu da ViewModel'de istediğiniz tüm manipülasyonları yapmanıza yardımcı olur (isterse sayfalama, sıralama veya filtreleme)

+2

Yanıtınız için teşekkürler Elad! – Aaron

+1

Bu harika bir cevap. Teşekkürler! –