Xamarin Forms - MVVM, DataBinding e a interface ICommand - II


  Neste artigo vou apresentar os principais conceitos sobre MVVM, DataBinding e da interface ICommand : Implementando o MVVM e definindo um comando

Na primeira parte do artigo apresentei os conceitos sobre o MVVM, databinding e ICommand e criei uma aplicação bem simpes sem usar o padrão MVVM. Vamos agora implementar o MVVM. aplicar o databinding e definir o comando usando a interface ICommand.

Até o momento a nossa aplicação possui o seguinte desenho, onde vemos que a lógica de apresentação esta no code-behind, e, temos assim um forte acoplamento entre a View e o Model:

Nosso objetivo neste artigo é implementar o padrão MVVM criando a ViewModel, e assim separar a lógica de apresentação do code-behind:

Recursos usados:

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

Implementando MVVM e definindo um Comando 

Abra o projeto criado no artigo anterior no Visual Studio Community 2015.

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

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

Precisamos definir nesta classe as propriedades e métodos necessários para criar a nossa view.

Se analisarmos a nossa view veremos que vamos precisar definir duas propriedades:

  1. A propriedade Nome que irá receber o nome informado pelo usuário;
  2. A propriedade Mensagem que irá exibir a mensagem de boas vindas;

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

    public class MainPageViewModel 
    {
        //propriedade para o nome
        public string Nome { get; set; }
        //propriedade para a mensagem
        public string Mensagem {get; set; }        
    }

Mas perceba que a nossa view possui também um botão com um evento definido no code-behind que ao ser disparado monta a mensagem e a exibe na Label.

Precisamos então definir em nossa ViewModel um comando que irá atuar da mesma forma.

É aqui que entra a interface ICommand e a classe Command.

Veja como fica a implementação de um comando que será disparado quando o usuário clicar no botão definido na view:

    public class MainPageViewModel 
    {
        //propriedade para o nome
        public string Nome { get; set; }
        //propriedade para a mensagem
        public string Mensagem {get; set; }        
        public ICommand BoasVindasCommand { get; private set; }
        public MainPageViewModel()
        {
            BoasVindasCommand = new Command(BoasVindasCmd);
        }
        void BoasVindasCmd()
        {
            Mensagem = "Bem-Vindo " + Nome;
        }
    }

Vamos entender o código:

1 - Primeiro definimos uma propriedade do tipo ICommand:

  public ICommand BoasVindasCommand { get; private set; }

2 - Depois criamos uma instância da classe Command onde definimos um delegate que aponta para classe BoasVindasCmd e que irá implementa o nosso comando

  BoasVindasCommand = new Command(BoasVindasCmd);

3 - Finalmente implementamos o nosso comando:

 Mensagem = "Bem-Vindo " + Nome;

Nota: Uma forma mais simplificada de implementar o comando seria assim:

        public Command BoasVindasCommand
        {
            get
            {
                return new Command(() =>
                {
                    Mensagem = "Bem-Vindo " + Nome;
                });
            }
        }

Aplicando o DataBinding

Muito bem. Agora podemos alterar a nossa view e aplicar o DataBinding.

Primeiro temos que definir como a nossa View vai se comunicar com a nossa ViewModel. Fazemos isso no arquivo code-behind MainPage.xaml.cs definindo o código a seguir:

       public MainPage()
        {
            InitializeComponent();
            this.BindingContext = new MainPageViewModel();
        }

Criamos uma instância da nossa ViewModel e atribuímos ao BindingContext da ContentPage. Assim podemos aplicar o databinding na view.

Nota: Poderíamos ter feito essa referência no código XAML.

Veja como ficou a nossa view MainPage  após aplicarmos o databinding:

<?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_Apps.AppMvvm1.Views.MainPage">    
    <StackLayout Spacing="20" VerticalOptions="Center" 
                 HorizontalOptions="Center">
        <Label Text="Xamarin Forms - MVVM" TextColor="Navy" 
               FontSize="20"/>
        <Entry Text="{Binding Nome}" Placeholder="Informe o nome" 
               FontSize="20" />
        <Button Text="Boas Vindas" TextColor="White" 
                BackgroundColor="Teal" 
                FontSize="20"
                Command="{Binding BoasVindasCommand}" />
        <Label Text="{Binding Mensagem}" FontSize="30" 
               TextColor="Red" 
               FontAttributes="Bold" />
    </StackLayout>    
</ContentPage >

Note que removemos os atributos x:Name das Labels e o evento Clicked do Button pois não vamos mais precisar deles.

A seguir implementamos o databinding vinculando a View às propriedades Nome e Mensagem e ao comando BoasVindasCommand:

  1. Text="{Binding Nome}"

  2. Text="{Binding Mensagem}"

  3.  Command="{Binding BoasVindasCommand}"

Dessa forma podemos remover o evento Clicked que havíamos definido no arquivo code-behind.

Se você executar o projeto neste momento vai ficar surpreso ao ver que ao clicar no botão a mensagem não será exibida na Label.

Porquê ?

Se você definir um breakpoint no comando definido na ViewModel irá constatar que a mensagem esta sendo montada mas não esta sendo exibida.

O motivo disso é que a view não foi notificada da alteração da mensagem, ou seja, a propriedade Mensagem foi alterada mas a view não foi notificada.

Precisamos de alguma forma notificar a view das alterações que ocorrerem nas propriedades definidas na ViewModel.

Para cumprir esse papel precisamos implementar a interface INotifyPropertyChanged em nossa ViewModel e alterar a definição da propriedade Mensagem para que ela notifique a view de qualquer alteração feita.

Vamos então fazer isso alterando o código da nossa ViewModel conforme mostrado a seguir:

     public class MainPageViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void Notificar([CallerMemberName] string prop = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
        }
        //propriedade para o nome
        public string Nome { get; set; }      
        //propriedade para a mensagem
        private string _mensagem;
        public string Mensagem
        {
            get { return _mensagem; }
            set
            {
                _mensagem = value;
                Notificar();
            }
        }
        public ICommand BoasVindasCommand { get; private set; }
        public MainPageViewModel()
        {
            BoasVindasCommand = new Command(BoasVindasCmd);
        }
        void BoasVindasCmd()
        {
            Mensagem = "Bem-Vindo " + Nome;
        }
    }

Agora, qualquer alteração na propriedade Mensagem irá disparar o evento para notificar a View que irá exibir a mensagem.

Executando o projeto iremos obter:

Agora, após a implementação da interface INotifyPropertyChanged,  a nossa view esta sendo notificada da alteração da propriedade Mensagem e exibe a mensagem na Label- lblMensagem.

Na próxima parte do artigo veremos como passar parâmetros para métodos na ViewModel.

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

"Verdadeiramente ele (Jesus) tomou sobre si as nossas enfermidades, e as nossas dores levou sobre si; e nós o reputávamos por aflito, ferido de Deus, e oprimido."
Isaías 53:4

Referências:


José Carlos Macoratti