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: