VB.NET - Sincronização automática com Mestre-Detalhe
Este artigo aplica os conceitos sobre o databinding abordados nos artigos :
VB.NET - Desvendando os segredos do Data Binding no VB.NET II.
VB.NET - Lendo arquivos textos delimitados e preenchendo listas.
O gerenciador de banco de dados usado neste artigo é o MSDE onde usamos as tabelas Customers, Orders e Order Details do banco de dados é o Northwind que foi importado do MS Access conforme abordado nos artigos:
VB.NET - Preenchendo controles
via MSDE
VB.NET - Criando uma conexão
genérica para qualquer banco de dados.
MSDE - Usando o MSDEQuery.
VB.NET - Criando banco de dados,
tabelas, stored procedures e Views no MSDE
Nota: o MSDE foi substituído pelo SQL Server Express que pode ser baixado em : SQL Server Express Edition download
O objetivo deste artigo é mostrar como você pode trabalhar com mais de uma tabela exibindo registros relacionados em uma estrutura Mestre-Detalhe usando o databinding. Vamos exibir os dados tabela Customers com seus dados relacionados na tabela Orders que por sua vez irá exibir os dados relacionados na tabela Orders Details.
Inicie um novo projeto no VS.NET e no formulário padrão insira os seguintes controles (conforme figura abaixo):
TextBox, GroupBox, Button, DataGrid
Ao executar o projeto o resultado será o exibido no formulário da figura abaixo:
Mas qual é mágica que estar por trás disto ? Como os registros são exibidos sincronizados usando uma estrutura do tipo Mestre-Detalhe ? Como conseguimos exibir os dados relacionados de 3 tabelas diferentes ?
Tratando os relacionamentos entre as tabelas com o DataRelation
Uma das funções primárias do objeto DataRelation é permitir a navegação de um DataTable para outro em um DataSet. Com isto estamos aptos a retornar todos os objetos DataRow relacionados em um DataTable usando um único DataRow de uma tabela relacionada. Assim depois de estabelecer um relacionamento entre a tabela Customers e a tabela Orders podemos retornar todos os registros de pedidos(orders) para um cliente(customer) particular usando o método DataRows.GetChildRows.
Se tivermos dois controles vinculados ao mesmo datasource, e não quisermos compartilhar a mesma posição , devemos estar certos de que o membro BindingContext de um controle difere do outro membro BindingContext do outro controle. Se ambos tiverem o mesmo BindingContext eles irão compartilhar a mesma posição no datasource.
Se incluímos uma Combobox e um DataGrid , como é o caso do nosso exemplo, em um formulário, o comportamento padrão é para que o membro BindingContext de cada um dos dois controles seja definido para o BindingContext do formulário. Assim , o comportamento padrão é para que o DataGrid e o Combobox compartilhem o mesmo BindingContext e dai a seleção na combobox estará sincronizada com a linha atual do DataGrid. Para não termos este comportamento devemos criar um novo membro BindingContext para um dos controles.
O código do projeto que cria os relacionamentos no DataSet entre as tabelas Customers, Orders e Orders Details é o seguinte :
'define o relacionamento entre as tabelas Customers e Orders Dim relCustOrd As System.Data.DataRelation Dim colMestre As System.Data.DataColumn Dim colDetalhe As System.Data.DataColumn colMestre = ds.Tables("Customers").Columns("CustomerID") colDetalhe = ds.Tables("Orders").Columns("CustomerID") relCustOrd = New System.Data.DataRelation("RelCustOrd", colMestre, colDetalhe) 'inclui o relacionamento entre a tabela Customers e Orders no dataset ds.Relations.Add(relCustOrd) 'define o relacionamento entre as tabelas Orders e Orders Details Dim relOrdDet As System.Data.DataRelation Dim colMestre2 As System.Data.DataColumn Dim colDetalhe2 As System.Data.DataColumn colMestre2 = ds.Tables("Orders").Columns("OrderID") colDetalhe2 = ds.Tables("OrderDetails").Columns("OrderID") relOrdDet = New System.Data.DataRelation("RelOrdDet", colMestre, colDetalhe2) 'inclui o relacionamento entre a tabela Orders e Orders Details no dataset ds.Relations.Add(relOrdDet) ....... |
Ele procurar reproduzir o relacionamento entre as tabelas:
Naturalmente o código que cria a conexão, o dataset já esta anteriormente definido conforme abaixo:
ConnectionString = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Northwind; _ User ID=sa;password=;Data Source=MACORATI\VSDOTNET" Dim cn As SqlConnection = New SqlConnection(ConnectionString) ds = New DataSet("CustOrders") Dim da1 As SqlDataAdapter = New SqlDataAdapter("SELECT * FROM Customers", cn) da1.TableMappings.Add("Table", "Customers") da1.Fill(ds) Dim da2 As SqlDataAdapter = New SqlDataAdapter("SELECT * FROM Orders", cn) da2.TableMappings.Add("Table", "Orders") da2.Fill(ds) Dim da3 As SqlDataAdapter = New SqlDataAdapter("SELECT * FROM [Order Details]", cn) da3.TableMappings.Add("Table", "OrderDetails") da3.Fill(ds) ....... |
A seguir basta efetuar a vinculação dos dados com o DataGrid e a Combobox.
O exemplo exibe um DataGrid para
os Pedidos (Orders) e outro para os detalhes(Orders Details). Os dados do
cliente são exibidos em controles TextBox e Combobox.
Ao alterar o cliente selecionado os dados de cada DataGrid são atualizados e
exibem os pedidos para o cliente atual. Afim de vincular os dois objetos
DataGrids devemos definir o DataSource de cada DataGrid para o mesmo DataSet.
Também devemos definir as propriedades do DataMembr para indicar o
BindingContext com o qual eles estão relacionados. Fazemos isto definindo o
DataMember para os DataGrids para o nome do relacionamento entre as tabelas
Customers e Orders; o mesmo é feito para a tabela
Orders e Orders Details.
dsView = ds.DefaultViewManager 'vinculando as tabelas e seus relacionamentos dgPedidos.DataSource = dsView dgPedidos.DataMember = "Customers.RelCustOrd" dgDetalhesPedidos.DataSource = dsView dgDetalhesPedidos.DataMember = "Customers.RelCustOrd.RelOrdDet" 'vinculação da ComboBox cbNome.DataSource = dsView cbNome.DisplayMember = "Customers.CompanyName" cbNome.ValueMember = "Customers.CustomerID" 'vinculação dos TextBox txtContato.DataBindings.Add("Text", dsView, "Customers.ContactName") txtFone.DataBindings.Add("Text", dsView, "Customers.Phone") txtFax.DataBindings.Add("Text", dsView, "Customers.Fax")
|
Para controlar a navegação definimos os códigos presentes no evento Click
de cada um dos botões de comando:
Private Sub btnAnterior_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnterior.Click If Me.BindingContext(dsView, "Customers").Position > 0 Then System.Math.Max(System.Threading.Interlocked.Decrement(Me.BindingContext(dsView, "Customers").Position), _ Me.BindingContext(dsView, "Customers").Position + 1) End If End Sub |
Botão Anterior |
Private Sub btnProximo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnProximo.Click Dim cm As CurrencyManager = CType(Me.BindingContext(dsView, "Customers"), CurrencyManager) If cm.Position < cm.Count - 1 Then System.Math.Min(System.Threading.Interlocked.Increment(cm.Position), cm.Position - 1) End If End Sub
|
Botão Próximo |
Com isto acabamos de mostrar como você conseguiu , sem muito esforço, tratar os dados de 3 tabelas relacionadas exibindo-os em uma estrutura Mestre-Detalhe sincronizada.
Use o seu talento e incremente a aplicação incluindo o tratamento de erros e outros detalhes...
Pegue o código completo do projeto aqui : dbMestreDetalhe.zip
Eu sei é apenas VB.NET mas eu gosto ...
Veja os
Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique
e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ? |
Gostou ?
Compartilhe no Facebook
Compartilhe no Twitter
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
VB6 - DataGrid, MSFlexGrid e alguns conceitos básicos. - Macoratti.net
VB .NET - DataGridView - Selecionando e exibindo ... - Macoratti.net