Sul sito della community romana del mondo .NET (www.dotnetromacesta.org) trovate un mio piccolo articolo su come realizzare un controllo ASP.NET, derivato dal controllo GridView, che permette all’utente di selezionare il numero di record da visualizzare.
Per semplicità riporto l’intero articolo rimandandovi al link di cui sopra per scaricare il file con il codice.La nostra GridView modificherà il pager della GridView originale suddividendolo in due colonne, la prima delle quali conterrà il controllo di paginazione originale (normalmente contenuto in una cella con l’attributo ColumnSpan pari al numero di colonne della griglia), mentre la seconda conterrà una label e una drop down list con i possibili valori della paginazione (recuperati da una nuova proprietà che l’utente può impostare da codice).
Creiamo, dunque una classe che chiameremo DynamicPageSizeGridView e che deriverà dalla GridView contenuta nel namespace System.Web.UI.WebControls.
Definiamo tre proprietà pubbliche:
PageSizeList : elenco dei possibili valori selezionabili dall’utente. Si tratta di una stringa composta da valori numerici separati dal carattere “;” ;
PageSelectorText : testo che comparirà al fianco del controllo di selezione del numero di record;
PageSelectorCssClass : classe di stile della cella contenente la label e la dropdown di selezione.
Tutte e tre le proprietà sfruttano il viewstate per memorizzare i valori in modo da mantenerli tra un post back ed il successivo:
Public Property PageSelectorText() As String
Get
Dim _PageSelectorText = Me.ViewState("PageSelectorText")
Return CStr(_PageSelectorText)
End Get
Set(ByVal value As String)
Me.ViewState("PageSelectorText") = value
End Set
End Property
Per creare fisicamente i controlli di gestione della paginazione, andiamo a gestire l’evento RowCreated ed in particolare ci occupiamo di agire sulla riga di tipo Pager:
Private Sub DynamicPageSizeGridView_RowCreated( _
ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
Handles Me.RowCreated
If e.Row.RowType = DataControlRowType.Pager Then
Dim pagerControl = e.Row.Cells(0).Controls(0)
e.Row.Cells(0).Controls.Clear()
e.Row.Cells(0).Controls.Add(CreatePagerTable(pagerControl))
End If
End Sub
In particolare andiamo a salvarci il controllo PagerTable che contiene il controllo di paginazione originale (che si trova nell’unica cella della riga di paginazione) e creiamo una tabella con una riga e due colonne. Nella prima di queste colonne (entrambe che occupano il 50% dello spazio) rimettiamo il paginatore originale, mentre nella seconda costruiamo i due controlli per la selezione del numero di record per pagina.
Function CreatePagerTable(ByVal pagerControl As Control) As Table
Dim table = New Table()
Dim row As New TableRow
Dim pagerCell As New TableCell
With pagerCell
.Width = Unit.Percentage(50)
.Controls.Add(pagerControl)
End With
row.Cells.Add(pagerCell)
Dim sizeCell As New TableCell
With sizeCell
.CssClass = Me.PageSelectorCssClass
.Width = Unit.Percentage(50)
Dim label = New Label()
label.Text = Me.PageSelectorText
.Controls.Add(label)
.Controls.Add(CreatePageSizeListDropDown())
End With
row.Cells.Add(sizeCell)
table.Rows.Add(row)
table.Width = Unit.Percentage(100)
Return table
End Function
Nella funzione CreatePageSizeListDropDown creiamo la dropdown per la selezione della dimensione di paginazione:
Private Function CreatePageSizeListDropDown() As DropDownList
Dim combo = New DropDownList()
combo.Items.AddRange((From s In Me.PageSizeList.Split(CChar(";")) _
Where IsNumeric(s) _
Order By s Ascending _
Distinct Select New ListItem(s, s)).ToArray())
combo.AutoPostBack = True
combo.SelectedValue = Me.PageSize.ToString()
AddHandler combo.SelectedIndexChanged, _
AddressOf Me.ComboPageSizeSelectionChanged
Return combo
End Function
Da notare l’utilizzo di LINQ per creare la lista dei valori possibili di paginazione contenuti nella proprietà PageSizeList.
Nell’evento di cambio dell’indice della dropdown effettuiamo il cambio di paginazione:
Protected Sub ComboPageSizeSelectionChanged( _
ByVal sender As Object, _
ByVal e As EventArgs)
Dim combo = CType(sender, DropDownList)
Dim selectedValue = combo.SelectedItem.Value
Me.PageSize = System.Convert.ToInt32(selectedValue)
Me.PageIndex = 0
End Sub
Recuperiamo il valore selezionato dall’utente, impostiamo il valore del PageSize e riportiamo il PageIndex a zero. Quest’ultima istruzione serve a garantire che, se ci si trova in una pagina diversa dalla prima e si seleziona una paginazione per cui esiste una sola pagina, non si abbia un errore.
A questo punto tutto sembra funzionare ma se selezioniamo una paginazione con un numero di record maggiore del numero di record totali della sorgente dati, scompare la riga di paginazione non consentendo più di cambiare il valore selezionato.
Per risolvere questo problema ci viene in aiuto un post di Ryan McDonnell(link) in cui si spiega come fare in modo di visualizzare sempre la riga di paginazione anche se il numero di record totali è minore del numero di record della pagina.
In sostanza è sufficiente implementare l’override della proprietà PageCount (utilizzata dal frame work per sapere quante pagine servono per visualizzare tutti i dati):
Public Overrides ReadOnly Property PageCount() As Integer
Get
Dim basePageCount = MyBase.PageCount
If basePageCount = 1 Then
Dim sf = New System.Diagnostics.StackFrame(1)
If sf.GetMethod().Name = "CreateChildControls" _
And sf.GetMethod().ReflectedType.Name = "GridView" Then
basePageCount += 1
End If
End If
Return basePageCount
End Get
End Property
Nel momento in cui ci si accorge che il numero di pagine necessarie per visualizzare i dati è pari ad 1 (cioè non viene visualizzata la riga di paginazione), si incrementa tale valore in modo da “ingannare” il framework e fargli , comunque, disegnare la riga di paginazione (priva del paginatore perché, effettivamente, non ci sono record su cui navigare).
In questo modo la nostra griglia è perfettamente funzionante.
Da notare che il tutto funziona sia con la paginazione lato server che con quella lato client.
Il codice sorgente è disponibile al seguente indirizzo
http://www.dotnetromacesta.org/common/articoli/aspnet/gridview/AspNet_GridView_Paginazione.aspx
Commenti