Seções iMasters
Desenvolvimento

Entendendo o Pattern Model-View-ViewModel (MVVM)

Inversão de controle, desacoplamento e injeção de dependência são formas de manter um código limpo, fácil de dar manutenção e que seja organizado, nos fazendo assim entender e amadurecer no processo de desenvolvimento de software. Hoje, falaremos de um pattern chamado Model-View-ViewModel (MVVM) e veremos na prática alguns desses conceitos.

O MVVM é um pattern que foi criado em 2005 por John Gossman, um dos arquitetos do WPF e Silverlight na Microsoft. O MVVM assemelha-se em alguns aspectos o MVC (Model View Controller) e ao MVP (Model View Presenter), podemos até dizer que ele é uma especialização do MVP adaptado para a arquitetura do WPF e Silverlight. Conceitualmente, o MVVM e o MVP são idênticos, o que os diferencia é que o MVVM é específico para a arquitetura do WPF e Silverlight, e o MVP é independente de plataforma.

O MVVM visa a estabelecer uma clara separação de responsabilidades em uma aplicação WPF e Silverlight, mantendo uma espécie de façade entre o Modelo de Objetos (entenda classes de negócio, serviços externos e até mesmo acesso a banco de dados) e a View, que é a interface, com a qual o usuário interage. Para entendermos melhor como se dá essa separação e para visualizar como os componentes interagem dentro desse cenário, observe a figura abaixo:

Como ilustra a figura acima, há uma clara separação das camadas. A camada Model (Modelo) não conhece a View (camada de apresentação) e vice-versa. Na verdade, a View conhece a ViewModel e se comunica com ela através do mecanismo de binding. E são os avançados mecanismos de binding, eventos roteados e comandos roteados, que fazem do MVVM um pattern poderoso para construção de aplicações WPF e Silverlight.

Talvez você esteja se perguntado: tá bom, a View está ligada a ViewModel através do mecanismo de binding, mas como funciona essa comunicação?

Observe abaixo:

Veja como é simples: a View, através do databinding, interage com a ViewModel notificando a ocorrência de eventos e o disparo de comandos. A ViewModel, por sua vez, responde a essa notificação realizando alguma ação no modelo, seja obtendo algum dado, atualizando ou inserindo informações no modelo.

Responsabilidades e características

View: a responsabilidade da View é definir a aparência ou a estrutura que o usuário vê na tela. O ideal é que o codebehind da view contenha apenas a chamada ao método InitializeComponent dentro do construtor, ou, em alguns casos, o código que manipule os controles visuais, ou crie animações, algo que é mais difícil de fazer em XAML. A View se liga ao ViewModel através da propriedade DataContext, que é setada para a classe ViewModel correspondente àquela View. Veja no código de exemplo, que será disponibilizado para baixar, como é feita declarativamente a ligação da View com o ViewModel através da propriedade DataContext.

Características comuns

  • A View é um elemento visual, como um objeto Window, Page, UserControl ou DataTemplate.
  • Ela referencia a ViewModel através da propriedade DataContext. Os controles da View são preenchidos com propriedades ou comando, expostos pela ViewModel.
  • O codebehind da view define comportamentos visuais (Behaviors) difíceis de expressar em XAM.

ViewModel: a responsabilidade da ViewModel, no contexto do MVVM, é disponibilizar para a View uma lógica de apresentação. A View Model não tem nenhum conhecimento específico sobre a view, ou sobre como ela é implementada, nem o seu tipo. A ViewModel implementa propriedades e comandos para que a View possa preencher seus controles, e a notifica caso haja alteração de estado, seja através de eventos ou de notificação de alteração. A ViewModel é peça fundamental no MVVM porque é ela quem vai coordenar as iterações da View com o Model, já que um não tem conhecimento do outro. Além de tudo isso, a ViewModel pode implementar a lógica de validação, para garantir a consistência dos dados.

Características comuns

  • A ViewModel é uma classe não visual, que expõe para a View uma lógica de apresentação
  • É testável, independentemente da View ou do Model
  • Coordena as iterações entre a View e o Model
  • Não referencia a View, na verdade, não tem nenhum conhecimento sobre ela
  • Implementa as interfaces INotifyPropertyChanged
  • Expõe propriedade e comando para que a View utilize para preencher seus controles, e notifica a View quando o estado de uma determinada propriedade muda, via implementação da inteface INotifyPropertyChanged ou INotifyCollectionChanged
  • Pode conter a lógica de validação, através da implementação das intefaces IDataErrorInfo ou da INotifyDataErrorInfo

Model: no MVVM, o Model encapsula a lógica de negócios e os dados. O Model nada mais é do que o modelo de domínio de uma aplicação, ou seja, as classes de negócio que serão utilizadas em uma determinada aplicação. Ele também contém os papéis e a validação dos dados de acordo com o negócio, cuja aplicação em questão visa a atender.

