WPF - Usando o mecanismo de Comandos (Commanding)


O WPF possui um recurso chamado Commanding que eu vou traduzir como mecanismo de Comando e que vou abordar neste artigo.

Primeiro eu vou dar uma introdução teórica sobre o assunto e depois mostrar como usar. Espero que seja útil.

O mecanismo de Comando no WPF é um mecanismo de entrada no WPF que fornece a manipulação de entrada em um nível semântico. As operações de Copiar , Recortar e Colar são exemplos de comandos que podem ser encontrados em muitos aplicativos.

O sistema de Comando no WPF esta baseado nas classes RoutedCommand e RoutedEvent que implementam a interface ICommand.

O mecanismo de Comando no WPF é algo parecido com eventos, visto que eles são baseados em ações do usuário na interface; um comando pode ser disparado como um evento, como um evento Click por exemplo, mas a diferença é que os comandos são construídos de uma forma que torna muito fácil expor a mesma funcionalidade para muitos lugares na interface sem ter que duplicar código.

O que torna os Comandos WPF diferente de um simples manipulador de eventos anexado a um botão ou um timer é que os comandos separam a semântica e a origem de uma ação de sua lógica. E, como eu já disse, isso permite a múltiplas fontes distintas invocar a mesma lógica de comando e permite que a mesma lógica de comando seja personalizada para diferentes alvos.

A maneira mais simples para usar um comando WPF é :

- usar uma das classes RoutedCommand predefinidas da biblioteca de classes de comando;
- usar um controle que tenha suporte nativo para manipular o comando;
- e usar um controle que tenha suporte nativo para invocar um comando;

Para aplicar os quesitos acima podemos definir um Comando Paste para um TextBox em um MenuItem pois:

- O comando Paste é um dos comandos predefinidos na classe ApplicationCommands;
- O controle TextBox foi construído na lógica para manipular o comando Paste;
- E a classe MenuItem possui suporte nativo para chamar comandos;

O exemplo a seguir mostra como configurar um MenuItem de modo que quando ele for clicado ele chamará o comando Paste em um TextBox, supondo que o TextBox tenha o foco de teclado.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>

O modelo de comando no WPF pode ser dividido em quatro conceitos básicos:

Os Comandos em WPF são criados por implementar a interface ICommand. A interface ICommand expõe métodos Execute e CanExecute e um evento, CanExecuteChanged, onde temos:

- Execute - Executa as ações que estão associadas com o comando;
- CanExecute - Determina se o comando pode Executar no seu atual destino;
- CanExecuteChanged - É gerado se o gerente do comando que centraliza as operações de comando detectar uma alteração no comando Origem que pode invalidar um comando que foi gerado, mas ainda não foi executado pela ligação de comando.

Criando uma aplicação WPF com Comandos

Vamos criar uma aplicação WPF usando o mecanismo de Comando para executar as operações de Copiar, Colar e Recortar para ilustrar a teoria acima.

Eu estou usando o Visual Studio 2010 Beta 2 para criar uma aplicação do tipo WPF Application com o nome wpf_Comandos;

A seguir inclua o seguinte código no arquivo MainWindow.xaml;

<Window x:Class="SimpleTextEditor.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="Usando Commands WPF" Height="321" Width="339">
    <Window.Resources>
        <Style TargetType="{x:Type Button}" x:Key="textBoxCommands">
            <Setter Property="Content" Value=
         "{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}" />
            <Setter Property="CommandTarget" Value="{Binding ElementName=textBox}" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Grid.Row="0">
            <Button Command="Cut" Style="{StaticResource textBoxCommands}" />
            <Button Command="Copy" Style="{StaticResource textBoxCommands}" />
            <Button Command="Paste" Style="{StaticResource textBoxCommands}" />
            <Button Command="AlignCenter" Style="{StaticResource textBoxCommands}" />
            <Button Command="AlignLeft" Style="{StaticResource textBoxCommands}" />
            <Button Command="AlignRight" Style="{StaticResource textBoxCommands}" />
            <Button Command="Undo" Style="{StaticResource textBoxCommands}" />
        </StackPanel>
        <RichTextBox Grid.Row="1" Name="textBox" 
       HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
    </Grid>
</Window>

Na figura abaixo vemos o resultado do código no descritor WPF;

O que temos aqui é essencialmente um conjunto de botões , controles Button, que operam em um controle RichTextBox usando o mecanismo de Comandos WPF;

Isso é tudo que é preciso para implementar os comandos, não há a necessidade de código adicional;

Observe que temos duas propriedades importantes que estão sendo definidas em cada um dos botões:

1-) Command - especifica qual comando será executado quando o botão for clicado. Existem duas formas de fazer esta declaração, a forma acima abreviada Command="Paste", ou a forma mais extensa Command ="{x:Static ApplicationCommands.Paste}" (que irei mostrar em outro exemplo)

A forma abreviada somente pode ser usada para os comandos pré-construídos, pois o WPF conhece onde eles estão. No exemplo os comandos Cut, Copy, Paste e Undo estão na classe ApplicationCommands e os comandos AlignCenter, AlignLeft e AlignRight estão na classe EditingCommands. (Existem outros comandos nas classes NavigationCommands, MediaCommands e ComponentCommands.)

2-) CommandTarget - especifica qual elemento o comando irá executar. No caso do exemplo , o alvo é sempre o TextBox. Se o comando alvo não for definido o comando não vai funcionar.

Dessa forma basta rodar a aplicação e usar os comandos no texto do controle RichtextBox;

Vou criar outro exemplo para mostrar como usar a declaração mais extensa para Command e CommandTarget.

No menu Project Selecione Add Window e selecione Window(WPF) e aceite o nome Window1.xaml;

A seguir inclua o código abaixo no arquivo Window1.xaml entre as tags <Grid>;

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Usando Comandos WPF" Height="301" Width="358">
    <Grid>
            <Button x:Name="btnCopiar" Height="23" Content="Copiar" 
                    Command="ApplicationCommands.Copy" CommandTarget="{Binding ElementName=txtDados}"
                    HorizontalAlignment="Left" Margin="31,25,0,0" VerticalAlignment="Top" Width="75" />
            <Button x:Name="btnRecortar" Height="23" Content="Recortar" 
                    Command="ApplicationCommands.Cut" CommandTarget="{Binding ElementName=txtDados}"
                    HorizontalAlignment="Left" Margin="121,25,0,0" VerticalAlignment="Top" Width="75" />
            <Button x:Name="btnColar" Height="23" Content="Colar" 
                    Command="ApplicationCommands.Paste" CommandTarget="{Binding ElementName=txtDados}"
                    HorizontalAlignment="Left" Margin="221,25,0,0" VerticalAlignment="Top" Width="75" />
            <TextBox x:Name="txtDados" Margin="31,54,31,30" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible" />
    </Grid>
</Window>

O resultado no descritor XAML deverá ser o seguinte:

Executando o projeto iremos obter:

Basta selecionar o texto a aplicar os comandos que vai funcionar...

Pegue o projeto completo aqui: wpf_Commands.zip (Lembre-se que você precisa do VS2010 beta 2 para abrir o projeto)

Eu sei é apenas WPF , mas eu gosto...

Referências:


José Carlos Macoratti