.NET MAUI - MVVM, DataBinding e a interface ICommand - III


  Vou continuar a apresentar os principais conceitos sobre MVVM, DataBinding e da interface   ICommand : Passando parâmetros para os comandos.

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 .NET MAUI 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 na prática.

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:

Passando parâmetros para um Comando

Abra o Visual Studio Community e clique em New Project;

Selecione Visual C#, o template .NET MAUI App e Informe o nome MauiCmdParametros ;

Selecione o .NET 7.0 e clique no botão Create;

Vamos criar no projeto a pasta Mvvm e nesta pasta vamos criar as pastas : Views, Models e ViewModels para organizar o código que iremos criar.

Vamos criar na pasta Views dentro da pasta Mvvm uma Content Page chamada RaizQuadradaView.xaml.

Clique com o botão direito do mouse sobre a pasta e selecione Add-> New Item

Selecione .NET MAUI e o template .NET MAUI ContentPage(XAML), informe o nome e clique em Add;

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

public partial class App : Application
{
   public App()
   {
InitializeComponent();
MainPage = new NavigationPage(new RaizQuadradaView());
   }
}

Assim definimos a nossa página RaizQuadradaView 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.

Nossa View 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.

  1. A propriedade RaizQuadradaResultado que irá receber o resultado do cálculo da raiz quadrada;
  2. 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 esta sendo passado como parâmetro para o nosso Command definido na ViewModel ?

Isso esta sendo 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");
        }

Aqui o método CalculaRaizQuadrada chama o método OnPropertyChanged(), passando o nome da propriedade, para notificar a View (a camada de apresentação) que a propriedade RaizQuadradaResultado foi atualizada, permitindo que a View exiba o novo valor da raiz quadrada na tela.

Definindo o código da View

Abra o arquivo RaizQuadradaView.xaml.cs vamos definir o BindingContext :

using MauiCmdParametros.Mvvm.ViewModels;

namespace MauiCmdParametros.Mvvm.Views;

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

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

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiCmdParametros.Mvvm.Views.RaizQuadradaView"
             Title="Raiz Quadrada" >   

    <VerticalStackLayout Spacing="30" Padding="20" VerticalOptions="Center">       

   <Entry x:Name="txtNumero"
               Keyboard="Numeric"
               Placeholder="Informe o número"
               FontSize="30"
               HorizontalTextAlignment="Center"
               ClearButtonVisibility="WhileEditing"
               WidthRequest="300"/>

        <Button Text="Calcular a Raiz Quadrada"
                FontSize="20"
                HorizontalOptions="Center"
                Command="{Binding RaizQuadradaCommand}"
                CommandParameter="{Binding Source={x:Reference
txtNumero}, Path=Text}" />


        <Frame BackgroundColor="Aqua">
            <StackLayout Orientation="Horizontal">
                <Label Text="Raiz =  "
                       FontSize="30"
                       FontAttributes="Bold"/>
                <Label Text="{Binding RaizQuadradaResultado}"
                       FontSize="30" />
            </StackLayout>
        </Frame>

    </VerticalStackLayout>
</ContentPage>

Vamos entender o código:

Estamos usando o VerticalStackLayout para empilhar as views na página definindo o layout que é mostrado na figura ao lado.

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

2- 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.

Agora, é só alegria...

Executando o projeto iremos obter:

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

Na próxima parte do artigo veremos como simplificar a implementação do padrão MVVM usando o pacote MVVM Community TooloKit.

Pegue o código do projeto aqui:  MauiCmdParametros.zip (sem as referências)

"Orem também para que sejamos libertos dos homens perversos e maus, pois a fé não é de todos.
Mas o Senhor é fiel; ele os fortalecerá e os guardará do Maligno."
2 Tessalonicenses 3:2,3

Referências:


José Carlos Macoratti