VB .NET - Trabalhando com DataGridView Dinâmico

 Neste artigo vou mostrar como podemos trabalhar com o controle DataGridView incluindo e removendo linhas e realizando a validação via código.


Neste artigo vou mostrar um exemplo prático bem simples onde vamos incluir e remover linhas do DataGridView de forma dinâmica e ainda realizar a validação dos dados via código usando eventos do controle.

No exemplo do artigo basta clicar no botão Incluir Linha ou pressionar F7 para incluir uma nova linha no DataGridView a seguir informar a quantidade e o valor. Durante este processo é realizado o cálculo do valor total e validação da entrada do usuário.

Para remover uma linha clique no botão Excluir Linha ou pressione F8 na linha selecionada.

Vou destacar as principais rotinas e eventos usados no projeto, que já estão comentadas.

Recursos Usados:

Criando o projeto no VS Community 2017

Abra no VS community 2017 e no menu File clique em New Project;

A seguir selecione o template Visual Basic -> Windows -> Windows Forms Application e informe o nome DataGridViewDinamico e clique em OK;

Agora abra o formulário Form1.vb e inclua os seguintes controles no formulário:

Disponha os controles conforme o leiaute da figura abaixo:

Definindo o código do formulário

Inclua os seguintes namespaces no formulário:

1- Código do construtor do formulário

No construtor do formulário, Sub New() , temos o código que vai chamar o método InicializaGrid():

    Public Sub New()
        InitializeComponent()
        Call InicializaGrid()
    End Sub

2- Código do método InicializaGrid()

Neste código definimos as propriedades do Grid suas colunas e cabeçalhos:

 Private Sub InicializaGrid()
        With dgvDados
            'define propriedades do datagridview
            .RowHeadersVisible = False
            .AllowUserToAddRows = False
            .AllowUserToDeleteRows = False
            .AllowUserToResizeRows = False
            .MultiSelect = False
            .ReadOnly = False
            ' Colunas
            .Columns.Add("PK", "Chave Primária")                            '// Col = 0
            .Columns.Add("ProdutoID", "Produto ID")                      '// Col = 1
            .Columns.Add("ProdutoNome", "Nome do Produto")      '// Col = 2
            .Columns.Add("Quantidade", "Quantidade")                   '// Col = 3
            .Columns("Quantidade").ValueType = GetType(Integer)
            .Columns.Add("Preco", "Preço Unitário")                         '// Col = 4
            .Columns("Preco").ValueType = GetType(Double)
            .Columns.Add("Total", "Total")                                       '// Col = 5
            .Columns("Total").ValueType = GetType(Double)
            ' Auto resize em todas as colunas.
            .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
            .AutoResizeColumns()
            .Font = New Font("Tahoma", 8.25)
            ' Coluna Total - somente leitura
            With .Columns("Total")
                .ReadOnly = True
                .DefaultCellStyle.BackColor = System.Drawing.Color.LightGoldenrodYellow
                .DefaultCellStyle.ForeColor = System.Drawing.Color.Red
                .DefaultCellStyle.Font = New Font(dgvDados.Font, FontStyle.Bold)
            End With
            ' Estilo do cabeçalho
            With .ColumnHeadersDefaultCellStyle
                .BackColor = Color.Navy
                .ForeColor = Color.White
                .Font = New Font("Tahoma", 8.25)
                .Font = New Font(dgvDados.Font, FontStyle.Bold)
            End With
            ' Alinha somente as colunas 3 a 5
            For i As Byte = 3 To 5
                ' Alinha Cabeçalho
                .Columns(i).HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight
                ' Alinha Celula
                .Columns(i).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
            Next
        End With
    End Sub

3- Código do evento Load do formulário frm

  Private Sub frmGridView_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.CenterToScreen()
        '//define a caixa de texto somente leitura e limpa o conteudo
        txtSomaTotal.ReadOnly = True
        txtSomaTotal.Clear()
    End Sub

 

4 - Código do evento Click do botão - Incluir Linha F7 :

    ' / Adiciona nova linha
    Private Sub btnAdicionar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdicionar.Click
        Dim Position As Integer = dgvDados.Rows.Count - 1
        Dim PK As Integer = 1   '// Valor inicial sem linhas
        '// Pega o valor da ultima linha
        Dim UltimaLInha As New DataGridViewRow
        ''// Tem linhas ?
        If Position >= 0 Then
            '// Pega as linhas do DataGridView
            UltimaLInha = dgvDados.Rows.OfType(Of DataGridViewRow).Last()
            '// Incrementa a PK (Column = 0)
            PK = UltimaLInha.Cells(0).Value + 1
        End If
        '// dados de exemplo: chave, codigo do produto, nome do produto, quantidade e valor
        Dim linha As String() = New String() {PK, "PROD00" & PK, "Produto " & PK, 1, 0.0, 0.0}
        '//adiciona a linha no grid
        dgvDados.Rows.Add(linha)
        '// Foco na celula da coluna(3) ou Quantidade
        dgvDados.CurrentCell = dgvDados.Rows(dgvDados.RowCount - 1).Cells(3)
        dgvDados.Focus()
        ' //calcula o total
        Call CalculaSomaTotal()
    End Sub

5- Código do evento Click do botão - Excluir Linha F8 :

    '/ Remover linha selecionada
   Private Sub btnRemoverLinha_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRemover.Click
        '/se não tem linhas então sai
        If dgvDados.RowCount = 0 Then Exit Sub
        '//remove a linha atual selecionada
       dgvDados.Rows.Remove(dgvDados.CurrentRow)
       dgvDados.Refresh()
        '//se existem linhas calcula a soma 
       If dgvDados.RowCount > 0 Then Call CalculaSomaTotal()
   End Sub

6- Código do método CalculaSomaTotal():

     ' / Calcula a soma total  (Coluna Index = 5)
    Private Sub CalculaSomaTotal()
        'define o valor igual a zero
        txtSomaTotal.Text = "0.00"
        'percorre as linhas do grid
        For i As Byte = 0 To dgvDados.RowCount - 1
            ' Converte a célula da coluna 5 para Double (usa CDbl ao estilo VB6 ...)
            txtSomaTotal.Text = CDbl(txtSomaTotal.Text) + CDbl(dgvDados.Rows(i).Cells(5).Value)
        Next
        '//formata e exibe o valor da soma
        txtSomaTotal.Text = Format(CDbl(txtSomaTotal.Text), "#,##0.00")
    End Sub

7-  Código do eventos do DataGridView usados no exemplo:

    ' / Antes de editar os dados
    Private Sub dgvDados_CellBeginEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles dgvDados.CellBeginEdit
        '//obtem a quantidade , e preço unitário das linhas do grid ; calcula soma e exibe na respectiva célula formatando o valor
        Dim Quantidade As Integer = dgvDados.Rows(e.RowIndex).Cells(3).Value
        Dim PrecoUnitario As Double = dgvDados.Rows(e.RowIndex).Cells(4).Value
        dgvDados.Rows(e.RowIndex).Cells(5).Value = (Quantidade * PrecoUnitario).ToString("#,##0.00")
    End Sub
    ' / Depois de pressionar o Enter para editar
    Private Sub dgvDados_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvDados.CellEndEdit
        '//verifica qual coluna foi editada
        Select Case e.ColumnIndex
            Case 3, 4 ' Indice da coluna = 3 (Quantidade), Column Index = 4 (Preco)
                ' Quantidade
                ' Se o valor for Null atribui zero
                If IsDBNull(dgvDados.Rows(e.RowIndex).Cells(3).Value) Then
                    dgvDados.Rows(e.RowIndex).Cells(3).Value = 0
                End If
                Dim Quantidade As Integer = dgvDados.Rows(e.RowIndex).Cells(3).Value
                '// =============== USA  A PROPRIEDADE TAG  =============== //
                ' manter o valor original em uma local temporario. (Tag Property)
                dgvDados.Tag = Quantidade
                '//verifica se a quantidade é menor que zero 
                If Quantidade <= 0 Then
                    dgvDados.Rows(e.RowIndex).Cells(3).Value = dgvDados.Tag
                    Quantidade = dgvDados.Tag
                End If
                ' Preco
                ' Se o valor for  Null atribui zero
                If IsDBNull(dgvDados.Rows(e.RowIndex).Cells(4).Value) Then
                    dgvDados.Rows(e.RowIndex).Cells(4).Value = 0.0
                End If
                '//define uma variavel com o valor do preco
                Dim PrecoUnitario As Double = dgvDados.Rows(e.RowIndex).Cells(4).Value
                '//atribui o valor na propriedade Tag do grid
                dgvDados.Tag = PrecoUnitario
                'se for menor que zero então retorna o valor anterior
                If PrecoUnitario < 0 Then
                    dgvDados.Rows(e.RowIndex).Cells(4).Value = dgvDados.Tag
                    PrecoUnitario = dgvDados.Tag
                End If
                ' calcula o valor = Quantidade x Preco
                dgvDados.Rows(e.RowIndex).Cells(5).Value = (Quantidade * PrecoUnitario).ToString("#,##0.00")
                '// Chama a soma
                Call CalculaSomaTotal()
        End Select
    End Sub
     Private Sub dgvDados_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) 
          Handles dgvDados.EditingControlShowing
        Select Case dgvDados.Columns(dgvDados.CurrentCell.ColumnIndex).Name
            ' / Pode usar ambas, indice da coluna ou nome do campo
            Case "Quantidade", "Preco"
                '// Para e Inicia o tratamento de evento
                RemoveHandler e.Control.KeyPress, AddressOf ValidKeyPress
                AddHandler e.Control.KeyPress, AddressOf ValidKeyPress
        End Select
    End Sub

Neste código estamos usando os seguintes eventos do DataGridView :

Estamos usando o operador AddresOff que cria uma instância delegada de procedimento que refere-se ao procedimento ValidKeyPress que iremos usar para validar a entrada do usuário. Neste caso estamos delgando o evento KeyPress para o método ValidKeyPress.

8-  Código do método ValidKeyPress que é usado para validar a entrada do usuário e esta associado ao evento KeyPress

    Private Sub ValidKeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
        'define um textbox
        Dim txtbox As TextBox = sender
        ' verifica a célula na qual a tecla foi pressionada para validar
        Select Case dgvDados.CurrentCell.ColumnIndex
            Case 3  ' Quantidade é um Integer
                Select Case e.KeyChar
                    Case "0" To "9"   ' digitos de 0 - 9 permitidos
                    Case ChrW(Keys.Back)    ' backspace permitido para deletar 
                    Case Else ' outra coisa qualquer ....
                        ' True = CPU cancela o evento KeyPress
                        e.Handled = True ' é como se voce nunca tivesse pressionado a tecla
                End Select
            Case 4  ' PrecoUnitario eh um Double
                Select Case e.KeyChar
                    Case "0" To "9"
                        ' permitido ","
                    Case ","
                        ' pode permitir somente um ","
                        If InStr(txtbox.Text, ".") Then e.Handled = True
                    Case ChrW(Keys.Back)
                        '// Retorna False é o valor padrão
                    Case Else
                        e.Handled = True
                End Select
        End Select
    End Sub

Executando o projeto teremos o resultado a seguir:

Pegue o projeto completo aqui:  DataGridViewDinamico.zip

Eu sou a videira, vós as varas; quem está em mim, e eu nele, esse dá muito fruto; porque sem mim nada podeis fazer. 
João 15:5

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 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti