Uma das primeiras dúvidas que surgem quando estamos utilizando MVVM é como mapear eventos da View para o ViewModel sem utilizar o code-behind. Há várias maneiras de se fazer isso e vamos explorar algumas delas neste post.

Para começar, crie uma aplicação em branco (Windows Phone Application).

1. Utilizando MvvmLight EventToCommand

Instale Mvvmlight em sua aplicação via nuget:

PM> install-package mvvmlight

O pacote do mvvmlight, além das suas dlls, já adiciona várias classes que vamos precisar em nosso exemplo. Vamos começar configurando o MainViewModel como DataContext da MainPage, assim temos para onde apontar nossos comandos. Adicione essa linha no cabeçalho da MainPage.xaml:

DataContext="{Binding Source={StaticResource Locator}, Path=Main}"

Dê um play para verificar se não há nenhum erro e vamos adicionar nosso comando. Abra o MainViewModel e modifique-o para que fique desta forma (não precisa modificar os “usings”):

 1: public class MainViewModel : ViewModelBase {
 2:  
 3:     public ICommand MostreMensagemCommand { get; set; }
 4:  
 5:     public MainViewModel() {
 6:         MostreMensagemCommand = new RelayCommand<string>(MostreMensagem);
 7:     }
 8:  
 9:     public void MostreMensagem(string mensagem) {
 10:         MessageBox.Show(mensagem);
 11:     }
 12: }

Na linha 3 estamos expondo o comando que deve ser chamado de nossa interface. Este comando simplesmente recebe um delegate para o método que realmente queremos invocar: MostreMensagem.

Agora abra o arquivo MainPage.xaml e modifique o grid “ContentPanel” para ficar assim:

 1: <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
 2:     <Button Content="Click me!">
 3:         <i:Interaction.Triggers>
 4:             <i:EventTrigger EventName="Click">
 5:                 <cmd:EventToCommand 
 6:                         Command="{Binding MostreMensagemCommand}" 
 7:                         CommandParameter="Hello Mvvmlight!"/>
 8:             </i:EventTrigger>                    
 9:         </i:Interaction.Triggers>
 10:     </Button>
 11: </Grid>

Não esqueça de adicionar também os namespaces:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP71" 

Veja que estamos utilizando um trigger que vai disparar quando o botão for clicado, chamando o comando MostreMensagemCommand presente no DataContext da View (no caso nosso MainViewModel) e por fim executando o nosso método MostreMensagem.

Dê play na aplicação e clique no botão para ver nossa mensagem:

HelloMvvmLight

Simples, não? Agora vamos ver como se faz isso usando puramente EventTriggers do Blend.

2. Utilizando o Blend InvokeCommandAction

Como o MvvmLight utiliza a dll do Blend System.Windows.Interactivity, ela já está adicionada em seu projeto se você seguiu os passos anteriores.

Esta mesma dll possui um trigger quase idêntico ao EventToCommand do Mvvmlight, chamado InvokeCommandAction. Para usá-lo, basta alterar o código do seu grid ContentPanel:

 1: <!--ContentPanel - place additional content here-->
 2: <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
 3:     <Button Content="Click me!">
 4:         <i:Interaction.Triggers>
 5:             <i:EventTrigger EventName="Click">
 6:                 <i:InvokeCommandAction
 7:                         Command="{Binding MostreMensagemCommand}"
 8:                         CommandParameter="Hello Blend!" />
 9:             </i:EventTrigger>
 10:         </i:Interaction.Triggers>
 11:     </Button>
 12: </Grid>

O funcionamento vai ser idêntico ao do mvvmlight, dê play na aplicação e veja a nova mensagem.

HelloBlend

3. Utilizando o Wp7Tools EventMapping

Apesar de gostar bastante do padrão, eu pessoalmente só utilizo comandos quando tenho que reaproveitar o mesmo comportamento em vários viewmodels.

Como a maioria das vezes eu criava um comando somente para repassar a execução a um método do viewmodel, sem mesmo utilizar o “CanExecute”, desenvolvi uma DependencyProperty para mapear eventos diretamente para actions.

Primeiramente, instale o Wp7Tools no seu projeto. O Wp7Tools é o framework que utilizo em todas as minhas aplicações e tem principalmente helpers para aumentar a testabilidade das mesmas. Você pode baixá-lo via nuget:

PM> install-package wp7tools
Adicione o namespace na MainPage:
xmlns:wp7="clr-namespace:Wp7Tools.Commands;assembly=Wp7Tools" 

E modifique o grid “ContentPanel” para ficar assim:

 1: <!--ContentPanel - place additional content here-->
 2: <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
 3:     <Button Content="Click me!">
 4:         <wp7:Events.Mappings>
 5:             <wp7:Map Event="Click" ToMethod="MostreMensagem" WithParam="Hello Wp7Tools!" />
 6:         </wp7:Events.Mappings>
 7:     </Button>
 8: </Grid>
 

O uso é simples, leia a linha 5 como: mapeie o evento “Click” para o método “MostreMensagem” com parâmetro “Hello Wp7Tools”.

HelloWp7Tools

E só isso. Você pode até apagar o MostreMensagemCommand do ViewModel que nem o usaremos mais, o mapeamento vai direto para o método MostreMensagem no MainViewModel. Bem menos código, não?

Por:

André Carlucci
@andrecarlucci
www.andrecarlucci.com

Categorias: artigos
Tags: , , , ,