TOC

This article has been localized into Portuguese by the community.

Comandos:

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.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!