Características comuns

  • O Modelo são classes que encapsulam a lógica de negócios e os dados
  • O Modelo não referencia diretamente a View ou ViewModel
  • Ele provê eventos de notificação de mudança de estado, através das interfaces INotifyPropertyChanged and INotifyCollectionChanged. Isso facilita o preenchimento de dados na View
  • O Modelo de dados contém validação de dados e reporta os erros através da interface INotifyDataErrorInfo
  • O Modelo de dados geralmente é utilizado com um repositório (pode ser o Repository Pattern) ou serviço

O MVVM permite a você ter uma visão da clara separação da Interface com o usuário (View), sua lógica de apresentação (ViewModel) e os seus Dados (Model). E, trabalhando dessa forma, temos separação de responsabilidades, desacoplamento e conseguimos evoluir e manter melhor as nossas aplicações.

Já falamos muito, vamos a um exemplo prático. Observe a figura abaixo e veja como ficou a nossa solução de exemplo:

É um projeto simples, apenas para ilustrar os conceitos mostrados no artigo. Vamos começar pela tela que lista os clientes.

Veja que ao abrir o arquivo TodosClientesView.xaml.cs, você verá que o codebehind contém somente a chamada ao método InitializeComponent e nada mais.

Mas ao abrir o arquivo TodosClientesView.xaml você verá que a propriedade DataContext, da grid dentro do User Control, está apontando para o ViewModel correspondente a essa tela, no caso, a classe TodosClientesViewModel.

TodosClientesView.xaml

TodosClientesView.xaml.cs

Vemos que não há ligação da View com o Model. É a responsabilidade da ViewModel fazer essa ligação, como já foi dito anteriormente. Se você observar, a propriedade ItemsSource da Grid está apontando para TodosClientes, que é justamente uma propriedade da classe ViewModel. Observe a figura abaixo:

Se você observar bem, a classe TodosClientesViewModel herda da classe ViewModeBase; isso se dá pelo fato de que, como as classes ViewModel precisam coordenar as ações da View e reagir a iterações realizadas pelo usuário na mesma, ela precisa implementar a interface INotifyPropertyChanged. Para facilitar, é definida uma classe base que implementa a interface e as classes derivadas apenas herdam e utilizam sua implementação da interface. Olhe o diagrama das classes ViewModel:

Note que a ViewModel da tela de cadastro de clientes também implementa a interface IDataErrorInfo, para também poder obter os erros de validação.

E, assim, vemos como fica clara a separação das responsabilidades da View, da ViewModel e do Model, e como recursos avançados como databinding, commands e eventos roteados tornam esse pattern muito poderoso e eficiente para construção de aplicações ricas.

Resumindo, a View conversa com a ViewModel, que conversa com o Model, ou seja, a view não conhece o model, que não conhece a view nem a viewmodel, totalmente desacoplado e de fácil manutenção. A aplicação de exemplo tem como objetivo apenas deixar consolidado os conceitos do pattern aprendido aqui.

Bom, pessoal, espero ter ajudado e colaborado com o aprendizado de vocês. Vejo no MVVM um auxílio poderoso na hora de construir aplicações ricas com boas práticas. Se você vai começar a mergulhar nesse maravilhoso mundo das interfaces ricas, com certeza vai precisar desse aliado do MVVM. Um abraço e até mais.

Mensagem do anunciante:

Torne-se um Parceiro de Software Intel®. Filie-se ao Intel® Developer Zone. Intel®Developer Zone

Comente também

51 Comentários

Como eu faço para baixar o código fonte deste artigo?

    Amigão, desculpe a demora em responder. Posso te mandar por e-mail, ou em breve estarei disponibilizando no github. E caso tenha alguma dúvida, me coloca a disposição para te ajudar. Abraços

Oi, teria como enviar o codigo fonte para o meu email ?

Carlos, tem como mandar o código no meu email, alias, não da pra deixar disponível em algum lugar para galera fazer o download?

Carlos Eduardo Ferreira de Souza

Pessoal segue abaixo, o link para o projeto de exemplo, o mesmo se encontra no meu skydrive:

http://cid-c093310ee2edea3e.office.live.com/browse.aspx/P%c3%bablico

Abraços e qualquer dúvida estou a disposição

    Trak Trak Trugui

    Carlos, o arquivo que vc postou no Skydrive esta corrompido, pelo motivos
    1) a Skydrive não consegue escanear o arquivo (quando tem senha, que não é o caso, ou quando esta corrompido)
    2) o WinRAR reporta isso: !…\Desktop\MVVMAplicaçãoExemplo_.rar: Unexpected end of archive
    3) Baixa o arquivo 3 vezes por browser diferentes.

    Poderia postar o arquivo novamente.
    Obrigado

    vitor

    Também tive o mesmo problema.

    paula

    O arquivo postado está corrompido!

Marnei Santos

Manda pra mim?
marneijs@msn.com

Valeu!

Laercio Sabino

manda pra mim tb por favor

Reginaldo

Olá, Paulo.

Òtimo artigo. O melhor que lí até hoje.
Podes me enviar o arquivo exemplo também? penhall@gmail.com

Forte abraço.

Helder

Muito bom mesmo !!! Parabéns. Estou fazendo um trabalho sobre MVVM e seu artigo abriu bastante a mente sobre como funciona este padrão. Parabéns! Por gentileza, poderia me enviar o arquivo de exemplo?

Fabio

O link do fonte está quebrado, por favor me envie por email fabiortsf@gmail.com.

Valew camarada?

Gustavo

Ótimo Post Carlos Parabéns, pode por gentileza me mandar o projeto neves.gustavo@gmail.com, Obrigado.

Luis Gustavo Costa Mendes

Muito bom o artigo.
Parabéns!!
Também gostaria de receber o exemplo em meu email (gutolg@gmail.com) se não for incômodo, para melhor entendimento.

Agradeço antecipadamente.

Anderson Wernek

Gostaria de receber o código, por favor. awernek arroba gmail ponto com.

[]‘s

Aldo

Opa gostaria de receber o código tbm, por favor, aldovrando@hotmail.com.

[]‘s

Marcelo

Olá, poderia me enviar o source deste exemplo também? marcelo_h.91@hotmail.com

Obrigado.

Marcelo

Olá poderia enviar o source no meu e-mail? Obrigado!

Jean

Parabens pelo artigo, o MVVM era umm ponto de ? até o momento. Poderia me enviar o fonte no email jeanmazc@hotmail.com Muito Obrigado.

Rodolfo

Estava totalmente perdido com esse tema e o artigo ajudou bastante. Por favor, envie o fonte para rafd75@gmail.com. Obrigado!

rodrigo

Bom dia, ótima matéria, gostaria de recebecer este material para estudo, envie por favor para rodrigo71.neves@hotmail.com

Bruno

Otímo artigo!! por favor, me passa esse fonte por e-mail. Brunoksi@gmail.com
Desde já agradeço.

Marcio

Bacana Carlos, excelente explicação sobre MVVM, já tive a oportunidade de trabalhar com esta arquitetura, é bem simples entender, o código fica limpo e facil de entender.

excelente!!

Abs

Marcio

Ton Borges

Muito bom o artigo, seria possivel enviar o fonte para o meu email?

Thiago Adriano

Olá muito bom o artigo, poderia me enviar o código ? thiago.adriano26@gmail.com

Marcos

Artigo muito bom, poderia enviar o código para o meu email? mcps.chiprauski@gmail.com

GUILHERME SERATTI

Gostei muito do seu artigo, quero começar a implementar as novas soluções da empresa utilizando esta forma de Desenvolvimento. Pode me enviar o código para o meu e-mail?! Gostaria de ter um exemplo para melhor entender. glm_seratti@hotmail.com

Jefferson Balivo

Amigo, poderia me enviar o arquivo também: jefferson@balivo.com.br

Tiago Xavier

Parabéns!!!!!!!!

Adorei esse artigo, tem como enviar o código fonte de exemplo.

Sirineo Filho

Gostaria de ver o código fonte para entender melhor a aplicação.

daniel

Meu TCC é baseado no desenvovimento de aplicações LOB utilizando Design Patterns. Me ajudaria muito esse projeto. Meu email é: danielmalavazi@bol.com.br. Muito obrigado

Obilteres

Xiiii. Manda pra mim tambem…..

Matheus

Encaminha pra mim por favor.
matheus_raimundos@yahoo.com.br

Rafael

poderia me enviar o exemplo no email?
rafa.aspx@gmail.com

pfeitor

Carlos, muito bom seu artigo, poderia me enviar o código fonte por email? Obrigado!
paulo_feitor@yahoo.com.br

Murillo

Gostei muito do artigo, você poderia me enviar o código fonte. Obrigado!
murillogrubler@hotmail.com

Fabio Cerri

Gostei! me envie o codigo fonte!! fabio.cerris@gmail.com

Luciano

Gostei do artigo, muito bem conceituado. Ninguém que recebe o código fonte compartilha um link para download? me envie o fonte por favor… assim que receber disponibilizo um link para quem ainda ver vir por ae, vlw.

Victor

Poderia me enviar o cogido fonte ? Obrigado, muito bom o trabalho !

victorss.42@hotmail.com

Leandro

Muito bom o artigo! Poderiam me mandar o código fonte? Grato!

Rafael Ferreira

É possível me enviar os fontes?
rafael_yami@hotmail.com

Ivan

Muito bom o trabalho!! Pode me enviar os fontes?

Vinícius Machado

Olá, estou elaborando minha monografia com base no padrão arquitetural MVVM, e gostaria apenas de dizer que o padrão MVVM é uma especialização do Presentation Model, apresentado por Martin Fowler, que também trabalha com abstração da interface gráfica.

No MVP, a camada intermediária conhece todas as camadas, enquanto no MVVM a camada intermediária conhece apenas o Model.

E parabéns pelo artigo que está excelente, sucesso!!!.

Aline

Olá, poderia me passar seu e-mail, se não for incômodo?

victor hugo

Também gostaria que enviasse pro meu e-mail, o Skydrive nao esta mais disponivel.
victorhdchagas@live.com

Cadu Souza

Pessoal segue o link do arquivo no google drive. Abs espero que ajude!
https://drive.google.com/file/d/0B0jf3_p-DD2MSWx0VVVod2VtREk/edit?usp=sharing

Qual a sua opinião?