2009-04-24 8 views

Respuesta

49

El artículo de proyecto de código anterior es bastante bueno para hacer esto con las tablas ADO. Si bien para la mayoría de las aplicaciones, es probable que funcione muy bien, y sea fácil de entender, también hay una forma más similar a "WPF-zen" para hacerlo, y eso sería usando CollectionViews. La ventaja de usar un CollectionView en comparación con el ejemplo anterior es que es un poco más general en términos de qué datos está poniendo en su grilla (no es que no pueda hacer ese ejemplo más general), y encaja bien con el modelo general de enlace de datos de WPF. Le brinda un lugar para respaldar operaciones comunes como clasificar, agrupar, etc., si las necesita.

Puse a punto un ejemplo muy breve de una PagingCollectionView que apenas funciona, unida al control .NET 4.0 DataGrid. Si bien el ejemplo en sí es bastante trivial, al menos te muestra cómo comenzar, ya que tienes un proxy alrededor de la colección real de datos en la que puedes ejecutar operaciones simples como MoveToNextPage y MoveToPreviousPage.

Aquí está el C#, tanto para el manejo de eventos de ventanas y la 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(); 
     } 
    } 
} 

Aquí está el XAML para la ventana:

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

Se puede construir un vistazo a este CollectionView para apoyar una mayor funcionalidad, algunos triviales, como MoveToLastPage y MoveToFirstPage, y algunas que le darán más importancia a la forma en que desea que se comporte, como la ordenación. Espero que sea útil.

+1

Además, Silverlight tiene uno de estos: http://msdn.microsoft.com/en -us/library/system.windows.data.pagedcollectionview (v = vs.95) .aspx, por lo que ver eso con Reflector también podría ser un ejemplo muy útil para trabajar fuera de. ¡Buena suerte! – timmyl

+0

+100 hombre! ¡¡¡¡Gracias!!!! –

+0

Este código parece omitir una parte crucial: cómo hacer que la cuadrícula de datos solo muestre ItemsPerPage en lugar de todos los elementos, ¿verdad? – newman

Cuestiones relacionadas