.NET - O padrão MVVM (Model-View-ViewModel) revisitado


  Neste artigo vou apresentar os conceitos relacionados como padrão de projeto Model-View-ViewModel (MVVM).

O padrão MVVM é basedo no padrão MVC - Model-View-Controller, eles possuem em comum o Model-View e são separados pelo ViewModel.

O padrão MVVM foi projetado para implementar a vinculação de dados entre o seu ViewModel e a sua View conforme mostra a figura abaixo:

Estruturalmente, uma aplicação que usa o padrão MVVM consiste basicamente em três componentes principais: o Modelo, a Visão(View) e a ViewModel.

Essa tarefa (a vinculação de dados) pode ser feita usando o Knockout e atualmente com o AngularJS que faz isso muito bem usando o recurso do two-way databinding.

Nota:  O AngularJS é considerado um framework Model-View-Whatever.(MVW) onde Whatever significa 'Tudo oque funciona para você"

A KnockoutJS é uma library JavaScript Open Source que usa o padrão MVVM (Model-View-ViewModel) para criar interfaces de usuário através de ligações declarativas de dados, interface de atualização automática, rastreamento de dependência e modelagem do lado cliente.

O conceito de MVVM deve ser muito intuitivo e familiar, especialmente para pessoas com experiência em WPF. (Veja as referências para saber mais sobre o padrão MVVM)

Você pode obter mais informações e detalhes bem como baixar a library JavaScript no site oficial do KnockoutJS - http://knockoutjs.com/

AngularJS é um framework JavaScript open-source, mantido pelo Google, que auxilia na execução de single-page applications. Seu objetivo é aumentar aplicativos que podem ser acessados por um navegador web, sob o padrão model–view–controller (MVC), em um esforço para facilitar tanto o desenvolvimento quanto o teste dos aplicativos.

O AngularJS é construído sob a ideologia de que programação declarativa deve ser usada para construção de Interfaces de Usuário e componentes de software, enquanto que a programação imperativa é excelente para escrever as regras de negócio.
http://angularjs.org/

A coisa mais importante a lembrar quando você for criar o seu ViewModel é que eles devem ser organizados de forma a tornar mais fácil a representação de como as suas Views vão usar os dados.

Esta é uma diferença importante pois os Models no padrão MVC são uma representação de como os dados estão armazenados no banco de dados.

No padrão MVC, o controlador de MVC aceita solicitações HTTP, obtém dados a partir do modelo, e encaminha o modelo para a view renderizando a saída.

Já os ViewModels são a peça que realiza essa mesma tarefa, pois o ViewModel assume a responsabilidade de realizar, ou expor o comando que abriga toda a lógica de interface do usuário, além de buscar os dados e a ligação de dados.

Neste contexto a ViewModel tem a responsabilidade de disponibilizar para a View uma lógica de representação.

Em uma aplicação ASP .NET MVC podemos ter um ViewModel representando um conjunto de um ou mais Models e outras informações que desejamos exibir em uma View.

Na figura cima vemos que o ViewModel - AlteraSenha - é composto por informações do Model Usuario e de informações que precisamos exibir somente na View para confirmar a senha.

Uma maneira de saber se você precisa usar o padrão ViewModel é observar como foi definido o seu Model e verificar se nele existem definições que somente são utilizadas pelas Views e não têm nada a ver com seu modelo de domínio.

Se isso for encontrado no seu modelo então talvez fosse o caso de você usar o ViewModel para separar essa responsabilidade a mais que esta no seu Model.

Recursos usados:

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

Criando o projeto no VS Community

Abra o VS Community e clique em New Project;

A seguir selecione a linguagem Visual C# e o template ASP .NET Web Application;

Informe o nome Mvc_MVVM e clique no botão OK;

A seguir selecione o template Empty, marque o folder MVC e clique no botão OK;

Definindo o Model

Vamos supor que temos uma classe Usuario nosso modelo de domínio.

Vamos definir na pasta Models o nosso modelo de domínio representando pela classe Usuario que tem o seguinte código:

using System;
using System.ComponentModel.DataAnnotations;
namespace Mvc_MVVM.Models
{
    public class Usuario
    {
       public int Id { get; set; }
       [Required]
       public string Nome { get; set; }
       [Required]
       public string Email { get; set; }
       [Required]
       public string Senha { get; set; }
       public DateTime DataCriacao { get; set; }
    }
}

Esse é nosso modelo de negócio que representa um usuário com id, nome, email, senha e data de inclusão no cadastro.

Definindo o ViewModel

Agora vamos supor que desejamos criar um formulário para alterar a senha do usuário e que vamos precisar exibir neste formulário as seguintes informações :

Observe que temos informações que precisamos exibir que não constam do nosso modelo de domínio. Essas informações somente serão exibidas na view.

Com base nisso, vamos criar uma pasta ViewModel em nosso projeto e nesta pasta criar o nosso ViewModel representando pela classe UsuarioViewModel com o seguinte código:

using System.ComponentModel.DataAnnotations;
namespace Mvc_MVVM.ViewModel
{
    public class UsuarioViewModel
    {
        [Required]
        public string Nome { get; set; }
        [Required]
        public string Senha { get; set; }
        [Required]
        public string NovaSenha { get; set; }
        public string ConfirmarSenha { get; set; }
    }
}

Como você pode ver a nossa View Model contém as propriedades Nome e Senha do modelo de domínio e as propriedades NovaSenha e ConfirmarSenha que iremos somente exibir na view.

As propriedades Id , Email e DataInclusao não são necessárias em nosso ViewModel.

Definindo o Controlador

Vamos definir um controlador HomeController na pasta Controllers bem simples apenas para gerar a view para o nosso ViewModel:

O código do controlador HomeController é dado a seguir:

using Mvc_MVVM.ViewModel;
using System.Web.Mvc;
namespace Mvc_MVVM.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            UsuarioViewModel usuario = new UsuarioViewModel();
            return View(usuario);
        }
        [HttpPost]
        public ActionResult Index(UsuarioViewModel usuario)
        {
            //logica para alterar senha do usuároi
            return View();
        }
    }
}

Gerando a view Index para o método Action Index e usando as seguintes configurações:

Teremos o seguinte código:

@model Mvc_MVVM.ViewModel.UsuarioViewModel
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()
        <div class="form-horizontal">
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.Nome, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Nome, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Nome, "", new { @class = "text-danger" })
                </div>
            </div>
           <div class="form-group">
                @Html.LabelFor(model => model.Senha, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Senha, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Senha, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.NovaSenha, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.NovaSenha, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.NovaSenha, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.ConfirmarSenha, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.ConfirmarSenha, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.ConfirmarSenha, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Alterar Senha" class="btn btn-default" />
                </div>
            </div>
        </div>
       }
</body>

Temos uma view fortemente tipada onde o tipo é nosso ViewModel: UsuarioViewModel.

Executando o projeto teremos o resultado abaixo:

O ponto chave a lembrar aqui é que o ViewModel somente representa os dados que você deseja usar na sua view e nada mais. (Um ViewModel pode combinar dados de mais de um Model)

Creio que você entendeu o conceito básico do que é um ViewModel e quando usá-lo.

Pegue o projeto completo aqui :  Mvc_MVVM.zip (sem as referências)

Ele(o anjo), porém, disse-lhes: Não vos assusteis; buscais a Jesus Nazareno, que foi crucificado; já ressuscitou, não está aqui; eis aqui o lugar onde o puseram.
Marcos 16:6

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti