O Windows Universal (Universal Windows Platform - UWP) é uma plataforma unificada para o desenvolvimento de aplicações para todos os dispositivos que executam o Windows 10. Entre esses dispositivos estão Computadores, Tablets, Smartphones e o XBox. Claro que por terem diferentes capacidades e componentes, em alguns casos é necessário desenvolver código especifico para cada dispositivo, mas a API de desenvolvimento do UWP facilita muito esse trabalho, evitando ter que reescrever a aplicação para cada plataforma.

O SQLite é um banco de dados muito leve escrito em C. Quase todos os dispositivos móveis utilizam esse banco de dados para o armazenamento de dados. Isso porque esses dispositivos muitas vezes não tem um poder computacional muito grande, ou eles devem economizar o máximo possível de energia, por isso o SQLite é uma excelente ferramenta para esses dispositivos. O SQLite está disponível em todos os dispositivos Android, e também nos dispositivos da Universal Windows Platform, como o WindowsPhone, o Windows e o XBox.

Para demonstrar como usar o SQLite com o UWP, esse artigo mostrará como configurar e desenvolver uma aplicação. A aplicação consistirá numa lista de compras, as compras serão cadastradas em um banco de dados, e existirá uma tela para ver as compras já cadastradas. Essa aplicação será desenvolvida com o Visual Studio 2015 Community, que é livre para estudos e testes. Na seção Links você encontra o endereço para o download dessa ferramenta.

Configuração da Aplicação

Para utilizar o SQLite em uma aplicação do UWP é necessário fazer duas configurações simples no Visual Studio. Primeiro é necessário baixar o suporte ao SQLite no Visual Studio, para isso vá até o menu Tools -> Extensions, depois vá a aba Online, e faça uma busca por sqlite, depois basta seguir as instruções da ferramenta para baixar esse suporte. A Figura 1 mostra a tela onde é feita está configuração, onde está selecionado o componente que deve ser instalado.

Figura 1. Instalando o suporte ao SQLite no Visual Studio

Depois é necessário colocar na configuração da aplicação a dependência para o SQLite, para que seja possível usar os pacotes de código para isso. Assim, vá no menu Project -> Manage nuGet Packages. Nessa tela faça uma busca por SQLite, e instale o pacote do SQLite na aplicação. A Figura 2 mostra a tela para fazer essa configuração e qual componente deve ser instalado.

Figura 2. Configuração do pacote do SQLite na aplicação

Desenvolvimento da Aplicação

Em uma aplicação UWP é utilizado a linguagem C#, que é uma linguagem orientada a objetos da Microsoft. Além do C#, para o desenvolvimento das interfaces de usuários (User Inteface - UI) é utilizada a linguagem XAML (Extensible Application Markup Language), que é uma linguagem de marcação simples, que contém os principais componentes para o desenvolvimento de UI, como formulários, listas e tabelas. Todo XAML tem uma classe C# associada, chamada de Code behind, que é a classe que controla os eventos que acontecem na visão.

Na aplicação desenvolvida nesse artigo, será possível cadastrar uma lista de compras feitas por um usuário com nome do produto, preço e a data da compra. Para representar esses dados, será necessária uma classe Compra com os atributos e os get e set. A Listagem 1 mostra o código dessa classe.

Listagem 1. Classe Compra

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
   
  namespace App9
  {
      class Compra
      {
   
          public string Nome { get; set; }
          public float Preco { get; set; }
          public DateTime Data { get; set; }
   
      }
  }

Os acessos ao banco de dados serão centralizados em uma classe, para facilitar a manutenção do código. A Listagem 2 mostra o código da classe CompraBD. Nessa classe existem três métodos, o LoadDatabase, que criar o banco caso ele não exista ou abre o banco caso ele já exista. O SalvarCompra, que salva uma compra passada como parâmetro. O DeletarCompra que exclui uma compra passada por parâmetro, e o ListarCompras, que retorna uma lista com todas as compras cadastradas. É importante notar que nessa classe deve ser utilizado o namespace do SQLite, com a linha de código using SQLite.

Listagem 2. Classe que faz o acesso ao banco de dados

  using SQLite;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
   
  namespace App9
  {
      class CompraBD
      {
   
          public static SQLiteConnection conn;
          public static void LoadDatabase()
          {
              conn = new SQLiteConnection("sqlitepcldemo.db");
              conn.CreateTable<Compra>();
          }
   
          public static void SalvarCompra(Compra compra)
          {
              conn.Insert(compra);
          }
   
          public static void DeletarCompra(Compra compra)
          {
              conn.Delete(compra);
          }
   
          public static List<Compra> ListaCompras()
          {
              List<Compra> retorno = new List<Compra>();
              var result = conn.Query<Compra>("Select Nome, Preco, Data FROM compra");
              foreach (var item in result)
              {
                  retorno.Add(item);
              }
              return retorno;
          }
          
      }
  }

O método que cria ou abre o banco de dados da aplicação deve ser executado sempre que a aplicação é aberta. Para isso, é necessário colocar uma chamada a esse método no OnLaunched da classe App, que sempre executa assim que a aplicação é chamada. Essa classe já tem diversas linhas de código que não iremos tratar nesse artigo. A Listagem 3 mostra o código que deve ser adiciona na classe. Não é necessário fazer nenhuma outra alteração na classe.

Listagem 3. Código da classe App.xaml.cs

  namespace App9
  {
    
      sealed partial class App : Application
      {
          protected override void OnLaunched(LaunchActivatedEventArgs e)
          {
              CompraBD.LoadDatabase();
              ….
          }
     }
  }

Depois dessas implementações, podemos começar a codificar as telas da aplicação. Primeiro, a tela inicial da aplicação, que terá apenas dois botões para que o usuário navegue para as telas de cadastro e listagem. A Listagem 4 mostra o código da tela, que é organizada em um <StackPanel> que coloca um componente embaixo do outro. Dentro do painel, existe um <TextBlock> com o nome da tela, e dois botões, um que vai para a tela de cadastro e outro para a tela de listagem.

Listagem 4. Código da tela principal da aplicação

  <Page
      x:Class="App9.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App9"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">
   
      <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
          <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
              <TextBlock Text="Lista de Compras" Width="200" Margin="20" FontSize="20" HorizontalAlignment="Center"/>
              <Button Content="Cadastrar" Margin="20"  Width="200" HorizontalAlignment="Center" Click="Button_Click"/>
              <Button Content="Listar" Margin="20" Width="200" HorizontalAlignment="Center" Click="Button_Click_1"/>
          </StackPanel>
      </Grid>
  </Page>

A Figura 3 mostra a tela inicial da aplicação, nela é possível observar o título da aplicação, e os dois botões para a navegação para as telas de cadastro e listagem de compras.

Figura 3. Tela inicial da aplicação

Toda tela em uma aplicação UWP tem uma classe chamada de code-behind, que serve para implementar as ações da tela. Na tela principal existem duas ações simples, apenas a navegação da página principal para as outras telas da aplicação, é isso que é feito nos métodos Button_Click, e Button_Click_1. A Listagem 5 mostra o código dessa classe.

Listagem 5. Code-Behind da tela MainPage

  namespace App9
  {
      public sealed partial class MainPage : Page
      {
          public MainPage()
          {
              this.InitializeComponent();
          }
   
          private void Button_Click(object sender, RoutedEventArgs e)
          {
              this.Frame.Navigate(typeof(CadastrarCompra));
          }
   
          private void Button_Click_1(object sender, RoutedEventArgs e)
          {   
              this.Frame.Navigate(typeof(ListarCompras));
          }
      }
  }

A próxima tela, é a de cadastro de compras. Essa tela também tem um <StackPanel> com dois <TextBox> nela, um para o cadastro do nome e a outra para o preço da compra. Além disso, é utilizado o componente <DatePicker> para o cadastro da data da compra. Por último existe apenas um botão que irá chamar a ação de cadastrar o produto em um banco de dados do SQLite. A Listagem 6 mostra o código dessa tela.

Listagem 6. Tela de cadastro de compras

  <Page
      x:Class="App9.CadastrarCompra"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App9"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">
   
      <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
          <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
              <TextBlock Text="Cadastro de Compras" Width="200" Margin="20" FontSize="20" HorizontalAlignment="Center"/>
              <TextBox PlaceholderText="Nome do Produto" Name="Nome" Width="200" Margin="10" />
              <TextBox PlaceholderText="Preço do Produto" Name="Preco" Width="200" Margin="10" />
              <DatePicker Name="DataCompra" Width="200" Margin="10" />
              <Button Content="Cadastrar" Width="100" HorizontalAlignment="Center" Click="Button_Click"/>
          </StackPanel>
      </Grid>
  </Page>

A Figura 4 mostra a tela de cadastro de compras. A tela tem dois campos de texto, um para o nome e o outro para o preço do produto comprado, um campo para o cadastro data da compra e um botão para efetuar o cadastro.

Figura 4. Tela de cadastro de compra

A classe da tela de cadastro de compra é bastante simples, ela tem apenas o método Button_Click para implementar a ação do botão de cadastrar. O que esse método faz é apenas criar um objeto da classe Compra, e passar esse objeto para o método SalvarCompra da classe CompraBD, que irá salvar essa compra no banco de dados do SQLite. Depois, é feita a navegação de volta para a tela principal da aplicação. A Listagem 7 mostra o código dessa classe.

Listagem 7. Code-Behind da tela de cadastro de compra

  namespace App9
  {
      public sealed partial class CadastrarCompra : Page
      {
          public CadastrarCompra()
          {
              this.InitializeComponent();
          }
   
          private void Button_Click(object sender, RoutedEventArgs e)
          {
   
              Compra compra = new Compra();
              compra.Nome = Nome.Text;
              compra.Preco = Convert.ToSingle(Preco.Text);
              compra.Data = DataCompra.Date.DateTime;
   
              CompraBD.SalvarCompra(compra);
   
              this.Frame.Navigate(typeof(MainPage));
          }
      }
  }

A tela de listagem de compras utiliza o componente ListView para mostrar a lista de todas as compras que foram cadastradas. Para isso, é utilizado outro tipo de classe, o ViewModel, que é um padrão de projeto que indica que toda tela deve ter uma classe para fornecer os dados para ela. Isso é configurado logo no começo do código com a tag <Page.DataContext> que define a classe CompraViewModel como a ViewModel dessa tela. A Listagem 8 mostra o código dessa tela.

Listagem 8. Tela de listagem de compras

  <Page
      x:Class="App9.ListarCompras"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App9"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:vm="using:App9"
      mc:Ignorable="d">
   
      <Page.DataContext>
          <vm:CompraViewModel />
      </Page.DataContext>
   
      <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
          <Grid.ColumnDefinitions>
              <ColumnDefinition/>
              <ColumnDefinition/>
          </Grid.ColumnDefinitions>
   
          <ListView Name="lvPessoas" ItemsSource="{Binding Items}" Header="{Binding ListName}" Grid.Column="0">
              <ListView.ItemTemplate>
                  <DataTemplate>
                      <StackPanel>
                                     <TextBlock Name="tbNome" Text="{Binding Nome}" FontSize="20" Tapped="tbData_Tapped"/>
                                     <TextBlock Name="tbPreco" Text="{Binding Preco}" FontSize="16" Tapped="tbData_Tapped" />
                      </StackPanel>
                  </DataTemplate>
              </ListView.ItemTemplate>
          </ListView>
   
          <Button Content="Voltar" Grid.Column="1" Click="Button_Click" />
      </Grid>
  </Page>

A Figura 5 mostra a tela de listagem de compras, os dados exibidos são o nome do produto e o preço. Na tela, há também um botão para voltar para a tela inicial da aplicação.

Figura 5. Tela de listagem de compras

Outra coisa interessante dessa classe é a utilização do evento Tapped, que é o evento de toque em uma tela touch screen ou o do clique no mouse em um computador em um <TextBlock>. Caso o usuário clique ou toque no texto, será executado o evento tbData_Tapped que está na classe code-behind da tela. A Listagem 9 mostra o código dessa classe, ela tem dois métodos, um para tratar o evento tapped já citado, e que vai levar a aplicação para uma tela onde serão exibidos os detalhes da compra. O outro método é para tratar o evento de clique no botão voltar, esse enveto levará o usuário de volta para a tela inicial da aplicação.

Listagem 9. Classe Code-Behind da tela de listagem de compras

  namespace App9
  {
   
      public sealed partial class ListarCompras : Page
      {
          public ListarCompras()
          {
              this.InitializeComponent();
          }
   
          private void tbData_Tapped(object sender, TappedRoutedEventArgs e)
          {
              Compra compra = (Compra)((TextBlock)sender).DataContext;
              this.Frame.Navigate(typeof(Detalhes), compra);
   
          }
   
          private void Button_Click(object sender, RoutedEventArgs e)
          {
              this.Frame.Navigate(typeof(MainPage));
          }
      }
  }

Para recuperar os dados do SQLIte, e mostrá-los na tela de listagem, é necessário implementar a classe ViewModel, essa tela usa uma lista de compras do tipo ObservableCollection, que funciona da mesma forma que um List, porém, ele é indicado quando é utilizado o ViewModel, pois assim, quando a lista é atualizada, essa atualização é refletida na tela também. Os dados que são recuperados do SQLite são colocados na lista no construtor da classe. A Listagem 10 mostra o código dessa classe.

Listagem 10. View Model da tela de listagem de compras

  namespace App9
  {
      class CompraViewModel
      {
          
          public CompraViewModel()
          {
              ListName = "Lista de Compras";
              List<Compra> compras = CompraBD.ListaCompras();
              for (int i = 0; i < compras.Count; i++)
              {
                  Compra compra = compras.ElementAt(i);
                  this.Items.Add(compra);
              }
   
          }
   
          public ObservableCollection<Compra> Items
          {
              get; set;
          } = new ObservableCollection<Compra>();
   
          public string ListName { get; set; }
   
      }
  }

A próxima tela, é a que mostra os detalhes de uma compra que o usuário selecionou na tela de listamgem de compras. Nessa tela há três <TextBlock>, um para cada informação da compra, o nome, o preço e a data. A Listagem 11 mostra o código dessa tela.

Listagem 11. Tela de detalhes de uma compra

  <Page
      x:Class="App9.Detalhes"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App9"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">
   
      <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
          <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
              <TextBlock Name="NomeCompra" />
              <TextBlock Name="PrecoCompra" />
              <TextBlock Name="DataCompra" />
              <Button Content="Voltar" Click="Button_Click" />
          </StackPanel>
      </Grid>
  </Page>

A Figura 6 mostra a tela de detalhes de uma compra. Nessa tela, são mostrados os dados da compra, o nome, o preço e a data, e também há um botão Voltar, que faz a aplicação retornar para a tela de listagem de compras.

Figura 6. Tela de detalhes de compra

A classe da tela de detalhes de compra é bastante simples, ela tem o método OnNavigatedTo, que é executado assim que a aplicação é direcionada para essa tela, esse método pega a compra que foi passada como parâmetro quando o usuário tocou na tela da listagem de compras e os coloca nos componentes da tela que foram definidos anteriormente. A Listagem 12 mostra o código dessa classe.

Listagem 12. Code-Behind da tela de detalhes de compra

  namespace App9
  {
      public sealed partial class Detalhes : Page
      {
          public Detalhes()
          {
              this.InitializeComponent();
          }
   
          protected override void OnNavigatedTo(NavigationEventArgs e)
          {
              Compra compra = (Compra)e.Parameter;
              NomeCompra.Text = "Nome: " + compra.Nome;
              PrecoCompra.Text = "Preço: " + Convert.ToString(compra.Preco);
              DataCompra.Text = "Data: " + compra.Data.ToString("dd/MM/yyyy");
          }
   
          private void Button_Click(object sender, RoutedEventArgs e)
          {
              this.Frame.Navigate(typeof(ListarCompras));
          }
      }
   
  }

Esse artigo mostrou como utilizar o SQLite na Universal Windows Platform, esse banco de dados pode ser utilizado quando se necessita economizar recursos do dispositivo, ou quando se necessita apenas de um banco de dados simples. Isso é muito comum em aplicações em dispositivos móveis.

Espero que este artigo seja útil! Até a próxima!

Links

Download Visual Studio
https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx

Universal Windows Platform
https://msdn.microsoft.com/en-us/library/windows/apps/dn894631.aspx

SQLite
https://www.sqlite.org/