Banco de Dados

6 fev, 2025

WPF – CRUD com SQLite

Publicidade

Hoje veremos como criar uma aplicação WPF e realizar um CRUD básico usando o SQLite. O WPF (Windows Presentation Foundation) é um framework de desenvolvimento de interface de usuário da Microsoft para a criação de aplicativos desktop Windows. Ele faz parte do conjunto de tecnologias do .NET Framework/.NET Core e fornece uma abordagem moderna e poderosa para a criação de interfaces gráficas ricas e interativas.

O WPF utiliza a linguagem de marcação XAML (eXtensible Application Markup Language) para definir a interface do usuário de forma declarativa, separando a lógica de apresentação da lógica de negócios. Isso permite que os desenvolvedores criem interfaces complexas e visualmente atraentes usando um modelo de programação orientado a objetos.

Neste artigo vamos criar uma aplicação WPF para gerenciar informações sobre produtos usando o SQLite.

Recursos usados:

  • VS 2022

  • .NET 7.0

Criando o projeto

No VS 2022 Community vamos criar um projeto usando o template e nomeá-lo como WpfProdutos :

Vamos incluir no projeto os seguintes pacotes nugets:

1- Microsoft.EntityFrameworkCore.Sqlite
2- Microsoft.Extensions.DependencyInjection
3- Microsoft.Extensions.DependencyInjection.Abstractions

A seguir vamos criar no projeto a pasta Data e nesta pasta criar a classe Produto e a classe ProdutoContext :

1- Produto – representa o modelo de domínio

public class Produto
{
  public int Id { get; set; }
  public string? Nome { get; set; }
  public string? Descricao { get; set; }
  public double Preco { get; set; }
  public int Quantidade { get; set; }
}

2- ProdutoContext – representa a classe de contexto que herda de DbContext e faz o mapeamento ORM.


public class ProdutoContext : DbContext
{
  public ProdutoContext(DbContextOptions<ProdutoContext> options): base(options)
  {
    Database.EnsureCreated();
  }

  public DbSet<Produto> Produto { get; set; }

  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
     modelBuilder.Entity<Produto>().HasData(GetProdutos());
     base.OnModelCreating(modelBuilder);
  }

  private List<Produto> GetProdutos()
  {
    return new List<Produto>
    {
      new Produto { Id = 1001, Nome = "Laptop", Preco = 20.02, Quantidade = 10,
 Descricao ="O melhor laptop para jogos"},
      new Produto { Id = 1002, Nome = "Microsoft Office", Preco = 20.99, Quantidade = 50,
 Descricao ="Aplicação Office"},
      new Produto { Id = 1003, Nome = "Lazer Mouse", Preco = 12.02, Quantidade = 20,
Descricao ="Um mouse decente"},
      new Produto { Id = 1004, Nome = "USB Storage", Preco = 5.00, Quantidade = 20,
Descricao ="Armazena ate 256GB de dados"}
    };
  }
}

Neste código, no construtor, estamos usando o o método Database.EnsureCreated() que verifica se o banco de dados foi criado e, se não, o cria com base no modelo definido pelas classes de entidade. Isso garante que o banco de dados esteja criado antes de ser usado.

O método HasData() recebe os dados retornados pelo método GetProdutos() e os insere no banco de dados quando o modelo for criado.

No arquivo App.xaml vamos alterar o código conforme a seguir:


<Application x:Class="WpfProdutos.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfProdutos"
             Startup="OnStartup">

   <Application.Resources>
   </Application.Resources>
</Application>

Neste código estamos especificando um evento chamado “OnStartup” que será tratado na classe App quando a aplicação for iniciada.

Agora no arquivo App.xaml.cs vamos registrar o serviço do contexto e definir o provedor do banco de dados e sua configuração:

using WpfProdutos.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System.Windows;
namespace WpfProdutos;
public partial class App : Application
{
    private readonly ServiceProvider serviceProvider;

    public App()
    {
        ServiceCollection services = new ServiceCollection();        
        services.AddDbContext<ProdutoContext>(options =>
        {
            options.UseSqlite("Data Source = ProdutosDB.db");
        });
        services.AddSingleton<MainWindow>();
        serviceProvider = services.BuildServiceProvider();
    }

    private void OnStartup(object s, StartupEventArgs e)
    {
        var mainWindow = serviceProvider.GetService<MainWindow>();
        mainWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;
        mainWindow.Show();
    }
}

Neste código temos o construtor da classe App onde estão sendo configurados os serviços necessários para a aplicação.

  • ServiceCollection services = new ServiceCollection();: Cria uma instância de ServiceCollection, que é um container para registrar serviços.
  • services.AddDbContext<ProductDBcontext>(option => …);: Registra um serviço de contexto de banco de dados ProductDBcontext usando o SQLite como provedor. A conexão com o banco de dados é especificada como “Data Source = ProdutosDB.db“. Isso indica que a aplicação usará um banco de dados SQLite chamado “ProdutosDB.db”.
  • services.AddSingleton<MainWindow>();: Registra um serviço de MainWindow como um serviço Singleton, o que significa que haverá apenas uma instância desse serviço em toda a aplicação.
  • serviceProvider = services.BuildServiceProvider();: Constrói o provedor de serviços com base nas configurações fornecidas. Agora, o serviceProvider contém todos os serviços configurados.
  • O método OnStartup obtemos o serviço , centralizamos a janela e a exibimos;

Vamos definir o código para criar a interface com usuário usando um DataGrid no arquivo MainWindow.xaml:

<Window x:Class="WpfProdutos.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"
        xmlns:local="clr-namespace:WpfProdutos"
        mc:Ignorable="d"
        Title="MainWindow" Height="550" Width="800">
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="45"/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Label FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5"
               Grid.Row="0" Content="Produtos - CRUD "/>
        <DataGrid x:Name="ProdutoDG" AutoGenerateColumns="False" CanUserAddRows="False" IsReadOnly="True"
                  Grid.Row="1" ColumnWidth="*" Margin="5" IsSynchronizedWithCurrentItem="True" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
                <DataGridTextColumn Header="Nome" Binding="{Binding Nome }"/>
                <DataGridTextColumn Header="Descrição" Binding="{Binding Descricao}"/>
                <DataGridTextColumn Header="Preço" Binding="{Binding Path=Preco, 
                                                            ConverterCulture='pt-BR',StringFormat=C}" />
                <DataGridTextColumn Header="Quantidade" Binding="{Binding Path=Quantidade}"/>
                <DataGridTemplateColumn Header="Editar">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="Edita" Click="SelectProdutoToEdit" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Deletar">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="Deleta" Click="DeleteProduto"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <Grid Grid.Row="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Border Grid.Column="0" Margin="5" BorderThickness="1" BorderBrush="Black">
                <StackPanel  Margin="5">
                    <Label Content="Novo Produto" FontWeight="Bold"
                       HorizontalAlignment="Center" 
                       VerticalAlignment="Center" Margin="5"/>
                    <Grid Name="NovoProdutoGrid">
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <Label Grid.Row="0" Grid.Column="0" Content="Nome"/>
                        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Nome}"/>
                        <Label Grid.Row="1" Grid.Column="0" Content="Descrição"/>
                        <TextBox Grid.Row="1" Grid.Column="2" Text="{Binding Descricao}"/>
                        <Label Grid.Row="2" Grid.Column="0" Content="Preço"/>
                        <TextBox Grid.Row="2" Grid.Column="3" Text="{Binding Preco}"/>
                        <Label Grid.Row="3" Grid.Column="0" Content="Quantidade"/>
                        <TextBox Grid.Row="3" Grid.Column="4" Text="{Binding Quantidade}"/>
                        <Button Grid.Row="4" Grid.ColumnSpan="2" Width="150" Content="Adicionar"
                                                                                          Margin="5" Click="AddItem"
                            HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Grid>
                </StackPanel>
            </Border>
            <Border Grid.Column="1" Margin="5" BorderThickness="1" BorderBrush="Black">
                <StackPanel Margin="5">
                    <Label Content="Editar" FontWeight="Bold"
                       HorizontalAlignment="Center" 
                       VerticalAlignment="Center" Margin="5"/>
                    <Grid Name="UpdateProdutoGrid">
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <Label Grid.Row="0" Grid.Column="0" Content="Nome"/>
                        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Nome}"/>
                        <Label Grid.Row="1" Grid.Column="0" Content="Descrição"/>
                        <TextBox Grid.Row="1" Grid.Column="2" Text="{Binding Descricao}"/>
                        <Label Grid.Row="2" Grid.Column="0" Content="Preço"/>
                        <TextBox Grid.Row="2" Grid.Column="3" Text="{Binding Preco}"/>
                        <Label Grid.Row="3" Grid.Column="0" Content="Quantidade"/>
                        <TextBox Grid.Row="3" Grid.Column="4" Text="{Binding Quantidade}"/>
                        <Button Grid.Row="4" Grid.ColumnSpan="2" Width="150" Click="UpdateItem"
                                Content="Editar" Margin="5"
                            HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Grid>
                </StackPanel>
            </Border>
        </Grid>
    </Grid>
</Window>

A interface gerada tem a seguinte aparência:

Agora vamos definir o código no arquivo code-behind MainWindow.xaml.cs :

using System.Linq;
using System.Windows;
using WpfProdutos.Data;
namespace WpfProdutos;
public partial class MainWindow : Window
{
    ProdutoContext context;
    Produto NovoProduto = new Produto();
    Produto selectedProduto = new Produto();
    public MainWindow(ProdutoContext context)
    {
        this.context = context;
        InitializeComponent();
        GetProdutos();
        NovoProdutoGrid.DataContext = NovoProduto;
    }
    private void GetProdutos()
    {
        ProdutoDG.ItemsSource = context.Produtos.ToList();
    }
    private void AddItem(object s, RoutedEventArgs e)
    {
        if (ValidaDados(NovoProduto))
        {
            context.Produtos.Add(NovoProduto);
            context.SaveChanges();
            GetProdutos();
            NovoProduto = new Produto();
            NovoProdutoGrid.DataContext = NovoProduto;
        }
        else
        {
            MessageBox.Show("Dados informados não são válidos", "Novo Produto - Erro",
                                         MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }
    private void UpdateItem(object s, RoutedEventArgs e)
    {
        if (ValidaDados(selectedProduto))
        {
            context.Update(selectedProduto);
            context.SaveChanges();
            GetProdutos();
        }
        else
        {
            MessageBox.Show("Dados informados não são válidos", "Atualiza Produto - Erro", 
                                        MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }
    private void SelectProdutoToEdit(object s, RoutedEventArgs e)
    {
        selectedProduto = (s as FrameworkElement).DataContext as Produto;
        UpdateProdutoGrid.DataContext = selectedProduto;
    }
    private void DeleteProduto(object s, RoutedEventArgs e)
    {
        var produtoToDelete = (s as FrameworkElement).DataContext as Produto;
        context.Produtos.Remove(produtoToDelete);
        context.SaveChanges();
        GetProdutos();
    }
    private bool ValidaDados(Produto produto)
    {
        if (produto.Id == 0) return false;
        if (produto.Nome == null) return false;
        if (produto.Descricao == null) return false;
        if (produto.Quantidade == 0) return false;
        return true;
    }
}

Neste código temos a lógica para realizar a inclusão e alteração dos dados de produtos usando o EF Core.

Pegue o código do projeto aqui:  WpfProdutos.zip