This article has been localized into Portuguese by the community.
Usando comandos do WPF
No artigo anterior, discutimos muita teoria sobre o que são comandos e como eles funcionam. Neste capítulo, veremos como você realmente usa os comandos, atribuindo-os aos elementos da interface do usuário e criando ligações de comando que os vinculem.
Vamos começar com um exemplo muito simples:
<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");
}
}
}
Definimos uma ligação de comando na janela, adicionando-a à coleção CommandBindings. Nós especificamos esse comando que desejamos usar (o comando Novo dos ApplicationCommands), bem como dois manipuladores de eventos. A interface visual consiste em um único botão, ao qual anexamos o comando usando a propriedade Command.
Em Code-behind, lidamos com os dois eventos. O manipulador CanExecute, que o WPF chamará quando o aplicativo estiver ocioso para ver se o comando específico está disponível no momento, é muito simples para este exemplo, pois queremos que esse comando específico fique disponível o tempo todo. Isso é feito definindo a propriedade CanExecute dos argumentos do evento como true.
O manipulador Executed simplesmente mostra uma caixa de mensagem quando o comando é invocado. Se você executar a amostra e pressionar o botão, você verá esta mensagem. Uma coisa a notar é que este comando tem um atalho de teclado padrão definido, que você obtém como um bônus adicional. Em vez de clicar no botão, você pode tentar pressionar Ctrl+N no teclado - o resultado é o mesmo.
Usando o método CanExecute
No primeiro exemplo, implementamos um evento CanExecute que simplesmente retornou true, para que o botão estivesse disponível o tempo todo. No entanto, isso não é verdade para todos os botões - em muitos casos, você deseja que o botão seja ativado ou desativado dependendo de algum tipo de estado em seu aplicativo.
Um exemplo muito comum disso é a alternância de botões para usar a Área de Transferência do Windows, onde você deseja que os botões Recortar e Copiar somente sejam ativados quando o texto é selecionado e o botão Colar somente seja habilitado quando o texto estiver presente na área de transferência. Isso é exatamente o que vamos realizar neste exemplo:
<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();
}
}
}
Então, temos essa interface muito simples com alguns botões e um controle TextBox. O primeiro botão irá cortar a área de transferência e o segundo irá colar a partir dela.
Em Code-behind, temos dois eventos para cada botão: um que executa a ação real, cujo nome termina com _Executed e, em seguida, os eventos CanExecute. Dentro Em cada um deles, você verá que eu aplico alguma lógica para decidir se a ação pode ou não ser executada e, em seguida, atribuí-la ao valor de retorno CanExecute no EventArgs.
O legal disso é que você não precisa chamar esses métodos para atualizar seus botões - o WPF faz isso automaticamente quando o aplicativo tem um momento inativo, garantindo que a interface permaneça atualizada o tempo todo.
Comportamento padrão de comando e CommandTarget
Como vimos no exemplo anterior, o manuseio de um conjunto de comandos pode levar a um pouco de código, com muitas declarações de método e uma lógica muito padrão. É provavelmente por isso que a equipe do WPF decidiu lidar com isso para você. De fato, poderíamos ter evitado todo o Code-behind no exemplo anterior, porque um TextBox do WPF pode manipular automaticamente comandos comuns como Recortar, Copiar, Colar, Desfazer e Refazer.
O WPF faz isso manipulando os eventos Executed e CanExecute para você, quando um controle de entrada de texto como o TextBox tem foco. Você está livre para substituir esses eventos, que é basicamente o que fizemos no exemplo anterior, mas se você quiser apenas o comportamento básico, poderá deixar o WPF conectar os comandos e o controle TextBox e fazer o trabalho para você. Basta ver o quanto este exemplo é mais simples:
<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>
Nenhum código code-behind necessário para este exemplo - o WPF lida com tudo isso para nós, mas apenas porque queremos usar esses comandos específicos para esse controle específico. O TextBox faz o trabalho para nós.
Observe como eu uso as propriedades CommandTarget nos botões para vincular os comandos ao nosso controle TextBox. Isso é necessário neste exemplo em particular, porque o WrapPanel não manipula o foco da mesma maneira, por exemplo. uma Barra de Ferramentas ou um Menu, mas também faz muito sentido dar aos comandos um alvo.
Resumo
Lidar com comandos é bastante simples, mas envolve uma marcação extra e código. A recompensa é especialmente óbvia quando você precisa invocar a mesma ação de vários lugares, ou quando você usa comandos internos que o WPF pode manipular completamente para você, como vimos no último exemplo.