MVVMCoffee

Neste artigo irei demonstrar como você pode trabalhar com o pattern MVVM (Model-View-ViewModel) em suas aplicações Xamarin.Forms, da maneira que eu considero mais simples possível  e sem depender de nenhum framework.

M V VM

mvvm

“O padrão Model-View-ViewModel (MVVM) ajuda a separar a lógica de negócios e apresentação de um aplicativo de sua interface do usuário (UI) de forma precisa. Mantendo uma separação clara entre a lógica do aplicativo e a interface do usuário, ajudando a resolver vários problemas de desenvolvimento e tornando mais fácil de testar um aplicativo, manter e evoluir. Ele pode também melhorar muito a oportunidades de reutilização de código e permitir que os desenvolvedores e designers de interface do usuário possam mais facilmente colaborarem durante o desenvolvimento de suas respectivas partes de um aplicativo.”Docs Microsoft

MVVMCoffee

Eu resolvi criar este pacote devido a necessidade que encontrei no meu dia-a-dia de trabalho. Lá na empresa temos o costume de não trabalhar com frameworks de MVVM, então toda vez que começo um projeto novo, necessito criar algumas classes bases para que possamos utilizar o MVVM e depois adaptarmos de acordo com a necessidade do projeto.

Pensando nisso, resolvi criar esta biblioteca para não precisar realizar este trabalho toda vez que iniciamos um novo projeto. Assim, eu ganho o tempo para tomar um café.

Gostaria de ressaltar que esta biblioteca não tem o intuito de competir ou substituir o uso dos frameworks. Caso você esteja buscando referências sobre os frameworks para MVVM, recomendo pesquisar sobre: MVVM Cross ou Prism, são dois ótimos frameworks e bem consolidados no mercado.

Vamos ao que interessa, como que você pode utilizar este plugin e também ganhar um tempo para tomar um café.

ADICIONANDO O NUGET PACKAGE

Instale o plugin em seu projeto compartilhado.

Screen Shot 2019-07-24 at 17.16.16

Estrutura de pastas

É de suma importância que você crie a seguintes estrutura de pastas em seu app para que o Plugin possa funcionar corretamente.

Crie três pastas, sendo elas: Models, Views e ViewModels.

  • Models – Pasta para as classes que representam suas entidades.
  • Views – Pasta para as suas pages.
  • ViewModels – Pasta para as classes que representam suas ViewModels.

Screen Shot 2019-07-24 at 17.19.24

Nomenclatura de arquivos

É também de suma importância para que o plugin funcione corretamente que todos os seus arquivos que representam suas Views e ViewModels estejam corretamente nomeados.

  • Views – Todo arquivo de page, precisa terminar com a palavra “Page”.
  • ViewModels – Todos os arquivos que representem ViewModel precisa terminar com a palavra “ViewModel”.

Screen Shot 2019-07-24 at 23.44.24

Essa nomenclatura é necessária para que o plugin possa identificar qual Page pertence a sua respectiva ViewModel.

Model

Toda classe que represente sua entidade, necessita herdar de “BaseModel”, para que dessa forma você possa utilizar  o método SetProperty e com isso a interface INotifyPropertyChanged.

using MVVMCoffee.Models;
namespace Sample.Models
{
public class Customer : BaseModel
{
public string Name
{
get { return _name; }
set { SetProperty(ref _name, value); }
}
string _name = string.Empty;
public int Age
{
get { return _age; }
set { SetProperty(ref _age, value); }
}
int _age;
}
}

view raw
Customer.cs
hosted with ❤ by GitHub

ViewModels

Toda classe que represente uma ViewModel, necessita herdar de “BaseViewModel”, para que dessa forma você possa utilizar as ViewModels nos exemplos de navegação a seguir.

using MVVMCoffee.ViewModels;
namespace Sample.ViewModels
{
public class MainViewModel : BaseViewModel
{
public MainViewModel()
{
}
}
}

view raw
MainViewModel.cs
hosted with ❤ by GitHub

Views

No Code-behind de suas páginas, defina na propriedade BindingContext qual ViewModel pertence aquela Page, como demonstrado a seguir.

using System.ComponentModel;
using Sample.ViewModels;
using Xamarin.Forms;
namespace Sample
{
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
private MainViewModel ViewModel => BindingContext as MainViewModel;
public MainPage()
{
InitializeComponent();
BindingContext = new MainViewModel();
}
}
}

view raw
MainPage.xaml.cs
hosted with ❤ by GitHub

Navegação

Para navegação temos 4 métodos, sendo eles:

PushAsync – Colocar uma nova página na pilha de páginas.

await Navigation.PushAsync<CustomerViewModel>(false);

view raw
PushAsync.cs
hosted with ❤ by GitHub

 

SetRootAsync – Definir uma nova página como a página root, ou seja, a primeira da pilha de páginas.

