Passa ai contenuti principali

VB.NET : GridView con paginazione selezionata dall'utente

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

Post popolari in questo blog

VB.NET : Aggregare stringhe con LINQ

Tip facile facile, ma a qualcuno potrebbe servire. Supponiamo di avere una lista di stringhe (magari come risultato di una query LINQ) e di voler ottenere una stringa con la concatenazione delle stesse: Dim list = CreateList() Dim concatStr = (From s In list _ Select s).Aggregate( Function (currentString, nextString) currentString + nextString) MessageBox.Show(concatStr) Il metodo CreateList non ci interessa, in questo momento, ma crea una lista di oggetti String. Protected Function CreateList() As IEnumerable( Of String ) Dim list As String () = {" stringa1 ", " stringa2 ", " stringa3 ", " stringa4 ", " stringa5 "} Return list.AsEnumerable() End Function Questo metodo potrebbe restituire una qualsiasi lista di oggetti di cui, nella select successiva recuperiamo solo stringhe. La stessa tecnica è utilizzabile per concatenare stringhe inserendovi un carattere separatore Dim list = CreateList() Dim

VB.NET: SplashScreen con effetto fade-in

In questo post vorrei proporvi un modo per realizzare una splash screen per le nostre applicazioni Windows Form che appare progressivamente con un effetto fade. Supponiamo di avere il nostro progetto VB.NET in una soluzione Visual Studio 2008 in cui abbiamo il sorgente della nostra applicazione Windows Form. Inseriamo una splash screen utilizzando il menù Progetto->Aggiungi Nuovo Elemento e selezionando il tipo di elemento “Schermata Iniziale” A questo punto Visual Studio creerà, automaticamente, la schermata iniziale che possiamo personalizzare graficamente come vogliamo. Per poter fare in modo che questa finestra appaia nel momento in cui avviamo l’applicazione, è necessario aprire le proprietà del progetto e impostare la maschera di avvio: In questo modo, all’avvio dell’applicazione, la schermata appare immediatamente e scompare un attimo prima della visualizzazione della finestra dell’applicazione. Possiamo far apparire la schermata iniziale con un ef

VB.NET: Convertire un file DOC in RTF e PDF con office interop

In questo post vorrei proporvi del codice per poter convertire un file .doc in un file .rtf oppure .pdf utilizzando le API di interoperabilità di Office. Creeremo una classe, DocConverter, che esporrà le due funzionalità sopra citate. Cominciamo con il prevedere un attributo privato della classe che rappresenterà l’applicazione Word che utilizzeremo per la conversione. Creeremo l’istanza dell’attributo privato all’interno del costruttore della classe: Public Sub New () If Not CreateWordApp() Then Throw New ApplicationException(" Assembly di interoperabilità con Office non trovato! ") End If End Sub Private _wordApp As Word.ApplicationClass Protected Function CreateWordApp() As Boolean Dim retval = True Try _wordApp = New Word.ApplicationClass() _wordApp.Visible = False Catch ex As System.Exception _wordApp = Nothing retval = False End Try Return retval End Function La conve