2009-04-24 3 views

ответ

49

Вышеупомянутая статья проекта кода неплохо для того, чтобы сделать это с помощью таблиц ADO. В то время как для большинства приложений это, вероятно, будет работать отлично, и это легко понять, есть еще один способ «WPF-zen-like», и это будет использовать CollectionViews. Преимущество использования CollectionView по сравнению с приведенным выше примером состоит в том, что он немного более общий с точки зрения того, какие данные вы помещаете в свою сетку (не то, что вы не можете сделать этот пример более общим), и он хорошо вписывается с общей моделью привязки данных WPF. Это дает вам возможность поддерживать общие операции, такие как сортировка, группировка и т. Д., Если вам это нужно.

Я собрал очень короткий пример едва работающего PagingCollectionView, связанного с элементом управления DataGrid .NET 4.0. Хотя сам пример довольно тривиален, он показывает, по крайней мере, как начать работу, поскольку у вас есть прокси-сервер вокруг фактического набора данных, на котором вы можете выполнять простые операции, такие как MoveToNextPage и MoveToPreviousPage.

Вот C# и для обработки событий окна и 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(); 
     } 
    } 
} 

Вот XAML для окна:

<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> 

Вы могли бы построить эту CollectionView поддерживать больше функциональных возможностей, некоторые тривиальным, как MoveToLastPage и MoveToFirstPage, а некоторые из них подумают о том, как вы себя ведете, например, сортировка. Надеюсь, это полезно.

+1

Кроме того, Silverlight имеет одно из следующих: http://msdn.microsoft.com/ru -us/library/system.windows.data.pagedcollectionview (v = vs.95) .aspx, поэтому просмотр этого с помощью Reflector также может быть очень полезным примером для работы. Удачи! – timmyl

+0

+100 человек! Благодаря!!!! –

+0

Этот код, кажется, пропустит важную роль: как заставить datagrid просто показать ItemsPerPage вместо всех элементов, правильно? – newman