await Navigation.SetRootAsync<CustomerViewModel>();

view raw
SetRootAsync.cs
hosted with ❤ by GitHub

 

PopAsync – Navegar para a página anterior da pilha de páginas.

await Navigation.PopAsync();

view raw
PopAsync.cs
hosted with ❤ by GitHub

 

PopToRootAsync – Navegar para a primeira página da pilha de páginas.

await Navigation.PopToRootAsync();

view raw
PopToRootAsync.cs
hosted with ❤ by GitHub

Hands-on

App

Na classe App.cs comece atribuindo uma nova NavigationPage para MainPage, como demonstrado a seguir.

using Xamarin.Forms;
namespace Sample
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
}
}

view raw
App.xaml.cs
hosted with ❤ by GitHub

XAML

Edite sua MainPage adicionando dois Buttons, como demonstrado a seguir.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Sample.MainPage"
Title="{Binding TitlePage}">
<StackLayout Margin="20" VerticalOptions="Center">
<Label Text="Examples of using MVVMCoffee plugin."
HorizontalTextAlignment="Center"/>
<Button Text="PushAsync to Form" BackgroundColor="#F3F3F3"
Command="{Binding PushAsyncToFormCommand}"/>
<Button Text="SetRootAsync" BackgroundColor="#F3F3F3"
Command="{Binding SetRootFormCommand}"/>
</StackLayout>
</ContentPage>

view raw
MainPage.xaml
hosted with ❤ by GitHub

 

Crie a FormPage, contendo um Entry e uma Label para testar o uso da interface INotifyPropertyChanged  e dois Buttons para utilizar os métodos PopAsync e PopToRootAsync, como demonstrado a seguir.

<?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="Sample.Views.FormPage"
Title="{Binding TitlePage}">
<ContentPage.Content>
<StackLayout Margin="20">
<StackLayout>
<Label Text="Example of Customer object for demonstrate using interface INotifyPropertyChanged"
HorizontalTextAlignment="Center"/>
<Entry Text="{Binding Customer.Name}"/>
<Label Text="{Binding Customer.Name}"/>
</StackLayout>
<StackLayout Padding="0,50">
<Button Text="PopAsync" BackgroundColor="#F3F3F3"
Command="{Binding PopAsyncCommand}"/>
<Button Text="PopToRootAsync" BackgroundColor="#F3F3F3"
Command="{Binding PopToRootAsyncCommand}"/>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>

view raw
FormPage.xaml
hosted with ❤ by GitHub

Observação: Lembre-se de adicionar no Code-behind de suas pages a sua respectiva ViewModel.

ViewModel

Na MainViewModel crie os commands para navegação e seus respectivos métodos.

using MVVMCoffee.ViewModels;
using Xamarin.Forms;
namespace Sample.ViewModels
{
public class MainViewModel : BaseViewModel
{
public Command PushAsyncToFormCommand { get; }
public Command SetRootFormCommand { get; }
public MainViewModel()
{
TitlePage = "MainPage";
PushAsyncToFormCommand = new Command(ExecutePushAsyncToFormCommand);
SetRootFormCommand = new Command(ExecuteSetRootFormCommand);
}
private async void ExecutePushAsyncToFormCommand()
{
await Navigation.PushAsync<FormViewModel>(false);
}
private async void ExecuteSetRootFormCommand()
{
await Navigation.SetRootAsync<FormViewModel>();
}
}
}

view raw
MainViewModel.cs
hosted with ❤ by GitHub

 

Crie a classe FormViewModel, com os Commads de navegação e seus respectivos métodos, também crie um objeto do tipo Customer.

using System;
using MVVMCoffee.ViewModels;
using Sample.Models;
using Xamarin.Forms;
namespace Sample.ViewModels
{
public class FormViewModel : BaseViewModel
{
public Command PopAsyncCommand { get; }
public Command PopToRootAsyncCommand { get; }
private Customer _customer;
public Customer Customer
{
get { return _customer; }
set { SetProperty(ref _customer, value); }
}
public FormViewModel()
{
TitlePage = "FormPage";
Customer = new Customer();
PopAsyncCommand = new Command(ExecutePopAsyncCommand);
PopToRootAsyncCommand = new Command(ExecutePopToRootAsyncCommand);
}
private async void ExecutePopAsyncCommand()
{
await Navigation.PopAsync();
}
private async void ExecutePopToRootAsyncCommand()
{
await Navigation.PopToRootAsync();
}
}
}

view raw
FormViewModel.cs
hosted with ❤ by GitHub

No final teremos a seguinte estrutura de projeto

Screen Shot 2019-07-27 at 14.56.49

Resultado

ezgif.com-video-to-gif.gif

 

Esse e todos os exemplos deste blog encontram-se disponíveis no GitHub.

icongithub

2 comentários em “MVVMCoffee

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s