In un vecchio articolo presente in VB T&T, vedemmo come creare un Notepad con Windows Presentation Foundation & Visual Basic 2008, introducendo il discorso degli Application Commands. Dicemmo che si tratta di comandi predefiniti che possono essere associati ai controlli dell’applicazione per eseguire operazioni “classiche” nelle applicazioni, come, per esempio, i Taglia/Copia/Incolla o Salva/Stampa.
Il tutto viene gestito da WPF attraverso l’infrastruttura dei CommandBindings, che offrono un approccio diverso della gestione dei comandi nelle applicazioni, soprattutto perchè siamo abituati a fare la considerazione: comando (menu/pulsante) -> evento Click -> esecuzione di un’azione. Tramite i CommandBindings, l’applicazione mantiene il controllo, in un’ottica tipicamente managed, sui comandi associati ai controlli. Vediamo subito un esempio, per capirci qualcosa di più. Riscriveremo il piccolo progetto visto in questo precedente post, per la stampa degli elementi dell’interfaccia, utilizzando i CommandBindings.
Lo XAML di esempio rimane invariato, una griglia con due righe, la prima contenente un TextBlock da stampare e la seconda un pulsante per l’esecuzione della stampa:
<Grid Name="Grid1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<TextBlock Name="TextBlock1" FontSize="26" FontWeight="Bold" Text="WPF Printing exercise" Grid.Row="0"/>
<Button Grid.Row="1" Width="100" Height="25" Content="Print me!" Name="Button1" />
</Grid>
Ora passiamo al codice Visual Basic, ma senza gestire alcun evento Click. In primo luogo, digitiamo il seguente codice (commentato, ma faremo altri commenti):
Private PrintBinding As CommandBinding
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
'Un nuovo CommandBinding
Me.PrintBinding = New CommandBinding
'Specifichiamo il tipo di comando predefinito
Me.PrintBinding.Command = ApplicationCommands.Print
'Associamo il gestore di evento Executed
AddHandler Me.PrintBinding.Executed, AddressOf PrintCommandHandler
'Aggiungiamo il nuovo comando alla collezione gestita a livello
'di applicazione
Me.CommandBindings.Add(Me.PrintBinding)
End Sub
Definiamo un oggetto chiamato PrintBinding, che è di tipo CommandBinding. Il CommandBinding collega un RoutedCommand (come quelli che andremo a utilizzare) a un gestore di evento specificato, che nel nostro caso si chiamerà PrintCommandHandler. Alla proprietà Command di questo oggetto si assegna uno degli ApplicationCommands, come ad esempio il Print che ci serve per la stampa. Infine, tramite AddHandler, specifichiamo il metodo da richiamare al verificarsi dell’evento Executed. Il nuovo CommandBinding va poi aggiunto alla collezione CommandBindings che viene gestita dall’applicazione.
Il codice del gestore di evento Executed è il seguente:
'Verrà richiamato quando l'utente fa clic sul pulsante,
'non tramite evento Click ma tramite infrastruttura CommandBindings
Private Sub PrintCommandHandler(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
Dim pDialog As New PrintDialog
If pDialog.ShowDialog = True Then
pDialog.PrintVisual(Me, "Stampa della finestra")
End If
'per via del "bubbling" possiamo settare e.Handled = True
'e.Handled = True
End Sub
Notate l’ultimo commento: tutti i controlli hanno una loro collezione CommandBindings e questo è dovuto al fatto i comandi passano attraverso il visual tree come i routed events. Il run-time va a “beccare” prima i CommandBindings nella collezione del controllo, poi quelli al livello superiore. Si può interrompere questo processo di bubbling impostando la proprietà Handled del tipo ExecutedRoutedEventArgs su True.
Vi basterà mandare in esecuzione l’applicazione per ottenere lo stesso risultato della scorsa volta, ma con un approccio decisamente migliore e vantaggioso.
Il codice sorgente a corredo di questo post è disponibile in area Download di VB T&T a questo indirizzo.
Alessandro