Quando estamos desenvolvendo aplicativos mobile utilizando Xamarin Forms, é normal que adotemos alguma arquitetura na organização do código fonte do nosso projeto. O padrão que muitas pessoas adotam é o MVVM.

Dentro do MVVM alguns métodos acabam se repetindo bastante ao longo do projeto e outras coisas acabam ficando um pouco trabalhosas, como a passagem de parâmetros para outras páginas, tratamento de eventos da página na View Model, injeção de dependências nos projetos de plataforma específicas e etc.

O Prism é uma biblioteca open source que implementa o padrão MVVM para projetos Xamarin Forms, UWP e WPF. Ele se defini como um framework para criar aplicativos XAML com baixo acoplados, de fácil manutenção e testáveis ​​em WPF, Windows 10 UWP e Xamarin

Você pode ver o código fonte do Prism aqui e a documentação oficial aqui.

O Prism é de fato um framework que possui muitos métodos e muitas utilidades, neste post nós abordaremos apenas o setup inicial do Prism. Durente novos posts no blog serão abordadas outras funcionalidades, mas caso você esteja precisando, a documentação do Prism é bem completa e pode te atender, clique aqui para ve-la (em inglês)

Xamarin Forms + Prism

Podemos criar um projeto Xamarin Forms que utilize o Prism de duas formas: Baixando os templates de projeto do Prism ou criando um novo projeto Xamarin Forms e configurando manualmente o Prism.

Neste post vamos utilizar os templates do Prism. Você pode fazer o download deles para utilizar no seu Visual Studio neste endereço

Instale o template e você já poderá criar um projeto Xamarin Forms e Prism rapidamente pelo Visual Studio com o auxilio de uma interface visual.

Criando um projeto com o Prism

O primeiro é passo é selecionar o template desejado no Visual Studio, neste post nós vamos trabalhar com o Prism Blank App

Depois disto o Prism irá perguntar para você qual container de injeção de dependências você irá utilizar, neste passo por padrão você terá duas opções o Unity e o DryIoc, neste post no iremos trabalhar com o DryIoc por ser um container de injeção de dependências mais leve e mais performático

Explorando o novo projeto criado pelo Prism

A primeira coisa de criarmos o projeto que podemos perceber é que o Prism automaticamente criou as pastas Views e ViewModels, justamente por ser um framework voltado para a utilização do padrão MVVM.

Veja também que o arquivo App.xaml.cs está diferente, ele conta com um construtor que recebe um IPlataformInitializer, que é uma classe interna do Prism utilizada nos projetos de plataforma específicos para inicializações customizadas, para registrar classes no container de injeção de dependências por exemplo.

Ainda no App.xaml.cs um outro método chama atenção, o RegisterTypes. Este método é sobrescrito no App.xaml.cs para que possamos manusear o container de injeção de dependências registrando nossas interfaces, instancias e páginas.

Dentro da pasta ViewModels foram criados dois arquivos o ViewModelBase e o MainPageViewModel

A classe ViewModelBase herda de BindableBasee implementa INavigationAware e IDestructible, ambas classes do Prism.

A classe BindableBase será responsável por implementar o INotifyPropertyChange nas ViewModels que herdarem dela.

A interface INavigationAware possui métodos que facilitam a navegação ente páginas no Xamarin Forms através das ViewModels, como os métodos OnNavigatedFrom, OnNavigatedTo e OnNavigatingTo, sendo executado quando sair da página, quando entrar na página e quando estiver entrando na página, respectivamente.

Esta classe possui ainda a propriedade NavigationService do tipo INavigationService. Este objeto facilita a chamada para navegação entre páginas, enquanto a classe INavigationAware implementa métodos que são chamados ao navegar, a interface INavigationService implementa métodos para realizar a navegação, como o NavigateAsync

Olhando agora os projetos de plataforma específicos, você verá algumas mudanças nos arquivos MainActivity e AppDelegate, veja que ambos estão passando uma classe initializer ao instanciar o App. Cada plataforma passa para o app sua forma de ser inicializada, a MainActivity passa a classe AndroidInitializer e o AppDelegate a classe iOSInitializer. Ambas as classes de inicialização poderiam ser herdadas por uma classe nossa em que pudéssemos customizar a inicialização da plataforma, como por exemplo registrando classes no container de injeção de dependências.

Utilizando o container de injeção de dependências

Regitrando uma página e uma viewModel para navegação

Agora que nós já exploramos o projeto criado, vamos utilizar os métodos do Prism que vimos acima.

Dentro de Views vamos criar uma nova página chamada de HelloWorldPage e dentro de ViewModels uma nova classe chamada de HelloWorldViewModel

Depois de criar nossa nova página e nossa ViewModel, vamos precisar informar para o Prism que elas existem e que podem receber navegação. Para isto, acesse a classe App.xaml.cs e no método RegisterTypes, vamos adicionar a seguinte linha:

containerRegistry.RegisterForNavigation<HelloWorldPage, HelloWorldViewModel>();

Além de informarmos para o Prism que a página pode receber navegação, também estamos informando qual é a ViewModel da página, o que nos economizará tempo a frente excluindo a necessidade de setar o binding context de cada página

Registrando uma nova interface

Agora vamos criar uma interface para ser registrada no nosso container de injeção de dependências, a classe IMinhaMensagem. Ela terá apenas um método chamado ObterBoasVindas(). Veja abaixo:

    public interface IMinhaMensagem
    {
        string ObterBoasVindas();
    }

E então depois de criar a interface, vamos criar uma classe responsável por fazer sua implementação:

 public class MinhaMensagem : IMinhaMensagem
    {
        public string ObterBoasVindas()
        {
            return "Xamarin <3 Prism";
        }
    }

Agora que já temos nossa interface e nossa classe concreta que implementa a interface, vamos adiciona-la ao nosso container de injeção de dependências para que possamos solicitar esta classe no construtor das nossas ViewMoels. Para isto, vamos novamente a classe App.xaml.cs no método RegisterTypes:

containerRegistry.Register<IMinhaMensagem, MinhaMensagem>();

Agora que registramos a classe no container, vamos voltar para a classe MainPageViewModel.cs, solicitar a classe IMinhaMensagem no construtor da página e setar o conteúdo do método ObterBoasVindas() na propriedade Title:

public class MainPageViewModel : ViewModelBase
{
    private readonly IMinhaMensagem _minhaMensagem;
    public MainPageViewModel(INavigationService navigationService, IMinhaMensagem minhaMensagem)
        : base(navigationService)
    {
        _minhaMensagem = minhaMensagem;
        Title = _minhaMensagem.ObterBoasVindas();
    }
}

Para finalizar vamos adicionar um botão na página MainPage que será responsável por efetuar a navegação para a página que criamos a HelloWorldPage:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MeuApp.Views.MainPage"
             Title="{Binding Title}">

    <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
        <Label Text="Welcome to Xamarin Forms and Prism!" />
        <Button Text="Navegar" Command="{Binding NavegarCommand}"/>
    </StackLayout>

</ContentPage>

E na MainPageViewModel vamos adicionar o command que irá realizar a navegação:

public class MainPageViewModel : ViewModelBase
{
    private readonly IMinhaMensagem _minhaMensagem;
    public DelegateCommand NavegarCommand { get; set; }
    public MainPageViewModel(INavigationService navigationService, IMinhaMensagem minhaMensagem)
        : base(navigationService)
    {
        _minhaMensagem = minhaMensagem;
        Title = _minhaMensagem.ObterBoasVindas();
        NavegarCommand = new DelegateCommand(() => navigationService.NavigateAsync(nameof(HelloWorldPage)));
    }
}

Perceba que na página estamos utilizando o Command no botão e passando valor do Command por Binding, sem que precisemos setar o binding context da página. Isto é possível porque lá na classe App.xaml.cs nós informamos a página MainPage e sua ViewModel a MainPageViewModel.

Outo ponto é que estamos usando o DelegateCommand do Prism, ele é mais poderoso que o Command convencional, possui formas mais simples de ser tipo e de controlar sua execução.

Na MainPageViewModel, estamos usando a propriedade navigationService herdada da classe BaseViewModel para fazer a navegação, como método NavigateAsync do Prism. Se você quiser, adicione um breakpoint nos métodos OnNavigatedTo, OnNavigatingTo da ViewModel HelloWorldViewModel, para observar o fluxo de navegação do Prism.

Play!

Ufa! Depois de realizar todos os passos acima, você será capaz de executar seu app e ver o resultado!

app rodando

Conclusão

O Prism é um framework muito poderoso que facilita muito o trabalho com o padrão MVVM, ele possui diversas classes e métodos que não serão abordados neste post, mas que possuem uma vasta documentação, você pode ver mais aqui.

Modificado pela ultima vez: 15 de maio de 2020

Comentários

Escreva uma resposta ou comentário

Seu endereço de e-mail não será publicado.

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.