VB .NET - Sincronizando dados entre dois controles Combobox


Vou mostrar neste artigo como realizar uma tarefa muito simples: sincronizar informações entre dois controles Combobox.

O cenário é muito comum: você possui dois controles combobox em um formulário Windows que exibem dados que possuem um relacionamento do tipo mestre-detalhes.

Por exemplo: em uma combobox você exibe uma lista de categorias para o usuário escolher e na outra combobox você exibe uma lista de produtos relacionado com a categoria selecionada na primeira combobox.

Este é o cenário mais simples mas você obter muitas variações; o que importa é que o tratamento é basicamente o mesmo.

Tenha em mente que a utilização do controle Combobox para exibição de dados deve ser feita com cautela. Se a quantidade de dados a ser exibida for muito grande deve-se adotar outra estratégia por questões de desempenho.

Neste artigo eu vou usar os seguintes recursos:

SQL Server Express LocalDB é uma versão leve do SQL Server que tem muitas características de programação de um banco de dados SQL Server. O SQL Server Express LocalDB é executado no modo de usuário e tem uma instalação rápida sem a necessidade de configuração.

No Microsoft SQL Server, o banco de dados ou qualquer código Transact-SQL podem ser movidos de SQL Server Express LocalDB para o SQL Server e SQL Azure, sem quaisquer passos de atualização.

Então, o SQL Server Express LocalDB pode ser usado como um ambiente de desenvolvimento para aplicações que utilizem todas as edições do SQL Server.

O SQL Server Express LocalDB permite recursos como procedimentos armazenados, funções definidas pelo usuário e agregados, Integração com NET Framework, tipos espaciais e outros recurso que não estão disponíveis no SQL Server Compact.

Definindo a fonte de dados

Neste artigo eu vou usar um banco de dados SQL Server LocalDB chamado Estoque.mdf onde teremos duas tabelas: Categorias e Produtos.

1- Estrutura e dados da tabela Categorias

1- Estrutura e dados da tabela Produtos

A estrutura das tabelas esta bem simplificada para facilitar o entendimento do artigo.

A fonte de dados não necessita obrigatoriamente ser um banco de dados poderíamos ter um arquivo texto ou XML.

O projeto Windows Forms

Inicie um novo projeto no Visual Studio 2012 Express for desktop e clique em New Project;

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

No formulário form1.vb inclua dois controles Labels, 1 controle Button (BtnSair) e dois controles Combobox - cboCategorias e cboProdutos, conforme o leiaute abaixo:

Agora temos que tomar uma decisão importante: Como realizar o acesso aos dados ?

A plataforma .NET oferece muitas formas de acessarmos uma fonte de dados em um SGBD relacional. As principais são:

Cada uma oferece vantagens e desvantagens que devem ser consideradas dependendo do cenário e do objetivo da nossa aplicação.

Neste artigo eu vou usar ADO .NET e vou também separar as responsabilidades criando uma classe que irá realizar o acesso aos dados de forma que teremos no formulário apenas o código que irá chamar a classe e exibir os dados.

Você vai encontrar com muita frequência na web muitos artigos sobre ADO .NET(incluindo artigos do site macoratti.net) onde o acesso aos dados é feito no próprio formulário. Abaixo temos um trecho de código que acessa os dados de um banco de dados SQL Server e retorna um dataset em um evento Click de um botão de comando de um formulário:

Dim conexao As SqlConnection = New sqlconnection()
conexao.ConnectionString = "Data Source=(LocalDB)\v11.0;Initial Catalog=Estoque;Integrated Security=True"
conexao.Open()
Dim adp As SqlDataAdapter = New SqlDataAdapter("select * from Categorias",conexao)
Dim ds As DataSet = New DataSet()
adp.Fill(ds)

Esta é uma abordagem ingênua que se justifica apenas pela simplicidade mas que sempre deve ser desencorajada.

No menu PROJECT clique em Add Class e a seguir selecione o template Class e informe o nome AcessoBD.vb e clique em Add;

A classe AcessoBD deverá possuir os métodos que no nosso caso retornam os dados das tabelas Categorias e Produtos.

Vamos aproveitar e usar três conceitos importantes da orientação a objetos : herança , interface e classe abstrata.

Vamos definir uma classe abstrata chamada DALBase que deverá implementar a interface IDisposable.

Esta classe deverá obter e retornar uma conexão do tipo SqlConnection e deverá ser herdada pela classe AcessoBD.

No menu PROJECT clique em Add Class e a seguir selecione o template Class e informe o nome DALBase.vb e clique em Add;

Neste momento temos então duas classes em nosso projeto; a classe AcessoBD e a classe DALBase.

Vamos começar definindo o código da classe DALBase:

Imports System.Data.SqlClient


Public
MustInherit Class DALBase

                           Implements IDisposable


 
Private _connection As SqlConnection

   Private conexaoBD As String = System.Configuration.ConfigurationManager.ConnectionStrings("ConexaoSQLServer").ToString()


   Protected
Sub New(ByVal conexaoBD As String)

        _connection = New SqlConnection(conexaoBD)

   End Sub

 

  Protected Sub New()

     _connection = New SqlConnection(conexaoBD)

   End Sub
 

  Protected Sub conectaBD()

      _connection = New SqlConnection(conexaoBD)

      _connection.Open()

  End Sub
 

  Protected ReadOnly Property Connection() As SqlConnection

        Get

        Return _connection

       End Get

  End Property
 

  Public Sub Dispose() Implements IDisposable.Dispose

       _connection.Dispose()

   End Sub

End Class

Esta classe apenas obtém a string de conexão do arquivo App.Config , retorna uma conexão e também encerra um conexão.

Agora podemos definir o código da classe AcessoBD conforme abaixo. Esta classe herda da classe DALBase.

Imports System.Data.SqlClient
Imports System.Configuration
Public Class AcessoBD
          Inherits DALBase
    Public Sub New()
    End Sub
    
    Public Sub AbrirConexao()
        Me.Connection.Open()
    End Sub

    Public Function GetDadosDataSetProdutos(ByVal codigo As Integer) As DataSet
        Try
            conectaBD()
            Dim da As New SqlDataAdapter("Select * from Produtos where categoriaid = " & codigo, Me.Connection)
            da.SelectCommand.CommandType = CommandType.Text
            Dim ds As New DataSet()
            da.Fill(ds)
            Return ds
        Catch ex As Exception
            Throw ex
        Finally
            Me.Connection.Dispose()
        End Try
    End Function

    Public Function GetDadosDataTableCategorias() As DataTable
        Try
            conectaBD()
            Dim da As New SqlDataAdapter("Select * from Categorias", Me.Connection)
            Dim dt As New DataTable()
            da.Fill(dt)
            Return dt(0).Table
        Catch ex As Exception
            Throw ex
        Finally
            Me.Connection.Dispose()
        End Try
    End Function
End Class

Temos dois métodos principais nesta classe :

Agora voltemos ao formulário form1.vb onde no evento Load vamos chamar a rotina carregaCategorias() que deverá preencher o controle cobCategorias com dados da tabela Categorias;

Para isso criamos uma instância da classe AcessoBD e usamos o método GetDadosDataTableCategorias;

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        carregaCategorias()
    End Sub

    Private Sub carregaCategorias()
        Dim conecta As New AcessoBD
        With cboCategorias
            .DataSource = conecta.GetDadosDataTableCategorias()
            .DisplayMember = "nome"
            .ValueMember = "categoriaid"
        End With
    End Sub   

No evento SelectedIndexChange da combobox cboCategorias vamos definir o código que irá preencher a combobox cboProdutos usando o método GetDadosDataSetProdutos da classe AcessoBD;

 Private Sub cboCategorias_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboCategorias.SelectedIndexChanged
        Try
           Dim item As Integer = 0
             Dim conecta As New AcessoBD
            With cboProdutos
                 item = DirectCast(cboCategorias.SelectedItem, DataRowView).Item("CategoriaId")
                .DataSource = conecta.GetDadosDataSetProdutos(item).Tables(0)
                .DisplayMember = "nome"
                .ValueMember = "produtoid"
            End With
        Catch ex As Exception
            MessageBox.Show(" Erro " & ex.Message)
        End Try
    End Sub
End Class

Executando o projeto vemos que a seleção de um item na combobox cboCategorias filtra os dados exibidos na combobox cboProdutos exibindo os produtos relacionados com a categoria escolhida:

Acabei . Até o próximo artigo VB.NET .

Pegue o projeto completo aqui: SincronizandoCombobox.zip

Rom_6:23 Porque o salário do pecado é a morte, mas o dom gratuito de Deus é a vida eterna em Cristo Jesus nosso Senhor.

Referências:


José Carlos Macoratti