VB .NET - Manipulando o DataGridView


O DataGridView é um controle com 1001 utilidades, flexível e poderoso se comparados com controles grids das versões anteriores do VB (lembra do DBGrid, MSFlexGrid, DataGrid, etc...)

Embora não seja complicado de usar como toda novidade desperta curiosidade e dúvidas, e, por este motivo este artigo procurar mostrar as maneiras mais comuns e úteis de usar o controle DataGridView.

Para começar você vai ter que ter instalado os seguintes recursos:

O primeiro passo e abrir o VB 2005 Express e criar uma aplicação Windows Forms via opção File->New Project com o nome de datagridViewTotal

Aqui é o ponto de partida para a nossa jornada, vamos lá...

Usando DataGridView com Arrays

Vamos definir um array chamado vetor com dois elementos e vincular o array ao DataGridView usando a propriedade DataSource:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'==========================================
'outras maneiras de declarar e iniciar um array
'(a)
'
Dim vetor(2) As String
'vetor(0) = "Super CD VB 40,00"
'vetor(1) = "Super DVD.NET 50,00
"
'(b)
'
Dim vetor() As String
'vetor = New String() {"Super CD VB 40,00", "Super DVD .NET 50,00"}

'=============================================


Dim vetor() As String = {"Super CD VB 40,00", "Super DVD .NET 50,00"}
DataGridView1.DataSource = vetor

End Sub

Opa ! mas o que aconteceu ??? O resultado não é o esperado. Por que ?

Você esperava que os elementos do array fossem exibidos mas somente o tamanho de cada elemento foi exibido.

O motivo deste comportamento é que o DataGridView procura pela primeira propriedade pública do objeto ao qual esta vinculado e a primeira propriedade pública de um array de strings é o tamanho de cada elemento contido no array.

Para fazer da maneira correta devemos envolver o array de string em uma classe que exponha propriedades públicas que retornem o conteúdo de cada um dos elementos que desejamos exibir.

Podemos fazer isso criando uma classe e definindo um construtor e uma propriedade pública para ter acesso ao valor de cada elemento do vetor:

No menu Project -> Add Class selecione o template Class e informe o nome vetor.vb para o nome da classe a seguir inclua o seguinte código na classe:


Voltando ao formulário form1.vb e alterando o código para usar a classe criada temos:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

'Dim vetor() As String = {"Super CD VB 40,00", "Super DVD .NET 50,00"}
'==========================================
'outras maneiras de declarar e iniciar um array
'(a)
'Dim vetor(2) As String
'vetor(0) = "Super CD VB 40,00"
'vetor(1) = "Super DVD.NET 50,00"
'(b)
'Dim vetor() As String
'vetor = New String() {"Super CD VB 40,00", "Super DVD .NET 50,00"}
'=============================================

Dim valores() As Vetor = {New Vetor("Super CD VB 40,00"), New Vetor("Super DVD .NET 50,00")}
DataGridView1.DataSource = valores

End Sub

Da mesma forma podemos vincular o controle DataGridView a um objeto mais complexo.

Usando DataGridView com DataSets Tipados

Um uso muito comum do controle DataGridView é a vinculação a uma tabela de um banco de dados. Podemos efetuar esta tarefa usando um DataSet tipado.

Vamos incluir um dataset tipado ao projeto clicando sobre o nome do projeto com o botão direito do mouse e seleciona a opção Add New Item. Na janela selecione o template DataSet e clique Add;

Habilite o DataBase Explorer no menu View e localize o banco de dados Northwind.mdf , expanda o objeto Tables e em seguida arraste e solte a tabela Customers no descrito DataSet1.xsd conforme a figura abaixo:

No próximo passo vamos vincular o dataset ao DataGridView e podemos fazer isto das seguintes formas:

1- Vincular o DataGridView diretamente ao adapter da tabela Customers:

Inclua o projeto a seguinte declaração :

Imports dataGridViewTotal.DataSet1TableAdapters

A seguir inclua um botão de comando no formulário e inclua o código abaixo no evento Click do botão:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  'cria uma instância da TableAdapter
  Dim da As New CustomersTableAdapter
  'vincula o TableAdapter ao DataGridView
  DataGridView1.DataSource = da.GetData
End Sub

Executando o projeto temos:

2- Vinculando o DataGridView a um BindginSource

Para este exemplo você deve criar um TableAdapter para a tabela Customers. Para fazer isso inclua um novo DataSet no projeto e arraste a partir da janela DataBase Explorer a tabela Customers do banco de dados Northwind.mdb.

A seguir Inclua no projeto a seguinte declaração (se ainda não o fez) :

Imports dataGridViewTotal.DataSet1TableAdapters

Agora insira um novo botão de comando e no evento Click do botão insira o código:

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

'cria uma instância da TableAdapter
Dim da As New CustomersTableAdapter
'cria uma instância de um BindingSource
Dim bindsrc As New BindingSource

'define a fonte de dados para o bindingsource e obtém os dados do método GetData do TableAdapter
bindsrc.DataSource = da.GetData
'vincula o BindingSource ao DataGridView
DataGridView1.DataSource = bindsrc

End Sub

Usando o DataGridView com DataSets não tipados

Você também pode definir o dataset via código vinculando em seguida o componente ao DataGridView.

Primeiro temos que criar e preencher um dataset para em seguida atribuir à propriedade DataSource do DataGridView o dataset gerado.

No código estou atribuindo à  propriedade DataMember a tabela gerada no dataset. Uma outra maneira de obter o mesmo resultado seria atribuir diretamente a propriedade DataSource a tabela gerada que no caso seria a primeira tabela (pois só temos uma) : ds.tables(0). Neste caso não necessitaríamos de definir o Datamember.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 

'define a string de conexao

Dim connStr As String =  "Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True"


'define a instrução sql

Dim sql As String = "SELECT * FROM Customers"


'define os objetos connecton, command e dataadapter

Dim conn As SqlConnection = New SqlConnection(connStr)

Dim comm As SqlCommand = New SqlCommand(sql, conn)

Dim dataadapter As SqlDataAdapter = New SqlDataAdapter(comm)


'define o dataset

Dim ds As DataSet = New DataSet()


Try

'---abre a conexao---

conn.Open()

'---preenche o dataset---

dataadapter.Fill(ds, "Clientes")

'---fecha a conexao---

conn.Close()

'---vincula o dataset ao DataGridView---

DataGridView1.DataSource = ds           'ou ds.tables(0)

'---define a tabela a ser exibida---

DataGridView1.DataMember = "Clientes"

Catch ex As Exception

MsgBox(ex.Message)

End Try

End Sub

Obtendo o valor da célula selecionada e Atribuindo a célula atual

Para obter o valor da célula clicada pelo usuário em um DataGridView usamos o evento CellEnter:

Private Sub DataGridView1_CellEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEnter

'---Quando o usuário clicar no controle , exibe o conteudo da célula
MsgBox(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value)

End Sub

Neste código estamos obtendo o valor da célula pelo índice da linha (e.RowIndex) e da coluna (e.ColumnIndex).

Se desejar obter valor da primeira coluna quando o usuário selecionar uma linha o código ficaria assim :

Private Sub DataGridView1_CellEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEnter

'---Quando o usuário clicar no controle , exibe o conteudo da célula referente a primeira coluna (Column=0)
MsgBox(DataGridView1.Rows(e.RowIndex).Cells(0).Value)

End Sub

Para atribuir a célula atual via código podemos atribuir um valor a propriedade CurrentCell do DataGridView . No código abaixo estou atribuindo a célula atual como sendo a primeira linha e a segunda coluna ( row=0  e column=1)

Private Sub setCurrentCellButton_Click(ByVal sender As ObjectByVal e As System.EventArgs) Handles setCurrentCellButton.Click

    ' Define a célula atual para a célula na coluna 1 e linha 0
    Me.dataGridView1.CurrentCell = Me.dataGridView1(1, 0)

End Sub

Validando a entrada de dados em uma célula

Podemos usar o evento CellValidating para verificar se a entrada de um usuário quando da edição dos dados de uma célula estiver ocorrendo é valida ou não.

No exemplo acima iremos efetuar a validação da coluna CompanyName para isso devemos implementar o tratamento dos eventos CellValidating e CellEndEdits.

O evento CellValidating ocorre quando a célula perde o foco de entrada habilitando a validação do seu conteúdo.

O evento CellEndEdits ocorre quando o modo de edição é encerrado para a atual célula selecionada.

No evento CellValidating é onde você determina se o valor de uma célula para um determinada coluna é válida. Se a validação da célula falha defina a propriedade Cancel da classe System.Windows.Forms.DataGridViewCellValidatingEventArgs para true. Isto faz com que o controle DataGridView não permita que o cursor deixe a célula.

Definindo a propriedade ErrorText na linha para exibir uma mensagem para o usuário exibe um ícone de erro com uma dica que contém o texto para o erro.

No evento CellEndEdit defina a propriedade ErrorText na linha para uma string vazia. Este evento ocorre somente quando a célula existe no modo edit o qual não pode ocorrer se a validação falhar.

No exemplo vamos verificar se a coluna CompanyName  esta vazia para a entrada do usuário:

Private Sub dataGridView1_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating


' Valida o entrada para o CompanyName não permitindo valores em branco

If DataGridView1.Columns(e.ColumnIndex).Name = "CompanyName" Then

        If String.IsNullOrEmpty(e.FormattedValue.ToString()) Then

                   DataGridView1.Rows(e.RowIndex).ErrorText = "O nome da Companhia não pode ser vazio."

                   e.Cancel = True

           End If

End If

End Sub

Private Sub dataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit

       ' Limpa o erro da linha no caso do usuário pressionar ESC

      DataGridView1.Rows(e.RowIndex).ErrorText = String.Empty

End Sub

 

Tratando ocorrências de erros em um DataGridView

Podemos efetuar o tratamento de erros para o controle DataGridView usando o evento DataError o qual é disparado quando a fonte de dados detecta uma violação de restrição ou quebra de regra de negócio.

A seguir temos um exemplo que quando ocorrer um valor para o campo CustomerID duplicado em uma nova linha ou linha sendo editada o evento DataError irá ocorrer e será tratado pela exibição de uma mensagem que descreve o erro.

Private Sub dataGridView1_DataError(ByVal sender As Object, ByVal e As DataGridViewDataErrorEventArgs)  Handles DataGridView1.DataError

' Se a fonte de dados levanta uma exceção quando uma célula esta comitda exibe um erro.
If e.Exception IsNot Nothing AndAlso e.Context = DataGridViewDataErrorContexts.Commit Then
      MessageBox.Show("O código do cliente - CustomerID - não pode ser duplicado.")
End
If

End Sub

Exibindo imagens em células de um DataGridView

Podemos exibir uma figura ou um gráfico em uma linha de dados. Para exibir imagens em um controle DataGridView não há muito segredo pois ele trata nativamente qualquer imagem suportada pela classe Image bem como o ormato de imagem OLE usado por alguns banco de dados.

Se a fonte de dados do controle DataGridView possuir uma coluna com imagens , elas serão exibida automaticamente exibidas no controle DataGridView.

Filtrando e ordenando colunas via código

Para filtrar os dados exibidos em um DataGridView podemos usar um objeto DataView.  A seguir temos um exemplo onde estamos filtrando os dados para o código do cliente iniciado pela letra B:

Nota: Para este exemplo você deve criar um TableAdapter para a tabela Customers. Para fazer isso inclua um novo DataSet no projeto e arraste a partir da janela DataBase Explorer a tabela Customers do banco de dados Northwind.mdb.

Você deverá declarar os seguintes namespaces no projeto para que o código abaixo funcione:

Imports System.Data.sqlclient
Imports
datagridviewTotal.DataSet1TableAdapters

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click


'---crria uma instância de um tableadapter ---

Dim adapter As New CustomersTableAdapter


'---cria uma instância de um dataview---

Dim dv As New DataView(adapter.GetData)


'filtra usando o criterio escolhido: clientes com código contendo B no início

With dv

    .AllowNew = False

    .AllowDelete = True

    .Sort = "ContactTitle ASC, Address ASC"

    .RowFilter = "CustomerID LIKE 'B*'"

End With

' atribui o dataview ao datagridview

DataGridView1.DataSource = dv

End Sub

O resultado da execução deste código será:


O dataView é obtido a partir do adapter chamando o método getData que retorna um DataTable preenchido conforme a consulta SQL definida.

No código acima o objeto DataView permite aos usuário incluir novas linhas , via propriedade AllowNew no controle DataGridView e também excluir  linhas , via propriedade AllowDelete.

Podemos ainda ordenar as linhas especificando o campo e a ordem correspondente que será aplicada usando a propriedade Sort. (ASC ordem ascendente DESC ordem descendente)

O filtro é feito pela expressão SQL usando a expressão LIKE via propriedade RowFilter.

Uma outra maneira de ordenar colunas é usar o método Sort do próprio controle DataGridView:

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

     DataGridView1.Sort(DataGridView1.Columns(0), System.ComponentModel.ListSortDirection.Descending)

End Sub

O código esta ordenando pela primeira coluna do componente (Columns(0)) usando a ordem descendente.

Definindo um texto em ToolTips em células individuais

De forma geral usamos o recurso ToolTips para exibir valores em células do DataGridView que são muito pequenas para exibir todo o conteúdo. Podemos reescrever este comportamento de forma a definir textos para ToolTips para células individuais. Isto é útil para exibir informação adicional sobre a célula ou para fornecer ao usuário uma descrição mais detalhada sobre o conteúdo da célula.

Para isto eu vou usar o o evento CellFormatting que ocorre quando o conteúdo de uma célula precisa ser formatado para exibição.

A tabela Customers não possui um campo muito adequado para um exemplo mais convincente ,vou usar portanto o campo City de e escolher algumas cidades de forma que exibam o nome do pais a qual pertençam. O código é o seguinte:

'Define o texto da propriedade ToolTip para células da coluna especificada , no caso a coluna: City

Sub dataGridView1_CellFormatting(ByVal sender As ObjectByVal e As DataGridViewCellFormattingEventArgs) _

Handles DataGridView1.CellFormatting

 

If e.ColumnIndex = Me.DataGridView1.Columns("City").Index AndAlso (e.Value IsNot Nothing) Then

    With Me.DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex)

               If e.Value.Equals("London") Then

                .ToolTipText = "< Inglaterra >"

              ElseIf e.Value.Equals("Sao Paulo") Then

                .ToolTipText = "< Brasil > "

              ElseIf e.Value.Equals("Madrid") Then

                .ToolTipText = "< Espanha >"

              ElseIf e.Value.Equals("Buenos Aires") Then

                .ToolTipText = "< Argentina >"

              End If

     End With

End If

End Sub

O resultado pode ser visto na figura abaixo:

Exibindo uma combobox em uma célula

Você pode exibir uma combobox em uma célula de forma a permitir que o usuário selecione valores determinados de uma lista existente. Neste caso você precisa incluir uma ComboBox na célula da coluna desejada. O código abaixo faz exatamente isto usando o controle BindingSource:

Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

 

'---inclui colunas no controle DataGridView---

DataGridView1.Columns.Add("ID", "Codigo")

DataGridView1.Columns.Add("Nome", "Nome Aluno")

 

'---define um controle bindingsource---

Dim bindingsource As New BindingSource

 

'---inclui itens no controle---

bindingsource.Add("Matemática")

bindingsource.Add("Português")

bindingsource.Add("História")

 

'---cria uma coluna do tipo combobox---

Dim comboBoxCol As New DataGridViewComboBoxColumn

 

'---define o cabecalho (header) ---

comboBoxCol.HeaderText = "Disciplinas"

'---vincula os dados---

comboBoxCol.DataSource = bindingsource

 

'---Inclui a coluna combobox ao DataGridView---

DataGridView1.Columns.Add(comboBoxCol)

End Sub

Se você não quiser usar um controle BindingSource pode incluir os itens diretamente no controle DataGridViewComboBoxColumn :

Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

 

'---inclui colunas no controle DataGridView---

DataGridView1.Columns.Add("ID", "Codigo")

DataGridView1.Columns.Add("Nome", "Nome Aluno")

 

'---cria uma coluna do tipo combobox---

Dim comboBoxCol As New DataGridViewComboBoxColumn

 

'---define o cabecalho (header) ---

comboBoxCol.HeaderText = "Disciplinas"

 

'---inclui itens no controle---

comboBoxCol.Items.Add("Matemática")

comboBoxCol.Items.Add("Português")

comboBoxCol.Items.Add("História")

 

'---Inclui a coluna combobox ao DataGridView---

DataGridView1.Columns.Add(comboBoxCol)


End
Sub

 

Se você deseja permitir que os usuários possam incluir novos valores no controle ComboBox. Neste caso você terá que fazer o seguinte :

 

1-) Usar o evento EditingControlShowing que ocorre quando o usuário vai tentar editar dados no controle Combobox:

 

Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms. DataGridViewEditingControlShowingEventArgs) _
Handles DataGridView1.EditingControlShowing
 

Dim comboBoxColumn As DataGridViewComboBoxColumn = DataGridView1.Columns(2)


If
(DataGridView1.CurrentCellAddress.X = comboBoxColumn.DisplayIndex)
Then

      Dim cb As ComboBox = e.Control

                If (cb IsNot Nothing) Then

                    cb.DropDownStyle = ComboBoxStyle.DropDown

                End If

End If

End Sub

 

Neste código estou verificando se a célula que esta sendo editada é do tipo ComboBox. Neste caso estou definindo o estilo do ComboBox como DropDown de forma que o usuário possa digitar o novo item a ser incluído.

 

2-) Usar o evento CellValidating do controle DataGridView que ocorre sempre que o usuário termina de digitar e deixa a célula:

 

Private Sub DataGridView1_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.  DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating
 

     Dim comboBoxColumn As DataGridViewComboBoxColumn = DataGridView1.Columns(2)
 

     If (e.ColumnIndex = comboBoxColumn.DisplayIndex) Then

                     If (Not comboBoxColumn.Items.Contains(e.FormattedValue)) Then

                    comboBoxColumn.Items.Add(e.FormattedValue)

                End If

      End If

End Sub

 

Aqui estou verificando e incluindo o novo item na ComboBox. Para que a inclusão seja possível a propriedade DataSource do coluna DataGridViewComboBoxColumn  não pode estar definida; assim não podemos vincular o bindingsource e incluir itens na combobox tendo que usar o código que inclui os dados diretamente na combobox.

 

 

Eu poderia estender este artigo, mas são tantos os recursos do DataGridView a explorar que vamos continuar a falar sobre assunto mais adiante... Aguarde.

 

Pegue o projeto completo aqui:   datagridviewTotal.zip

 

Até breve...


Veja os Destaques e novidades do SUPER DVD VB (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Veja mais sistemas completos para a plataforma .NET no Super DVD .NET , confira...

Quer aprender C# ??

Chegou o Super DVD C# com exclusivo material de suporte e vídeo aulas com curso básico sobre C#
 

   Gostou ?   Compartilhe no Facebook    Compartilhe no Twitter

Referências:


José Carlos Macoratti