VB .NET - Formulário com busca dinâmica


Este artigo mostra como criar um formulário de busca dinâmica em uma aplicação em camadas.

Para mostrar como o formulário funciona vou usar uma aplicação VB .NET que usa um formulário de clientes que permite abrir o formulário de busca onde são mostrados todos os clientes já cadastrados permitindo assim um cliente ser selecionado e os seus dados serem exibidos no formulário.

O formulário de manutenção de clientes tem o seguinte leiaute:

Por uma questão de didática e espaço vou implementar somente o código relacionado com o botão Procurar e o formulário frmProcurarCliente.vb e não vou detalhar muito a criação das camadas da aplicação. Abaixo vemos o leiaute do formulário frmProcurarCliente:

Neste formulário podemos realizar a busca de clientes por : código, nome, telefone e celular.

Estou usando um banco de dados SQL Server chamado Macoratti.mdf para realizar a manutenção dos clientes e um arquivo Access chamado audit.mdb usado para gravar o log de auditoria da aplicação.

Abaixo vemos um trecho no arquivo App.Config que mostra a string de conexão para os arquivos usados na aplicação:

<connectionStrings>
<add name="SQL Server" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=c:\dados\Macoratti.mdf;Integrated Security=True;User Instance=True" /><add name="MS Access" providerName="System.Data.OleDb" connectionString="Provider=Microsoft.Jet.OleDb.4.0; Data Source=C:\dados\audit.mdb" />
</connectionStrings>

A tabela Clientes tem a sua estrutura exibida a seguir:

Obs: rowversion é um campo usado para tratar a concorrência.

Criando o projeto

Abra o Visual Basic 2010 Express Edition e crie um novo projeto do tipo Windows Forms com o nome Clientes;

A seguir no menu File-> Add -> New Project vamos incluir mais três projetos do tipo Class Library com o nome : BLL, DAL e Modelo

Ao final dessa etapa teremos uma solução contendo 4 projetos:

BLL - Projeto referente a camada de negócios;
DAL - Projeto referente a camada de acesso a dados;
Modelo - Projeto referente ao domínio da aplicação;
Clientes - Projeto referente a camada de apresentação;

Vamos agora definir os arquivos e o código para cada uma das camadas definidas conforme mostra a figura abaixo da solução exibida na janela Solution Explorer:

Na camada Modelo demos a classe Cliente.vb que define o nosso domínio conforme o código abaixo:

Namespace Macoratti.Modelo
    Public Class Cliente
        Public Property ClienteId As Integer
        Public Property Nome As String
        Public Property Endereco As String
        Public Property Cep As String
        Public Property Estado As String
        Public Property Bairro As Integer
        Public Property Telefone As String
        Public Property Celular As String
        Public Property Contato As String
        Public Property Observacao As String
        Public Property RowVersion As Integer = 1
    End Class
End Namespace

Na camada de acesso a dados - DAL - temos as classe que permite o acesso aos dados sendo que temos uma classe base abstrata chamada BaseDAL.vb e a classe AcessoDB.vb que herda dessa classe base.

A classe LogDAL.vb é usada para permitir a gravação de logs de auditoria da aplicação e a classe TipoAcessoDB.vb define se estamos acessando um banco de dados Access ou SQL Server.

A camada de negócios - BLL - temos a classe ClienteBLL.vb com o seguinte código:

Imports System.Data
Imports System.Data.Common
Imports DAL.Macoratti.DAL
Imports Modelo.Macoratti.Modelo

Namespace Macoratti.BLL
    Public Class ClienteBLL

        Public Sub New()
        End Sub

        Public Function getTabela(ByVal sql As String) As DataTable
            Try
                Dim dtb As New DataTable
                Dim x As AcessoDB = New SqlServerDatabase()
                x.PrepareQuery(sql)
                dtb = x.GetDataTable()
                Return dtb
            Catch ex As Exception
                Throw ex
            End Try
        End Function

        Public Function GetCliente(ByVal codigoCliente As Integer) As Cliente
            Const stringSQL As String = "SELECT Clientes.clienteid, Clientes.nome, Clientes.endereco, Clientes.cep, Clientes.estado, Clientes.bairro, _
 Clientes.telefone, Clientes.celular, Clientes.contato , Clientes.observacao FROM Clientes WHERE clienteid = @clienteid"
            'Dim x As AcessoDB = New OleDatabase()
            Dim x As AcessoDB = New SqlServerDatabase()
            x.PrepareQuery(stringSQL)
            x.AddParameter("clienteid", codigoCliente)
            If x.RecordExists() Then
                Dim dr As DataRow = x.GetDataRow()
                Dim cli As Cliente = DatabaseToCliente(dr)
                dr = Nothing
                x.Dispose()
                Return cli
            Else
                x.Dispose()
                Return Nothing
            End If
        End Function

        Public Function GetClienteTelefone(ByVal telefone As String) As Cliente
            Const stringSQL As String = "SELECT Clientes.clienteid, Clientes.nome, Clientes.endereco, Clientes.cep, Clientes.estado, _ 
Clientes.bairro, Clientes.telefone, Clientes.celular, Clientes.contato , Clientes.observacao FROM Clientes WHERE telefone = @telefone"
            'Dim x As AcessoDB = New OleDatabase()
            Dim x As AcessoDB = New SqlServerDatabase()
            x.PrepareQuery(stringSQL)
            x.AddParameter("telefone", telefone)
            If x.RecordExists() Then
                Dim dr As DataRow = x.GetDataRow()
                Dim cli As Cliente = DatabaseToCliente(dr)
                dr = Nothing
                x.Dispose()
                Return cli
            Else
                x.Dispose()
                Return Nothing
            End If
        End Function

        Public Function GetClientes() As Cliente()
            Const stringSQL As String = "SELECT Clientes.clienteid, Clientes.nome, Clientes.Telefone, Clientes.Celular FROM Clientes Order by nome"
            Dim x As AcessoDB = New SqlServerDatabase()
            x.PrepareQuery(stringSQL)
            Dim dt As DataTable = x.GetDataTable()
            x.Dispose()
            If dt IsNot Nothing Then
                If dt.Rows.Count <> 0 Then
                    Dim clis As Cliente() = New Cliente(dt.Rows.Count - 1) {}
                    For ctr As Integer = 0 To dt.Rows.Count - 1
                        clis(ctr) = New Cliente()
                        clis(ctr) = DatabaseToCliente(dt.Rows(ctr))
                    Next
                    Return clis
                Else
                    Return Nothing
                End If
            Else
                Return Nothing
            End If
        End Function

        Private Function DatabaseToCliente(ByVal dr As DataRow) As Cliente
            Dim cli As New Cliente()
            If dr.Table.Columns.Contains("clienteid") Then
                cli.ClienteId = dr("clienteid").ToString()
            End If
            If dr.Table.Columns.Contains("nome") Then
                cli.Nome = dr("nome").ToString()
            End If
            If dr.Table.Columns.Contains("endereco") Then
                cli.Endereco = dr("endereco").ToString()
            End If
            If dr.Table.Columns.Contains("cep") Then
                cli.Cep = dr("cep").ToString()
            End If
            If dr.Table.Columns.Contains("estado") Then
                cli.Estado = dr("estado").ToString()
            End If
            If dr.Table.Columns.Contains("bairro") Then
                If IsDBNull(dr("bairro")) Then
                    dr("bairro") = 0
                End If
                cli.Bairro = Convert.ToInt32(dr("bairro"))
            End If
            If dr.Table.Columns.Contains("telefone") Then
                cli.Telefone = dr("telefone").ToString()
            End If
            If dr.Table.Columns.Contains("celular") Then
                cli.Celular = dr("celular").ToString()
            End If
            If dr.Table.Columns.Contains("contato") Then
                cli.Contato = dr("contato").ToString()
            End If
            If dr.Table.Columns.Contains("observacao") Then
                cli.Observacao = dr("observacao").ToString()
            End If
            If dr.Table.Columns.Contains("RowVersion") Then
                cli.RowVersion = CInt(dr("RowVersion"))
            End If
            dr = Nothing
            Return cli
        End Function
    End Class
End Namespace

Esta classe possui os métodos:

Obs: Os demais métodos da classe CLienteBLL forma omitidos.

Na camada de apresentação temos a classe Publico.vb é uma classe que não pode ser herdada (NotInheritable ou Sealed em C#);

Ela define os tipos de operações que podemos usar em nossa aplicação;

Namespace Macoratti

    Public NotInheritable Class VariaveisPublicas
        Private Sub New()
        End Sub

        Public Enum ModeAtualizar
            ModoIncluir
            ModeEditar
            ModeNenhum
        End Enum

    End Class
End Namespace

A camada de apresentação também inclui os formulários frmClientes e frmProcurarCliente que vermos a seguir:

O código do formulário frmClientes.vb é dado abaixo:

Imports Modelo.Macoratti.Modelo
Imports Clientes.Macoratti.BLL

Public Class frmClientes

    Private _modoAtualizar = Macoratti.VariaveisPublicas.ModeAtualizar.ModeNenhum
    Private _ClienteAtual As Cliente = Nothing

    Private Sub toolStripSair_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles toolStripSair.Click
        Me.Close()
    End Sub

    Private Sub frmClientes_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim dtcbo As DataTable = Nothing
        Dim cliCRUD As New ClienteBLL
        dtcbo = cliCRUD.getTabela("Select id, nome from Estados where ativo=" & 1)
        preencheComboBox(cboEstado, dtcbo)
        dtcbo = cliCRUD.getTabela("Select bairroid, nome from Bairros")
        preencheComboBox(cboBairro, dtcbo)
        BloqueiaDesbloqueiaTextBox(True)
        HabilitaDesabilitaButtons(True)
    End Sub

    Private Sub preencheComboBox(ByVal ctrl As ComboBox, ByVal tabela As DataTable)
        With ctrl
            .DataSource = tabela
            .DropDownStyle = ComboBoxStyle.DropDownList
            .ValueMember = tabela.Columns(0).ColumnName
            .DisplayMember = tabela.Columns(1).ColumnName
            .SelectedIndex = -1
        End With
    End Sub

    Private Sub verRegistro(ByVal id As Integer)
        Dim cliCRUD As New ClienteBLL()
        Dim cli As Cliente = cliCRUD.GetCliente(id)
        _ClienteAtual = cli
        If cli IsNot Nothing Then
            txtCodigo.Text = cli.ClienteId
            txtNome.Text = cli.Nome
            txtTelefone.Text = cli.Telefone
            txtCelular.Text = cli.Celular
            txtContato.Text = cli.Contato
            txtEndereco.Text = cli.Endereco
            txtCep.Text = cli.Cep
            cboEstado.SelectedValue = cli.Estado
            cboBairro.SelectedValue = cli.Bairro
            txtObservacao.Text = cli.Observacao
        Else
            MessageBox.Show("Registro não encontrado.", "Exibir", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End If
    End Sub
    
    Private Sub toolStripProcurar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles toolStripProcurar.Click
        Dim frm As New frmProcurarCliente()
        frm.ShowDialog()
        If frm.DialogResult.Equals(DialogResult.OK) Then
            Me.verRegistro(frm.Tag.ToString())
        End If
        frm.Dispose()
    End Sub

#Region "Habilita/Bloqueia e Desbloquiea/Desabilita Botoes"
#Region "Operações CRUD"
#Region "Limpar TextBox"
#Region "Validacao TextBox"

End Class

Quando a aplicação o código do evento Load do formulário é executado:

Private Sub frmClientes_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  Dim dtcbo As DataTable = Nothing
  Dim cliCRUD As New ClienteBLL
  dtcbo = cliCRUD.getTabela("Select id, nome from Estados where ativo=" & 1)
  preencheComboBox(cboEstado, dtcbo)
  dtcbo = cliCRUD.getTabela("Select bairroid, nome from Bairros")
  preencheComboBox(cboBairro, dtcbo)
  BloqueiaDesbloqueiaTextBox(True)
  HabilitaDesabilitaButtons(True)
End Sub

Este código usa o método getTabela() da classe ClienteBLL para retornar um DataTable que usamos para preencher a combobox do formulário.

Após isso o formulário é exibido conforme a figura a seguir:

Quando o usuário clica no botão Procurar (ícone da lupa) o código do evento - toolStripProcurar_Click - é acionado;

Este código cria uma instância do formulário frmProcurarCliente() e o exibe na tela:

O código do formulário frmProcurarCliente é mostrado abaixo:

Imports Modelo.Macoratti.Modelo
Imports Clientes.Macoratti.BLL

Public Class frmProcurarCliente

    Private Sub frmProcurar_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        listView1.Columns.Add("Cod.", 60, HorizontalAlignment.Left)
        listView1.Columns.Add("Nome", 190, HorizontalAlignment.Left)
        listView1.Columns.Add("Telefone", 140, HorizontalAlignment.Left)
        listView1.Columns.Add("celular", 140, HorizontalAlignment.Left)
        carregaClientes()
    End Sub

    Private Sub carregaClientes()
        Dim cliCRUD As New clienteBLL()
        Dim clis As Cliente() = cliCRUD.GetClientes()
        If clis IsNot Nothing Then
            For ctr As Integer = 0 To clis.GetUpperBound(0)
                Dim lvItem As New ListViewItem()
                lvItem.Text = clis(ctr).ClienteId
                lvItem.SubItems.Add(clis(ctr).Nome)
                lvItem.SubItems.Add(clis(ctr).Telefone)
                lvItem.SubItems.Add(clis(ctr).Celular)
                lvItem.Tag = clis(ctr).ClienteId
                listView1.Items.Add(lvItem)
            Next
            listView1.TopItem.Selected = True
            listView1.TopItem.Focused = True
            listView1.TopItem.EnsureVisible()
            listView1.[Select]()
        End If
    End Sub

    Private Sub textCodigo_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtCodigo.TextChanged
        Dim lvItem As ListViewItem = listView1.FindItemWithText(txtCodigo.Text)
        If lvItem IsNot Nothing Then
            lvItem.Selected = True
            lvItem.Focused = True
            lvItem.EnsureVisible()
        End If
    End Sub

    Private Sub textNome_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtNome.TextChanged
        For ctr As Integer = 0 To listView1.Items.Count - 1
            If listView1.Items(ctr).SubItems(1).Text.StartsWith(txtNome.Text) Then
                listView1.Items(ctr).Selected = True
                listView1.Items(ctr).Focused = True
                listView1.Items(ctr).EnsureVisible()
                Return
            End If
        Next
        listView1.TopItem.Selected = True
        listView1.TopItem.Focused = True
        listView1.TopItem.EnsureVisible()

    End Sub

    Private Sub txtTelefone_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtTelefone.TextChanged
        For ctr As Integer = 0 To listView1.Items.Count - 1
            If listView1.Items(ctr).SubItems(2).Text.StartsWith(txtTelefone.Text) Then
                listView1.Items(ctr).Selected = True
                listView1.Items(ctr).Focused = True
                listView1.Items(ctr).EnsureVisible()
                Return
            End If
        Next
        listView1.TopItem.Selected = True
        listView1.TopItem.Focused = True
        listView1.TopItem.EnsureVisible()

    End Sub

    Private Sub txtCelular_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtCelular.TextChanged
        For ctr As Integer = 0 To listView1.Items.Count - 1
            If listView1.Items(ctr).SubItems(3).Text.StartsWith(txtCelular.Text) Then
                listView1.Items(ctr).Selected = True
                listView1.Items(ctr).Focused = True
                listView1.Items(ctr).EnsureVisible()
                Return
            End If
        Next
        listView1.TopItem.Selected = True
        listView1.TopItem.Focused = True
        listView1.TopItem.EnsureVisible()

    End Sub
    Private Sub listView1_DoubleClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles listView1.DoubleClick
        Me.Tag = listView1.FocusedItem.Tag.ToString()
        Me.DialogResult = DialogResult.OK
        Me.Close()
    End Sub
    Private Sub btnFechar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFechar.Click
        Me.Close()
    End Sub
    Private Sub listView1_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles listView1.KeyPress
        If e.KeyChar = Chr(13) Then
            Me.Tag = listView1.FocusedItem.Tag.ToString()
            Me.DialogResult = DialogResult.OK
            Me.Close()
        End If
    End Sub
    Private Sub txtTelefone_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtTelefone.KeyPress
        If e.KeyChar = Chr(13) Then
            Me.Tag = listView1.FocusedItem.Tag.ToString()
            Me.DialogResult = DialogResult.OK
            Me.Close()
        End If
    End Sub
    Private Sub txtCodigo_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtCodigo.KeyPress
        If e.KeyChar = Chr(13) Then
            Me.Tag = listView1.FocusedItem.Tag.ToString()
            Me.DialogResult = DialogResult.OK
            Me.Close()
        End If
    End Sub
    Private Sub txtNome_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtNome.KeyPress
        If e.KeyChar = Chr(13) Then
            Me.Tag = listView1.FocusedItem.Tag.ToString()
            Me.DialogResult = DialogResult.OK
            Me.Close()
        End If
    End Sub
End Class

O código define um controle ListView que é populado rotina carregaClientes() através do método GetClientes da classe ClienteBLL.

Ao selecionar um item exibido no formulário será chamada a rotina verRegistro(frm.Tag.ToString());

Esta rotina recebe o código do cliente selecionado e chama o método GetCliente da classe ClienteBLL da qual foi criada uma instância conforme o código a seguir:

Dim cliCRUD As New ClienteBLL()
Dim cli As Cliente = cliCRUD.GetCliente(id)

O método GetCliente retorna um objeto do tipo Cliente que usamos para preencher os controles do formulário:

Esse exemplo reúne conceitos importantes usados em um projeto como distribuição em camadas, log de auditoria e a criação de formulário de busca dinâmica que tratamos neste artigo.

Pegue o projeto completo aqui : Clientes.zip

Eu sei é apenas VB .NET mas eu gosto...

"Todos quantos vieram antes de mim são ladrões e salteadores; mas as ovelhas não os ouviram. Eu sou a porta; se alguém entrar por mim, salvar-se-á, e entrará, e sairá, e achará pastagens." João 10:8-9

Referências:


José Carlos Macoratti