Neste artigo vou mostrar como o SQLite em uma aplicação Xamarin Forms usando o padrão MVVM. |
Eu já publiquei alguns artigos (veja as referências) sobre como usar o SQLite tanto no Xamarin Android como no Xamarin Forms e estou voltando ao assunto para desta vez mostrar como usar o padrão MVVM em uma aplicação usando o SQLite.
Para saber mais sobre o MVVM veja nas referências os artigos onde eu já tratei dos conceitos e de como usar o MVVM.
Neste artigo eu vou mostrar a maneira correta de criar uma aplicação com acesso a dados usando o MVVM.
Vou criar uma aplicação para gerenciar produtos e vou realizar as operações CRUD para criar, alterar e excluir um produto de uma base de dados local no Sqlite. Para isso vamos usar o plugin sqlite-net-pcl via nuget: NuGet Gallery | sqlite-net-pcl 1.5.231
Nota: Existe o plugin NuGet Gallery | SQLite.Net-PCL 3.1.1 mas este plugin sofreu sua ultima atualização em 2015, e, apresenta erros quando adicionado ao projeto .NET Standard.
A validação de dados será feita usando os recursos do FluentValidation : NuGet Gallery | FluentValidation 8.0.100
Vamos definir uma camada de acesso aos dados em uma classe DatabaseHelper e implementar o padrão repositório que vai centralizar as operações de acesso e persistência dos dados.
Vamos criar também um conversor de valor (Value Converter) para converter o formato de dados usado no preço do produto para string.
Vamos também aplicar os conceitos de Messaging Service para poder enviar mensagens das ViewModels para as Views, e, do Navigation Service para realizar a navegação entre as páginas usando os recursos de injeção de dependência do Xamarin Forms.
Abaixo temos a aplicação funcionando:
Nossa aplicação vai possui 3 páginas principais que serão definidas via código XAML e definidas pelas views:
Teremos também uma ContentView chamada PedidoView que vai conter o código comum para Pedidos.
Para cada view vamos definir uma ViewModel conforme a seguir:
O objetivo é aplicar as boas práticas em nosso projeto de forma a ter uma aplicação robusta e fácil de testar e manter.
Recursos Usados
Criando o projeto no VS 2017
Abra o VS 2017 Community e clique em New Project e a seguir escolha Cross Platform -> Mobile App (Xamarin.Forms) e informe o nome PedidoApp:
A seguir selecione a Plataforma, eu marquei somente Android, e escolha a estratégia de compartilhamento que será .NET Standard.
Clique no botão OK.
Pronto nosso projeto já esta criado. ( Atualmente(08/2018) a versão mais atual estável é a 3.1.0)
Criando a estrutura do projeto
Para organizar nosso projeto vamos criar as seguintes pastas via menu Project-> New Folder;
A seguir vemos a estrutura criada no projeto:
Incluindo os pacotes Nuget usados no projeto
Vamos agora via menu Tools e a opção Manage Nuget Packages for Solution incluir os pacotes nuget usados em nosso projeto:
Clique na guia Browse e a seguir localize e instale em todos os projetos os seguinte pacotes :
Ao final deveremos ter as as seguintes dependêncais em nosso projeto .NET Standard :
Definindo o modelo de domínio
Vamos definir o nosso modelo de domínio representado pela classe Pedido na pasta Models com o seguinte código:
Neste código estamos mapeando a entidade Pedido para a tabela Pedidos no banco de dados SQLite, e, definindo o campo Id como chave primária auto-incremental na tabela Pedidos.
Definindo a camada de acesso a dados
Vamos definir a camada de acesso a dados criando a classe DatabaseHelper na pasta Helpers.
Nesta classe vamos definir a conexão com o SQLite e o nome do banco de dados que vamos criar.
Para simplificar o nosso código vamos usar a biblioteca chamada PCL Storage através da qual podemos usar o compartlhamento de arquivos para todas as plataformas sem ter que escrever código separado para cada plataforma.
A PCL Storage fornece um conjunto consistente de APIs IO para arquivos locais para Android, iOS , Windows Store e Windows Phone tornando mais simples o tratamento de arquivos no ambiente multiplataforma.
Nesta classe vamos definir todos os métodos para realizar o acesso e a persistência dos dados no SQLite.
Abaixo temos o código da classe DatabaseHelper:
using PCLExt.FileStorage;
using PCLExt.FileStorage.Folders;
using PedidoApp.Models;
using SQLite;
using System.Collections.Generic;
using System.Linq;
namespace PedidoApp.Helpers
{
public class DatabaseHelper
{
//defina uma conexao e o nome do banco de dados
static SQLiteConnection sqliteconnection;
public const string DbFileName = "PedidosDB.db";
public DatabaseHelper()
{
//cria uma pasta base local para o dispositivo
var pasta = new LocalRootFolder();
//cria o arquivo
var arquivo = pasta.CreateFile(DbFileName, CreationCollisionOption.OpenIfExists);
//abre o BD
sqliteconnection = new SQLiteConnection(arquivo.Path);
//cria a tabela no BD
sqliteconnection.CreateTable<Pedido>();
}
//Pegar todos os dados
public List<Pedido> GetAllPedidosData()
{
return (from data in sqliteconnection.Table<Pedido>()
select data).ToList();
}
//Pegar dados especifico por id
public Pedido GetPedidoData(int id)
{
return sqliteconnection.Table<Pedido>().FirstOrDefault(t => t.Id == id);
}
// Deletar todos os dados
public void DeleteAllPedidos()
{
sqliteconnection.DeleteAll<Pedido>();
}
// Deletar um dado especifico por id
public void DeletePedido(int id)
{
sqliteconnection.Delete<Pedido>(id);
}
// Inserir dados
public void InsertPedido(Pedido pedido)
{
sqliteconnection.Insert(pedido);
}
// Atualizar dados
public void UpdatePedido(Pedido pedido)
{
sqliteconnection.Update(pedido);
}
}
}
|
Definindo a validação dos dados
Agora vamos usar os recursos da FluentValidation e definir a validação dos dados em nossa aplicação. Para isso vamos criar classe PedidoValidator na pasta Validator com o código abaixo:
Estamos validando as propriedades Titulo, Link, Preco e Descricao. Definimos também dois métodos para validação do Preco, PrecoMaiorQueZero, e, para verificar se a string esta vazia : ValidateStringEmpty.
Definindo os serviços usados na aplicação
Na pasta Services vamos criar os serviços usados na aplicação. Para isso vamos definir as interfaces dos serviços e a seguir sua implementação.
Vamos começar com a definição do repositório usado na aplicação criando a interface IPedidoRepository :
A seguir crie a classe PedidoRepository que implementa esta interface :
using PedidoApp.Helpers;
using PedidoApp.Models;
using System.Collections.Generic;
namespace PedidoApp.Services
{
//implementa o repositorio
public class PedidoRepository : IPedidoRepository
{
DatabaseHelper _databaseHelper;
public PedidoRepository()
{
_databaseHelper = new DatabaseHelper();
}
public void DeleteAllPedidos()
{
_databaseHelper.DeleteAllPedidos();
}
public void DeletePedido(int pedidoID)
{
_databaseHelper.DeletePedido(pedidoID);
}
public List<Pedido> GetAllPedidosData()
{
return _databaseHelper.GetAllPedidosData();
}
public Pedido GetPedidoData(int pedidoID)
{
return _databaseHelper.GetPedidoData(pedidoID);
}
public void InsertPedido(Pedido pedido)
{
_databaseHelper.InsertPedido(pedido);
}
public void UpdatePedido(Pedido pedido)
{
_databaseHelper.UpdatePedido(pedido);
}
}
}
|
Nesta implementação do padrão repositório estamos usando uma instância da nossa camada de acesso a dados para ter acesso e persistir os dados. Centralizamos assim nesta classe todo o acesso a dados.
Agora vamos definir o serviço de mensagens usado na aplicação. Crie a interface IMessageService com o código abaixo:
Esses métodos serão usados para exibir mensagens usando a classe DisplayAlert. Para implementar esta interface crie a classe MessageService :
A implementação obtém a página atual do topo da pilha de navegação da aplicação : PedidoApp.App.Current e usa a classe DisplayAlert() para exibir uma mensagem.
Para concluir vamos definir o serviço de navegação criando a interface INavigationService :
Na interface definimos os métodos para navegar entre as páginas da aplicação.
Na classe NavigationService vamos implementar esta interface conforme a seguir:
Definimos a implementação dos métodos:
Para concluir essa etapa vamos criar na pasta Util a classe CurrencyConverter cujo código temos a seguir:
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using Xamarin.Forms;
namespace PedidoApp.Util
{
/// <summary>
/// Conversor para ser usado em campos Entry com máscara para moeda
/// <para>A propriedade vinculada deve ser to tipodecimal, e tem que invocar a
/// o evento PropertyChangedEventArgs sempre que seu valor for alterado
/// de forma que o comportamento da mascara seja mantido.</para>
/// </summary>
public class CurrencyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//implementação para notação 000.00
//return Decimal.Parse(value.ToString()).ToString("C");
//implementação local pt-br 000,00
NumberFormatInfo nfi = new CultureInfo("pt-BR").NumberFormat;
return Decimal.Parse(value.ToString()).ToString("C", nfi);
}
public object ConvertBack(object value,Type targetType,object parameter,CultureInfo culture)
{
string valueFromString = Regex.Replace(value.ToString(), @"\D", "");
if (valueFromString.Length <= 0)
return 0m;
long valueLong;
if (!long.TryParse(valueFromString, out valueLong))
return 0m;
if (valueLong <= 0)
return 0m;
return valueLong / 100m;
}
}
}
|
Nessa classe convertemos os valores do preço do pedido informados via view Entry para o formato string onde implementamos a notação da moeda Real (R$).
Na próxima parte to artigo vamos registrar os serviços e definir as Views e as ViewModels da nossa aplicação.
"Jesus respondeu, e disse-lhe: Se alguém me ama, guardará a minha palavra, e meu
Pai o amará, e viremos para ele, e faremos nele morada."
João 14:23
Referências:
Xamarin Android - CRUD Básico com SQLite
Xamarin Android - Login com SQLite - Macoratti
Xamarin.Forms - Criando uma aplicação com a ...
Xamarin.Forms - Persistindo dados com o SQLite
Xamarin Forms - MVVM - Macoratti
NET - O padrão MVVM revisitado
Xamarin Forms - Criando uma página de Login (MVVM)
Xamarin Forms - MVVM - A interface ICommand -
Xamarin Forms - MVVM, DataBinding e a interface .