Neste artigo vou mostrar como usar o padrão de projeto MVVM em aplicações WPF. |
O padrão
Model-View-ViewModel permite aos desenvolvedores separar completamente a
interface do usuário lógica de negócios que acessa os dados. A separação da
interface do usuário da lógica de negócios e dos dados permitem criar um
projeto robusto, limpo e testável.
O DataBinding da WPF é extremamente poderoso porque permite separar a
interface de usuário da lógica de negócios.
Neste
artigo veremos um exemplo que não usa o código no code-behind. No entanto,
isso não é necessário para implementar o padrão MVVM. O que importa para o
MVVM é que você quer desacoplar sua View do seu Model fazendo com que a
comunicação entre os dois sejam feita via ViewModel.
O propósito desta arquitetura desacoplada é permitir que você altere
facilmente a View ou o modelo sem quebrar o código existente. Você também
quer poder testar completamente todo o seu código sem se preocupar com o uso
de ferramentas difíceis porque você criou uma View XAML fortemente acoplada
com a sua logíca de negócios.
Recursos Usados
Criando o projeto WPF
Abra o VS 2015 Community e crie um novo projeto (File-> New Project) usando a linguagem C# e o template Windows Classic Desktop e a seguir WPF Application;
Informe um nome a seu gosto. Eu vou usar o nome Wpf_Mvvm:
Definindo o Model
Crie uma pasta chamada Model no projeto e nesta pasta inclua a classe Contato.cs e inclua o código a seguir nesta classe:
using System.ComponentModel;
namespace Wpf_Mvvm.Model
{
public class Contato : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Esta rotina é chamada cada vez que o valor da propridade
// for definida. Isso vai disparar um evento para notificar
// a WPF via data binding que algo mudou
private void OnPropertyChanged(string nomePropriedade)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nomePropriedade));
}
private string _nome;
private string _sobrenome;
private string _telefone;
private string _email;
public string Nome
{
get { return _nome; }
set
{
_nome = value;
OnPropertyChanged("Nome");
}
}
public string Email
{
get { return _email; }
set
{
_email = value;
OnPropertyChanged("Email");
}
}
public string Sobrenome
{
get { return _sobrenome; }
set
{
_sobrenome = value;
OnPropertyChanged("Sobrenome");
}
}
public string Telefone
{
get { return _telefone; }
set
{
_telefone = value;
OnPropertyChanged("Telefone");
}
}
}
}
|
Temos na classe Contato uma objeto CLR simples que implementa a interface INotifyPropertyChanged e que representa o Model no MVVM. A implementação da interface vai fazer com que toda vez que ocorrer uma alteração o nos valores das propriedades o evento PropertyChangedEventHandler seja disparado.
Definindo a ViewModel
Crie uma pasta chamada ViewModel no projeto e nesta pasta inclua a classe ContatoViewModel.cs e inclua o código a seguir nesta classe:
using System.Collections.ObjectModel;
using Wpf_Mvvm.Model;
namespace Wpf_Mvvm.ViewModel
{
public class ContatoViewModel : ObservableCollection<Contato>
{
public ContatoViewModel()
{
PreparaContatoCollection();
}
private void PreparaContatoCollection()
{
var Contato1 = new Contato
{
Nome = "Jose Carlos",
Sobrenome = "Macoratti",
Email = "macoratti@yahoo.com",
Telefone = "012-8789-0200"
};
Add(Contato1);
var Contato2 = new Contato
{
Nome = "Bruno",
Sobrenome = "Silveira",
Email = "brunosilv@email.com",
Telefone = "021-9987-3458"
};
Add(Contato2);
var Contato3 = new Contato
{
Nome = "Jonatas",
Sobrenome = "Sanches",
Email = "jonsanch@email.com",
Telefone = "011-8975-57898"
};
Add(Contato3);
}
}
}
|
A nossa classe ContatoViewModel obterá os dados do nosso modelo e apresentará os dados para a view através do databinding.
A ViewModel herda de uma classe chamada ObservableCollection<>. que é uma classe genérica que aceita nosso modelo como o tipo genérico.
Ela basicamente transforma nosso ViewModel em uma coleção de objetos Contato com notificações de alteração incorporadas para facilitar os mecanismos de databinding do WPF. Quando usamos ObservableCollection, o databinding sabe quando itens são adicionados ou removidos.
Neste código definimos o método PreparaContatoCollection() que cria 3 instãncias da classe Contato e as adiciona à coleção interna da ViewModel. Vamos vincular uma propriedade ItemsSource do controle ListView ao ViewModel e também vincular a propriedade DataContext da Grid com a ViewModel.
Ao configurar a propriedade DataContext da Grid faremos com que os controles filhos herdam o DataContext para fazer o DataBinding.
A propriedade ItemsSource do ListView vai preencher o controle com cada item existente em nosso ObservableCollection<Contato>.
Definindo a View
Vamos agora definir a View da nossa aplicação abrindo o arquivo MainWindow.xaml e incluir o código abaixo neste arquivo:
<Window x:Class="Wpf_Mvvm.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:viewModel="clr-namespace:Wpf_Mvvm.ViewModel"
Title="ContatoMVVM" Height="300" Width="300">
<Window.Resources>
<viewModel:ContatoViewModel x:Key="contatoViewModel" />
</Window.Resources>
<Grid DataContext="{StaticResource ResourceKey=contatoViewModel}">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="93*" />
<RowDefinition Height="29*" />
<RowDefinition Height="27*" />
<RowDefinition Height="30*" />
<RowDefinition Height="81*" />
</Grid.RowDefinitions>
<ListView Grid.ColumnSpan="2" BorderThickness="2" x:Name="lstContatos"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{StaticResource ResourceKey=contatoViewModel}"
DisplayMemberPath="Nome"
Margin="0,0,0,28"
Grid.RowSpan="2" />
<TextBlock Grid.Column="0" Grid.Row="1" Text="Nome" />
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Path=Nome}" />
<TextBlock Grid.Column="0" Grid.Row="2" Text="Sobrenome" />
<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Path=Sobrenome}" />
<TextBlock Grid.Column="0" Grid.Row="3" Text="Email" />
<TextBox Grid.Column="1" Grid.Row="3" Text="{Binding Path=Email}" />
<TextBlock Grid.Column="0" Grid.Row="4" Text="Telefone" />
<TextBox Grid.Column="1" Grid.Row="4" Text="{Binding Path=Telefone}" />
</Grid>
</Window>
|
Observe que definimos a propriedade DataContext da Grid vinculada ao
recurso estático do ViewModel que criamos no dicionário. O DataContext
fornece um contexto vinculativo para os controles WPF e quando
configuramos o DataContext na Grid, esse valor se propagará para os
elementos filhos através da herança de propriedade - é por isso que todos os
valores vinculados ao TextBox podem ser configurados para propriedades do
modelo.
Isso ocorre porque o DataContext está definido para o nosso
ViewModel, que é um ObservableCollection<Contato>. Então, quando
estabelecemos nossos caminhos de ligação, a WPF sabe estamos tratando com um
objeto Contato e os valores são mapeados para as propriedades
corretas.
Executando o projeto iremos obter o resultado abaixo:
Criamos uma janela WPF vinculada aos dados do nosso objeto Contato.
Você pode atualizar os valores dos TextBox e eles serão alterados no
ListView, e ao clicar no ListView os valores sreão atualizados com base na
sua seleção.
Assim a interface do usuário esta 100% vinculada aos dados e não escrevemos
nenhum manipulador de eventos no code-behind, fizemos isso usando código
XAML. Note que o resource dictionaries não esta limitado aos objetos CLR
podemos usar controles de terceiros, styles, type converters ou qualquer
outro tipo de objeto na marcação XAML.
Pegue o projeto completo aqui : Wpf_Mvvm.zip
"Se dissermos que
temos comunhão com ele (Deus), e andarmos em trevas, mentimos, e não
praticamos a verdade."
1 João 1: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:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Visual Studio - Dica de produtividade - Quick Launch - Macoratti.net
Visual Studio - Dica de produtividade - Nuget - Macoratti.net
Apresentando o WPF - Windows Presentation Foundation - Macoratti
WPF - Criando uma aplicação básica (para iniciantes) - Macoratti
NET - Apresentando o padrão Model-View-ViewModel - Macoratti