Back-End

3 fev, 2017

Xamarin Forms – MVVM, DataBinding e a interface ICommand – Parte 03

Publicidade

Neste artigo, vou apresentar os principais conceitos sobre MVVM, DataBinding e da interface ICommand: como passar parâmetros para um comando.

Até o momento, já sabemos como executar ações na ViewModel a partir da View usando a interface ICommand. Mas e se você precisar passar informações da View para métodos definidos via ICommand na ViewModel? É isso que irei abordar neste artigo.

Pois bem, já vimos que para definir comandos usamos a interface ICommand, e que as classes Command e Command<T> fornecidas pelo Xamarin.Forms implementam a interface ICommand, onde T é o tipo dos argumentos para Execute e CanExecute.

Assim, vimos que dentro de um ViewModel, deve haver um objeto do tipo Command ou Command<T> para cada propriedade pública na ViewModel do tipo ICommand.

O construtor de Command ou Command<T> requer um objeto Action de retorno, que é chamado quando o botão chama o método ICommand.Execute.

Então, como podemos passar um parâmetro para um Command?

Um parâmetro pode ser passado para um método ICommand.Execute usando a classe Command <T> para instanciar o comando. Nada melhor que um exemplo prático para entender como isso funciona.

Vamos criar uma aplicação que calcula a raiz quadrada de um valor que será passado para o comando como um parâmetro.

Recursos usados: Visual Studio Community 2015

Nota: Baixe e use a versão Community 2015 do VS; ela é grátis e é equivalente a versão Professional.

Passando parâmetros para um comando: criando o projeto e definindo a View e a ViewModel

Abra o Visual Studio Community 2015 e clique em New Project. Selecione Visual C#, o template Cross Plataform e, a seguir, o Blank App (Xamarin.Forms Portable).

Informe o nome XF_ParametrosCommand e clique no botão OK. Agora, crie no projeto as pastas Views e ViewModels que irão conter a View e a ViewModel.

A seguir, inclua na pasta Views a página RaizQuadradaPage.xaml que vai representar a View da nossa aplicação. Já no menu Project, clique em Add New Item e, a seguir, em Cross Platform e em Forms Xaml Page e informe o nome RaizQuadradaPage.xaml.

Antes de prosseguir, abra o arquivo App.cs e altere o código do construtor conforme abaixo:

public App()
        {
            // The root page of your application
           MainPage = new NavigationPage(new RaizQuadradaPage());
        }

Assim, definimos a nossa página como a principal.

Vamos criar uma classe em nosso projeto, na pasta ViewModels, que irá conter o código responsável pela criação e apresentação da view.

No menu Project, clique em Add Class e informe o nome RaizQuadradaViewModel.

Definindo o código da ViewModel

Agora precisamos definir na ViewModel as propriedades e métodos necessários para criar a nossa view, que vai precisar informar um número, ter um botão de comando que, ao ser clicado, irá disparar uma ação para realizar o cálculo da raiz quadrada e deverá exibir o resultado.

Assim, para criar essa view, vamos precisar definir a propriedade para tratar com o resultado do cálculo e um comando para executar uma ação do usuário.

  • A propriedade RaizQuadradaResultado que irá receber o resultado do cálculo da raiz quadrada;
  • Um comando RaizQuadradaCommand que irá realizar o cálculo da raiz quadrada.

Além disso, a nossa ViewModel vai precisar implementar a interface INotifyPropertyChanged para notificar a View das alterações.

Então, o código da classe RaizQuadradaViewModel deve ficar assim:

using System;
using System.ComponentModel;
using System.Windows.Input;
using Xamarin.Forms;
namespace XF_ParametroCommand.ViewModels
{
    public class RaizQuadradaViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var changed = PropertyChanged;
            if (changed != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public double RaizQuadradaResultado { get; private set; }
        public ICommand RaizQuadradaCommand { get; private set; }
        public RaizQuadradaViewModel()
        {
            RaizQuadradaCommand = new Command<string>(CalculaRaizQuadrada);
        }
        void CalculaRaizQuadrada(string valor)
        {
            double numero = Convert.ToDouble(valor);
            RaizQuadradaResultado = Math.Sqrt(numero);
            OnPropertyChanged("RaizQuadradaResultado");
        }
    }
}

Você percebeu que o número que será informado pelo usuário na view está sendo passado como parâmetro para o nosso Command definido na ViewModel?

Isso é feito na instanciação do comando no construtor da classe ViewModel:

RaizQuadradaCommand = new Command<string>(CalculaRaizQuadrada);

Estamos definindo o Command<T>, onde T é a string que representa o valor informando pelo usuário na View que iremos criar a seguir.

Na implementação do comando – CalculaRaizQuadrada -, recebemos o valor como string, convertemos para double, calculamos o valor da raiz quadrada e notificamos a view das alterações:

void CalculaRaizQuadrada(string valor)
 {
 double numero = Convert.ToDouble(valor);
 RaizQuadradaResultado = Math.Sqrt(numero);
 OnPropertyChanged("RaizQuadradaResultado");
 }

Definindo o código da View

Agora, abra o arquivo RaizQuadradaPage.xaml na pasta Views e inclua o código abaixo:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XF_ParametroCommand.Views.RaizQuadradaPage"
             Title="Raiz Quadrada">
    <StackLayout Padding="5">
    
        <StackLayout Orientation="Horizontal">
            <Label Text="Digite um número:" FontSize="Large" />
            <Entry x:Name="txtNumero" 
                      WidthRequest="100" 
                      FontSize="Large" />
        </StackLayout>
        <Button Text="Calcular a Raiz Quadrada" 
                HorizontalOptions="Center"
                Command="{Binding RaizQuadradaCommand}"
                CommandParameter="{Binding Source={x:Reference txtNumero}, Path=Text}" />
        <Frame BackgroundColor="Yellow">
           <StackLayout Orientation="Horizontal">
              <Label Text="Raiz Quadrada =" FontSize="Large" />
              <Label Text="{Binding RaizQuadradaResultado}" FontSize="Large"/>
           </StackLayout>
        </Frame>
    </StackLayout>
</ContentPage>

Vamos entender o código:

Estamos usando o StackLayout para empilhar as views na página definindo o layout que é mostrado na figura acima.

Definimos a view Entry, onde atribuímos o nome txtNumero ao atributo x:Name, pois vamos precisar informar para o parâmetro usando no comando de onde vem o valor informado.

No Button, definimos duas propriedades usando o databinding:

Command : Command="{Binding RaizQuadradaCommand}"

Aqui estamos vinculando o comando RaizQuadradaCommand definido na ViewModel ao Button de forma que, quando ele for clicado, esse comando será acionado;

CommandParameter: CommandParameter="{Binding Source={x:Reference txtNumero}, Path=Text}"

Aqui estamos configurando o parâmetro que será passado para o Command (o Text da view Entry) usando o CommandParameter do Button.

Para isso, estou informando o identificador da View – txtNumero – de onde vem o parâmetro e o valor que queremos passar, que é o – Text – desta view que foi definida no Path.

Antes de executar o projeto, temos que vincular a ViewModel com a View e podemos fazer isso definindo uma instância da ViewModel, atribuindo-a ao BindingContext da ContentPage no code-behind.

Abra o arquivo RaizQuadradaPage.xaml.cs e definda o código abaixo:

    public partial class RaizQuadradaPage : ContentPage
    {
        public RaizQuadradaPage()
        {
            InitializeComponent();
            this.BindingContext = new RaizQuadradaViewModel();
        }
    }

Agora, é só alegria!

Executando o projeto, iremos obter:

Dessa forma, vimos como passar parâmetros para comandos criados na ViewModel usando a interface ICommand.

Pegue o código das views e da ViewModel aqui: XF_ParametroCommand.zip