VB.NET - Busca Dinâmica em um ComboBox


Preencher uma comboBox e efetuar uma busca dinâmica nos itens adicionados a mesma é uma tarefa corriqueira no dia a dia de um programador. Neste artigo vou mostrar como você pode preencher um comboBox com os dados de uma tabela e a seguir permitir uma busca dinâmica nos itens inseridos quando o usuário digitar na caixa de texto da combo.

Eu já mostrei uma forma de fazer a mesma coisa no artigo : VB .NET - Criando uma Combobox com recurso Auto Completar.   Neste artigo além da mostrar outra maneira de obter o mesmo resultado estou usando o acesso a um banco de dados Access - Northwind.mdb - e selecionando os dados da tabela produtos para exibir o nome do produto na combobox.

- Inicie um novo projeto no Visual Studio.NET com as seguintes características (sinta-se a vontade para alterar a seu gosto.)

  1. Project Types : Visual Basic .NET
  2. Templates : Windows Application
  3. Name : AutoCombo
  4. Location : c:\vbnet\AutoCombo

No formulário padrão form1.vb insira um controle combobox e um controle Button conforme a figura abaixo:

No evento Load do formulário eu vou inserir o código que acesso o banco de dados , seleciona os dados da tabela e preenche a combobox. (Não é a maneira mais elegante de fazer este serviço , você poderia criar uma classe e remover  o código do formulário)

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

        'Retorna os nomes dos produtos da tabela  produtos
        Dim strConn As String = "Provider=Microsoft.JET.OLEDB.4.0;Data Source = c:\teste\Northwind.mdb"

        Dim dbConn As System.Data.OleDb.OleDbConnection = New System.Data.OleDb.OleDbConnection(strConn)

        dbConn.Open()

        Dim DSet As New DataSet(), SQLStr As String
        Dim cmd As System.Data.OleDb.OleDbCommand
        Dim dbAdaptr As System.Data.OleDb.OleDbDataAdapter = New System.Data.OleDb.OleDbDataAdapter()

        'cria o objeto datarow e datatable
        Dim tRow As DataRow, tTbl As DataTable

        'mapeia a tabela produtos , monta o sql para selecionar os nomes dos produtos
        'e executa o objeto command preenchendo a seguir o dataset
        With dbAdaptr
            .TableMappings.Add("Table", "Produtos")
            SQLStr = "Select [NomeDoProduto] from Produtos order by NomeDoProduto"
            cmd = New System.Data.OleDb.OleDbCommand(SQLStr, dbConn)
            cmd.CommandType = CommandType.Text
            .SelectCommand = cmd
            .Fill(DSet)
            .Dispose()
        End With

        DSet.AcceptChanges()
        tTbl = DSet.Tables.Item(0)
        DSet.Dispose()
        dbConn.Close()

        ' preenche o combo combobox
        cboAuto.Text = ""
        cboAuto.Items.Clear()
        cboAuto.BeginUpdate()

        ' carrega o combo com o nome dos produtos
        For Each tRow In tTbl.Rows
            cboAuto.Items.Add(tRow("NomeDoProduto").ToString)
        Next
        cboAuto.EndUpdate()
    End Sub

 

 

A seguir vou comentar as partes que acho interessante no código acima.

 

- .TableMappings.Add("Table", "Produtos") - Quando um data adapter lê os dados de uma fonte de dados ele determina onde por os dados na tabela correspondente usando o mapeamento para a tabela. O mapeamento vincula o nome das colunas no fonte com aqueles da tabela no DataSet.

 

- .SelectCommand = cmd - Obtêm ou define um comando SQL ou procedimento armazenado usado para selecionar os registros na fonte de dados.  Se a propriedade não retornar nenhuma linha de registro , não haverá tabela incluída no DataSet.

 

-DSet.AcceptChanges() - Atualiza todas as alterações feitas para o DataSet desde que ele foi carregado ou até a última vez que o método foi chamado. Tanto a classe DataTable como DataRow possui o método AcceptChanges ;Ao invocar o método em um DataSet faz com que ele seja chamado em cada tabela do DataSet. Desta maneira você tem múltiplos níveis no qual o método pode ser chamado.

 

cboAuto.BeginUpdate()/  cboAuto.EndUpdate() - O método BeginUpdate evita que o controle seja redesenhado até que o método EndUpdate e assim mantêm o desempenho quando itens são incluídos na combobox. A melhor forma de preencher uma combobox é usar o método AddRange da classe ComboBox.Collection pois isto permite que você inclua um array de itens na lista de uma vez. Se você quer incluir item a item ( que é o nosso caso) pode usar o método Add e pode usar então o método BeginUpdate para evitar que o controle seja redesenhado a cada item incluído na lista. Após terminar a tarefa chame o método EndUpdate para que o controle seja redesenhado. Isto pode previnir que a tela sofra o efeito de tremulação durante o desenho do controle se a quantidade de itens for muito grande.

 

No evento Change do comboBox incluimos o código que realiza a busca:

 

 ' Usamos o evento "Change" para uma busca alfabetica
    Private Sub cboAuto_TextChanged(ByVal sender As Object, _
     ByVal e As System.EventArgs) Handles cboAuto.TextChanged

        Dim boxIndex As Integer, lExst As Boolean
        
        Dim box As ComboBox = sender
        Dim txt As String = box.Text
        Dim posCursor As Integer = box.SelectionStart

        ' Se o cursor não estiver no inicio do textbox inicia a busca
        If posCursor <> 0 Then
            lExst = False
            ' Procura na combo pela entrada na lista
            For boxIndex = 0 To box.Items.Count - 1
                If UCase(Mid(box.Items(boxIndex), 1, posCursor)) = UCase(Mid(txt, 1, posCursor)) Then
                    box.Text = box.Items(boxIndex)
                    box.SelectionStart = posCursor
                    lExst = True
                    Exit For
                End If
            Next
            ' Se não encontrar retorna o valor anterior
            If Not lExst Then
                box.Text = Mid(txt, 1, posCursor - 1) + Mid(txt, posCursor + 1)
                box.SelectionStart = posCursor - 1
            End If
        End If
    End Sub

 


Executando o projeto teremos:

 

 

Até o próximo artigo...


José Carlos Macoratti