C#
- Vinculando uma fonte de dados XML a um controle TreeView
Imagine o seguinte cenário:![]()
Você trabalha em uma grande empresa que recebe dados das filiais para serem consolidados. Os dados sempre estiveram em arquivos texto que você tratava e consolidava.
A partir do mês que vem os dados passarão a vir no formato XML e você terá que acessar e exibir estas informações.
Você receberá dois arquivos : um arquivo XML contendo os dados propriamente ditos e um arquivo XSD usado para validar o arquivo XML.
|
O arquivo XML chamado de estoque.xml possui a seguinte estrutura:
| <?xml
version="1.0" standalone="yes"?> <NewDataSet> <Produtos> <ProdutoID>355</ProdutoID> <CategoriaID>16</CategoriaID> <NumeroModelo>RU007</NumeroModelo> <NomeModelo>Rain Racer 2000</NomeModelo> <ImagemProduto>image.gif</ImagemProduto> <CustoUnitario>1499.99</CustoUnitario> <Descricao>Looks like an ordinary bumbershoot, but don't be fooled! Simply place Rain Racer's tip on the ground and press the release latch.</Descricao> </Produtos> ................. <Produtos> </Produtos> <Categorias> <CategoriaID>14</CategoriaID> <NomeCategoria>Communications</NomeCategoria> </Categorias> ....................... <Categorias> <CategoriaID>20</CategoriaID> <NomeCategoria>General</NomeCategoria> </Categorias> </NewDataSet> |
Este arquivo contém informações sobre produtos e categorias e o arquivo estoque.xsd que irá validar este arquivo e definir a sua estrutura e o relacionamento entre as tabelas possui o seguinte conteúdo:
<?xml version="1.0" standalone="yes"?>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="Produtos">
<xs:complexType>
<xs:sequence>
<xs:element name="ProdutoID" msdata:ReadOnly="true" msdata:AutoIncrement="true" type="xs:int" />
<xs:element name="CategoriaID" type="xs:int" />
<xs:element name="NumeroModelo" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="NomeModelo" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="ImagemProduto" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="CustoUnitario" type="xs:decimal" />
<xs:element name="Descricao" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="3800" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Categorias">
<xs:complexType>
<xs:sequence>
<xs:element name="CategoriaID" msdata:ReadOnly="true" msdata:AutoIncrement="true" type="xs:int" />
<xs:element name="NomeCategoria" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//Produtos" />
<xs:field xpath="ProdutoID" />
</xs:unique>
<xs:unique name="Categorias_Constraint1" msdata:ConstraintName="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//Categorias" />
<xs:field xpath="CategoriaID" />
</xs:unique>
</xs:element>
</xs:schema>
|
Seu objetivo será 'destrinchar' estes arquivos, obter as informações e exibi-las em uma controle TreeView em uma aplicação Windows Forms.
Elementar não é mesmo ???
![]()
No arquivo estoque.xsd temos a definição de um dataset contendo as tabelas Categorias e Produtos e do relacionamento entre elas enquanto que no arquivo estoque.xml temos os dados.
A aplicação Windows Forms deverá exibir os dados conforme a figura abaixo:
![]() |
![]() Em um controle TreeView temos
exibidos as categorias e os respectivos produtos
Ao selecionar um produto é exibido em um controle Label a direita a sua descrição. |
E para terminar a fase de definições, você deve usar a linguagem C#.
Eu vou usar o Visual Studio 2010 beta 2 (estou usando e abusando) e criar um projeto Windows Forms Application (Menu File -> New Project) usando a linguagem C# com o nome TreeViewDataBinding;
No formulário padrão form1.cs defina o leiaute conforme mostrado na figura abaixo:
![]() |
Agora no formulário form1.cs defina o namespace System.Data pois vamos trabalhar com objetos Table, DataSet, DataRow, etc.;
using System.Data;
No formulário vamos criar também algumas classes para gerenciar as informações que serão obtidas a partir do arquivo XML e XSD.
Eu poderia ter criado as classes em um arquivo separado (seria mais aconselhável) mas resolvi criar no formulário mesmo para mostrar que podemos usar este recurso.
A seguir temos o código das classes:
public class ProdutoDataBase
{
public class Tabelas
{ //define as tabelas que iremos usas
public const string Produto = "Produtos";
public const string Categoria = "Categorias";
}
public class ProdutoCampo
{ //define os campos dos produtos que serão exibidos
public const string Nome = "NomeModelo";
public const string Descricao = "Descricao";
}
public class CategoriaCampo
{ //define o campo da categoria que será exibido
public const string Nome = "NomeCategoria";
}
//define o dataSet e o DataRelation para o relacionamento das tabelas
private DataSet dsEstoque;
DataRelation relCategoriaProduto;
public ProdutoDataBase()
{ //cria uma instância do DataSet
dsEstoque = new DataSet();
try
{
//lê o esquema e o arquivo XML que é a fonte de dados
dsEstoque.ReadXmlSchema(Application.StartupPath + "\\estoque.xsd");
dsEstoque.ReadXml(Application.StartupPath + "\\estoque.xml");
// Define o relacionamento entre Categorias e Produtos
relCategoriaProduto = new DataRelation("Prod_Cat",
dsEstoque.Tables["Categorias"].Columns["CategoriaID"],
dsEstoque.Tables["Produtos"].Columns["CategoriaID"]);
dsEstoque.Relations.Add(relCategoriaProduto);
}
catch (Exception ex)
{
MessageBox.Show(" Erro - A aplicação será encerrada : " + ex.Message);
Application.Exit();
}
}
//obtem a tabela Categorias
public DataTable getCategorias()
{
return dsEstoque.Tables["Categorias"];
}
//obtem o produto relacionado com a categoria
public DataRow[] getProdutosNaCategoria(DataRow rowParent)
{
return rowParent.GetChildRows(relCategoriaProduto);
}
//exibe a descrição do produto selecionado
public string getExibeTexto(DataRow row)
{
string text = "";
switch (row.Table.TableName)
{
case Tabelas.Produto:
text = "ID: " + row[0] + "\n";
text += "Nome: " + row[ProdutoCampo.Nome] + "\n\n";
text += row[ProdutoCampo.Descricao];
break;
}
return text;
}
}
|
Na classe ProdutoDataBase temos definidos as seguintes classes:
Nesta classe estamos acessando os arquivos XML e XSD usando do método ReadXML do objeto DataSet além de dar o suporte para acessar os dados do arquivo XML.
Agora no início do formulário vamos criar uma instância dessa classe para usar no acesso e exibição do dados.
private ProdutoDataBase DataClass = new ProdutoDataBase();
A seguir no evento Load do formulário temos o código que acessa os dados no XML da tabela Categorias e as exibe no controle TreeView;
private void Form1_Load(object sender, System.EventArgs e)
{
TreeNode noPai;
foreach (DataRow row in DataClass.getCategorias().Rows)
{
// Incluir o Nó Categoria
noPai = treeDB.Nodes.Add(row[ProdutoDataBase.CategoriaCampo.Nome].ToString());
noPai.ImageIndex = 0;
// Armazena a informação sobre a Categoria
noPai.Tag = row;
// Inclui um Nó
noPai.Nodes.Add("*");
}
}
|
A seguir no evento BeforeExpand do controle TreeView temos o código que armazena a informação sobre o produto:
private void treeDB_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e)
{
TreeNode nodeSelected, nodeChild;
nodeSelected = e.Node;
if (nodeSelected.Nodes[0].Text == "*")
{
// Limpa o Nó *
nodeSelected.Nodes.Clear();
foreach (DataRow row in
DataClass.getProdutosNaCategoria((DataRow)nodeSelected.Tag))
{
nodeChild = nodeSelected.Nodes.Add(row[ProdutoDataBase.ProdutoCampo.Nome].ToString());
// Armazena a informação sobre Produto
nodeChild.Tag = row;
nodeChild.ImageIndex = 1;
nodeChild.SelectedImageIndex = 1;
}
}
}
|
No evento AfterSelect do TreeView temos o código que exibe a informação sobre o produto no controle Label - lblinfo:
private void treeDB_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
{
lblInfo.Text = DataClass.getExibeTexto((DataRow)e.Node.Tag);
}
|
O código a seguir fecha a aplicação:
private void cmdClose_Click(object sender, System.EventArgs e)
{
this.Close();
}
|
Dessa forma exibimos os dados de um arquivo XML em um controle TreeView.
Pegue o projeto completo aqui :
TreeViewDataBinding.zip
Eu sei é apenas C#, mas eu gosto...
Referências: