WPF - Manutenção de dados com DataGrid e LINQ to SQL


O WPF - Windows Presentantion Fundation - possui muitos componentes com grande facilidade de configuração e a partir de 2008 (a partir da liberação da versão 3.5 da NET Framework SP1 e do Visual Studio 2008 SP1) foi incluído o componente DataGrid de grande versatilidade e que veio preencher uma lacuna que faltava entre os componentes WPF. Então vamos dar uma espiada no controle DataGrid...

O componente DataGrid da WPF faz parte do WPF ToolKit e para incluir este componente em seu projeto você deve seguir os seguintes passos:

Neste artigo eu pretendo mostrar como podemos usar o componente DataGrid para efetuar a manutenção de dados diretamente no Grid de forma simples e direta.

Para isso eu vou usar o Visual Studio 2008 Service Pack 1 e um banco de dados Cadastro.mdf criado no SQL Server contendo uma tabela Produtos com uma estrutura bem simples  conforme mostra a visão do Server Explorer na figura abaixo :

Abra o Visual Studio 2008 SP1 e crie um novo projeto do tipo Windows usando o template WPF Aplication com o nome CRUDDataGridWPF e clique OK;

A seguir no menu Project selecione Add New Item e a seguir o template LINQ to SQL Classes informando o nome Produtos.dbml e clicando em Add;

No descritor LINQ arraste a tabela Produtos a partir do Server Explorer para gerar a entidade Produto mapeada pelo LINQ to SQL conforme a figura abaixo:

Com isso já podemos efetuar o tratamento dos dados sem usar consultas SQL nem objetos ADO .NET em nosso código iremos tratar somente com os objetos mapeados.

Vamos criar a interface usando o componente DataGrid e o TextBlock a partir da ToolBox. Selecione o arquivo Window1.xaml e defina a seguinte interface:

Estamos usando o componente DataGrid e TextBlock. Veja abaixo como ficou o código XAML:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Custom="http://schemas.microsoft.com/wpf/2008/toolkit" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="CRUDDataGridWPF.Window1"
    Title="Manutenção de dados com DataGrid" Height="300" Width="627" ResizeMode="CanMinimize" mc:Ignorable="d">
    <Grid>
    	<Grid.RowDefinitions>
    		<RowDefinition Height="0.912*"/>
    		<RowDefinition Height="0.088*"/>
    	</Grid.RowDefinitions>
        <Custom:DataGrid x:Name="dgData" Margin="0" AutoGenerateColumns="False" 
                         RowEditEnding="dgData_RowEditEnding" 
                         CommandManager.PreviewExecuted="dgData_PreviewExecuted"
                         CanUserAddRows="True" CanUserDeleteRows="True">
            <Custom:DataGrid.Columns>
                <Custom:DataGridTextColumn Binding="{Binding id}" Header="ID" IsReadOnly="True" Width="80"/>
                <Custom:DataGridTextColumn Binding="{Binding nome}" Header="Nome" Width="200"/>
                <Custom:DataGridTextColumn Binding="{Binding preco}" Header="Preço" Width="300"/>
            </Custom:DataGrid.Columns>    
        </Custom:DataGrid>
        <TextBlock x:Name="txtStatus" Margin="8,4.89,12,0" Grid.Row="1" 
                   TextWrapping="Wrap" d:LayoutOverrides="Height" Background="Aquamarine" Foreground="DarkBlue" />
    </Grid>
</Window>

 

Observando o código XAML notamos a utilização dos eventos anexados CommandManager.PreviewExecuted e RowEditEnding.

O evento PreviewExecuted ocorre quando o método Execute de um RoutedCommand é chamado. O CommandManager é o responsável por gerenciar os comandos roteados.

Por padrão o DataGrid da WPF irá comitar uma linha quando o foco for perdido , a tecla ENTER for pressionada , ou via código forçando commit na linha.

Ocorre que não existe uma método no DataGrid que permite que você informe qual entrada será comitada na linha, mas existem eventos que permitem que você cancela a operação de edição.

Vejamos então como fica o código do arquivo code-behind WIndow1.xaml.cs;

Primeiro devemos declarar a utilização do namespace System.Data.Linq:

using System.Data.Linq;

No evento WindowLoaded temos o código que será executado na carga da aplicação WPF e que deverá fazer a leitura dos dados e sua exibição no DataGrid:

    void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            ProdutosDataContext context = new ProdutosDataContext();
            
            var resultado = from p in context.Produtos
                                   select p;
            if (resultado.ToList().Count > 0)
            {
                txtStatus.Text = "Produtos lidos com sucesso.";
            }
            dgData.ItemsSource = resultado.ToList();
        }

O código associado ao evento RowEditEnding que será responsável por criar e atualizar novas informações no DataGrid;

Note que após selecionar o produto desejado usando a consulta LINQ  verificamos se o produto existe e em caso positivo usamos o método InsertOnSubmit(objeto) e em seguida o método SubmitChanges() do contexto para persistir as inclusões;

Se o produto já existir então apenas atribuímos as alterações e persistimos usando  SubmitChanges();

    private void dgData_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
        {
            if (e.EditAction == DataGridEditAction.Commit)
            {
                ProdutosDataContext context = new ProdutosDataContext();

                Produto p = e.Row.DataContext as Produto;
                var resultado = (from prd in context.GetTable<Produto>()
                                       where prd.id == p.id
                                       select prd).SingleOrDefault();
                'o produto não existe então vamos incluir
                if (resultado == null)
                {
                    Table<Produto> pTabela = context.GetTable<Produto>();
                    Produto produto = new Produto();
                    produto.nome = p.nome;
                    produto.preco = p.preco;
                    pTabela.InsertOnSubmit(produto);
                    pTabela.Context.SubmitChanges();
                    txtStatus.Text = "Dados Incluidos com sucesso";
                }
                else //o produto já existe vamos alterar
                {
                    resultado.nome = p.nome;
                    resultado.preco = p.preco;
                    context.SubmitChanges();
                    txtStatus.Text = "Dados atualizados com sucesso";
                }
            }
        } 

 

O código associado ao evento PreviewExecuted que será responsável pela exclusão da informação no DataGrid;

Localizamos e selecionamos o produto desejado usando uma consulta LINQ e em seguida verificamos se foi pressionada a tecla DEL. Após solicitar a confirmação o produto é deletado usando o método DeleteOnSubmit(objeto) e as alterações persistidas na fonte de dados usando o SubmitChanges();

 private void dgData_PreviewExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            ProdutosDataContext context = new ProdutosDataContext();
            Produto produto = dgData.SelectedItem as Produto;

            if (produto != null)
            {
                var produtoEncontrado = (from p in context.GetTable<Produto>()
                                                       where p.id == produto.id
                                                       select p).SingleOrDefault();
                if (e.Command == DataGrid.DeleteCommand)
                {
                    if (!(MessageBox.Show("Deseja excluir o registro selecionado ?", 
                        "Confirma Exclusão !", MessageBoxButton.YesNo) == MessageBoxResult.Yes))
                    {
                        e.Handled = true;
                    }
                    else
                    {
                        context.Produtos.DeleteOnSubmit(produtoEncontrado);
                        context.SubmitChanges();
                        txtStatus.Text = "Dados excluídos com sucesso.";
                    }
                }
            }
        }

Executando o projeto teremos:

1- A apresentação dos dados no DataGrid no início da aplicação obtido pela execução do código no evento  WindowLoaded ();

2- Selecionando uma célula podemos alterar o valor e persistir na fonte de dados. Resultado obtido pelo código associado ao evento RowEditEnding;

3-  E O código associado ao evento PreviewExecuted  permite selecionar uma linha e pressionando a tecla DEL podemos excluir um registro da fonte de dados:

E com isso acabamos de mostrar como podemos usar o DataGrid e implementar

Aguarde mais dicas sobre WPF.

Pegue o projeto completo aqui: CRUDDataGridWPF.zip

Eu sei é apenas WPF, mas eu gosto...

Referências:


José Carlos Macoratti