This article has been localized into Italian by the community.
Utilizzare i comandi WPF
Nel precedente articolo, abbiamo discusso molto di teoria su quali comandi ci sono e come funzionano. In questo capitolo, esamineremo come effettivamente utilizzare i comandi, assegnandoli agli elementi dell'interfaccia utente e creando i binding che li collegano tutti insieme.
Inizieremo con un esempio molto semplice:
<Window x:Class="WpfTutorialSamples.Commands.UsingCommandsSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="UsingCommandsSample" Height="100" Width="200">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.New" Executed="NewCommand_Executed" CanExecute="NewCommand_CanExecute" />
</Window.CommandBindings>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Command="ApplicationCommands.New">New</Button>
</StackPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
namespace WpfTutorialSamples.Commands
{
public partial class UsingCommandsSample : Window
{
public UsingCommandsSample()
{
InitializeComponent();
}
private void NewCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("The New command was invoked");
}
}
}
Definiamo un binding di comando sulla Window, aggiungendolo alla sua raccolta CommandBindings. Specifichiamo il comando che vogliamo usare (il comando New da ApplicationCommands), oltre a due gestori di eventi. L'interfaccia visiva è costituita da un singolo pulsante, al quale assegniamo il comando per utilizzare la proprietà Command .
Nel Code-behind, gestiamo i due eventi. Il gestore CanExecute , che WPF chiamerà quando l'applicazione è inattiva per vedere se lo specifico comando è attualmente disponibile, è molto semplice per questo esempio, poiché vogliamo che questo particolare comando sia sempre disponibile. Questo è fatto impostando la proprietà CanExecute degli argomenti dell'evento su true.
Il gestore Executed mostra semplicemente una finestra di messaggio quando viene richiamato il comando. Se esegui l'esempio e premi il pulsante, vedrai questo messaggio. Una cosa da notare è che questo comando ha una scorciatoia da tastiera predefinita, che ottieni come bonus aggiuntivo. Invece di fare clic sul pulsante, puoi provare a premere Ctrl + N sulla tastiera - il risultato è lo stesso.
Utilizzare il metodo CanExecute
In questo primo esempio, abbiamo implementato l'evento CanExecute che semplicemente restituisce sempre true, quindi il bottone sarà sempre disponibile. Ma non può essere sempre true per tutti i bottoni, in molti casi vuoi che un bottone sia abilitato o disabilitato a seconda di un particolare stato della tua applicazione.
Un esempio molto comune di questa commutazione dei bottoni è quando si utilizza la Clipboard di Windows , dove vuoi che i bottoni Taglia e Copia siano abilitati solo quando il testo è selezionato, e il bottone Incolla solo quando è presente del testo nella Clipboard. Questo è esattamente quello che andremo a realizzare nel seguente esempio:
<Window x:Class="WpfTutorialSamples.Commands.CommandCanExecuteSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CommandCanExecuteSample" Height="200" Width="250">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Cut" CanExecute="CutCommand_CanExecute" Executed="CutCommand_Executed" />
<CommandBinding Command="ApplicationCommands.Paste" CanExecute="PasteCommand_CanExecute" Executed="PasteCommand_Executed" />
</Window.CommandBindings>
<DockPanel>
<WrapPanel DockPanel.Dock="Top" Margin="3">
<Button Command="ApplicationCommands.Cut" Width="60">_Cut</Button>
<Button Command="ApplicationCommands.Paste" Width="60" Margin="3,0">_Paste</Button>
</WrapPanel>
<TextBox AcceptsReturn="True" Name="txtEditor" />
</DockPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
namespace WpfTutorialSamples.Commands
{
public partial class CommandCanExecuteSample : Window
{
public CommandCanExecuteSample()
{
InitializeComponent();
}
private void CutCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = (txtEditor != null) && (txtEditor.SelectionLength > 0);
}
private void CutCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
txtEditor.Cut();
}
private void PasteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = Clipboard.ContainsText();
}
private void PasteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
txtEditor.Paste();
}
}
}
Quindi, abbiamo questa semplice interfaccia con una coppia di bottoni e una TextBox. Il primo bottone taglierà il testo e le metterà negli appunti mentre il secondo lo incollerà.
Nel codice, abbiamo due eventi per ogni bottone: uno che esegue l'azione reale, il cui nome finisce con _Executed, e poi l'evento CanExecute. In ognuno di essi, vedrà che ho applicato un pò di logica per decidere se eseguirlo o no e quindi assegnarla al valore di ritorno CanExecute su EventArgs.
La cosa bella di questo è che tu non devi chiamare tutti questi metodi per avere il tuo bottone aggiornato. WPF lo fa automaticamente quando l'applicazione ha un momento di inattività, assicurandoti che l'interfaccia rimarrà aggiornata tutto il tempo.
Comportamento dei comandi di default e CommandTarget
Come abbiamo visto nell'esempio precedente, la gestione di un insieme di comandi può portare a dover scrivere un bel po 'di codice, con molte dichiarazioni di metodo e una logica molto standard. Questo è probabilmente il motivo per cui il team WPF ha deciso di gestirlo per te. In effetti, avremmo potuto evitare tutti i Code-behind nell'esempio precedente, perché un TextBox WPF può gestire automaticamente comandi comuni come Taglia, Copia, Incolla, Annulla e Ripristina.
WPF lo fa gestendo gli eventi Executed e CanExecute per te, quando un controllo di input del testo come il TextBox ha il focus. Sei libero di scavalcare questi eventi, che è fondamentalmente ciò che abbiamo fatto nell'esempio precedente, ma se vuoi solo il comportamento di base, puoi lasciare che WPF connetta i comandi ed il controllo TextBox, e fa il lavoro per te. Guarda quanto è più semplice questo esempio:
<Window x:Class="WpfTutorialSamples.Commands.CommandsWithCommandTargetSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CommandsWithCommandTargetSample" Height="200" Width="250">
<DockPanel>
<WrapPanel DockPanel.Dock="Top" Margin="3">
<Button Command="ApplicationCommands.Cut" CommandTarget="{Binding ElementName=txtEditor}" Width="60">_Cut</Button>
<Button Command="ApplicationCommands.Paste" CommandTarget="{Binding ElementName=txtEditor}" Width="60" Margin="3,0">_Paste</Button>
</WrapPanel>
<TextBox AcceptsReturn="True" Name="txtEditor" />
</DockPanel>
</Window>
Nessun codice code-behind necessario per questo esempio: WPF si occupa di tutto questo per noi, ma solo perché vogliamo utilizzare questi comandi specifici per questo specifico controllo. Il TextBox fa il lavoro per noi.
Nota come utilizzo le proprietà CommandTarget sui pulsanti, per associare i comandi al nostro controllo TextBox. Questo è richiesto in questo un esempio particolare, poiché WrapPanel non gestisce il focus nello stesso modo di come farebbe ad es. una barra degli strumenti o un menu, ma è anche molto sensato dare un bersaglio al comando .
Sommario
Trattare con i comandi è piuttosto semplice, ma implica un po 'di markup e codice in più. La ricompensa è particolarmente ovvia quando è necessario invocare la stessa azione da più posti, o quando si usano comandi integrati che WPF può gestire completamente per te, come abbiamo visto nell'esempio precedente.