Desenvolvimento - C#

Persistindo TreeView no Banco de Dados

O intuito deste artigo é mostrar uma das maneiras possíveis de salvarmos os dados de uma TreeView no Banco de Dados para que a mesma possa ser carregada em um momento posterior.

por André Alves de Lima



1. Introdução

O intuito deste artigo é mostrar uma das maneiras possíveis de salvarmos os dados de uma TreeView no Banco de Dados para que a mesma possa ser carregada em um momento posterior.

Existem vários métodos para atender essa demanda, como utilizar-se de serialização, utilizar o componente DBTreeControl ou criar uma estrutura própria para armazenar os nós do Banco de Dados, sendo essa última a que será abordada neste artigo.

2. Representando a TreeView em um Banco de Dados Relacional

Para entendermos como podemos armazenar uma TreeView no Banco de Dados, tomemos a seguinte TreeView representada na figura abaixo como exemplo.

TreeViewOutlook.jpg

Como vocês podem observar, a seção “Mail Folders” do Outlook conta com uma TreeView para organizar a nossa lista de pastas. Toda TreeView tem uma ou mais raízes (no nosso exemplo, o nó “Personal Folders”) e nós filhos, como “Deleted Items”, “Faculdade”, “Raptors”, etc. Um detalhe importante da TreeView é que, para qualquer nó não raíz, nós sempre conseguimos identificar qual é o nó pai do mesmo.

Portanto, uma das estruturas de tabela de Banco de Dados que podem ser utilizadas para armazenar os nós de uma TreeView é a seguinte:

EstruturaTblNodesTable.jpg

A coluna CodNode é utilizada como identificador do nó, a coluna CodParentNode contará com o identificador do nó que é seu pai e a coluna Description conterá uma breve descrição do nó, que será exibida na nossa TreeView de exemplo.

Dessa forma, a TreeView do Outlook que exibimos anteriormente poderia ser armazenada da seguinte forma nessa tabela:

TreeViewOutlookNoBanco.jpg

3. Criando a aplicação para salvar a TreeView

Com o Visual Studio 2008 ou 2010, criaremos uma aplicação Windows Forms utilizando o .Net Framework 3.5.

Após o projeto ter sido criado, localize o componente da TreeView na toolbox e arraste-a para o form criado pelo Visual Studio. Dê o nome de treeViewSample para essa TreeView. Inclua também quatro Buttons (btAddNode, btRemoveNode, btSaveTreeView e btLoadTreeView) e um TextBox (tbNode) nesse form, de forma que ele fique parecido com a figura abaixo:

ExemploForm.jpg

Feito isso, iniciemos implementando os métodos de inclusão e exclusão de nós. Para tanto, no evento click do botão de “Adicionar Nó”, utilize o seguinte código:

private void btAddNode_Click(object sender, EventArgs e)

{

if (!tbNode.Text.Equals(string.Empty))

{

TreeNode newNode = new TreeNode(tbNode.Text);

if (treeViewSample.SelectedNode != null)

treeViewSample.SelectedNode.Nodes.Add(newNode);

else

treeViewSample.Nodes.Add(newNode);

if (newNode.Parent != null)

newNode.Parent.Expand();

treeViewSample.SelectedNode = null;

}

else

MessageBox.Show("Por favor, digite um texto para o novo nó!!!", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

Já para o botão de “Remover Nó”, utilize o código:

private void btRemoveNode_Click(object sender, EventArgs e)

{

if (treeViewSample.SelectedNode != null)

treeViewSample.Nodes.Remove(treeViewSample.SelectedNode);

}

Para a parte de acesso a dados, utilizaremos nesse exemplo o Linq to Sql. Portanto, adicione um novo item do tipo LINQ to SQL Classes à sua solução, dando o nome de TreeViewDB.

Na janela de edição do dbml, escolha a opção Server Explorer e adicione a conexão apontanto para o Banco de Dados onde está armazenada a tabela que persistirá a TreeView.

Uma vez encontrada a tabela na aba Server Explorer, arraste-a para dentro do dbml, para que o Visual Studio crie as classes de persistência, conforme ilustrado na figura abaixo.

ExemploDBML.jpg

Altere o nome da Parent Property to auto-relacionamento para um nome mais amigável (utilizei o nome ParentNode), conforme ilustrado na figura abaixo:

ExemploAlteraNomeRelacionamento.jpg

Feito isso, o Visual Studio já terá criado todas as classes necessárias para fazermos a persistência de dados dessa tabela.

Portanto, voltemos ao nosso form para adicionarmos um atributo com o DataContext dessa tabela:

private TreeViewDBDataContext db = new TreeViewDBDataContext();

O próximo passo é implementar o código do nosso botão que salva a TreeView no Banco. Para tanto, utilize o seguinte código:

private void btSaveTreeView_Click(object sender, EventArgs e)

{

db.NodesTables.DeleteAllOnSubmit(db.NodesTables);

db.SubmitChanges();

foreach (TreeNode node in treeViewSample.Nodes)

{

NodesTable newDBNode = new NodesTable() { Description = node.Text };

SaveChildren(node, ref newDBNode);

db.NodesTables.InsertOnSubmit(newDBNode);

}

db.SubmitChanges();

}

private void SaveChildren(TreeNode treeNode, ref NodesTable dbNode)

{

foreach (TreeNode node in treeNode.Nodes)

{

NodesTable childDBNode = new NodesTable()

{

Description = node.Text,

ParentNode = dbNode

};

SaveChildren(node, ref childDBNode);

}

}

O código acima limpa a tabela NodesTable (com a chamada DeleteAllOnSubmit) e, recursivamente, percorre o componente treeViewSample criando os registros para representar a TreeView na nossa tabela de NodesTable no Banco de Dados.

A única parte que fica faltando é o código para carregar a TreeView do Banco de Dados, que é apresentado logo abaixo:

private void btLoadTreeView_Click(object sender, EventArgs e)

{

treeViewSample.Nodes.Clear();

var rootNodes = from n in db.NodesTables

where n.CodParentNode == null

select n;

foreach (NodesTable rootNode in rootNodes)

{

TreeNode newNode = new TreeNode(rootNode.Description);

LoadChildren(ref newNode, rootNode.ChildrenNodes);

treeViewSample.Nodes.Add(newNode);

}

treeViewSample.ExpandAll();

}

private void LoadChildren(ref TreeNode treeNode, System.Data.Linq.EntitySet<NodesTable> childrenNodes)

{

foreach (NodesTable childNode in childrenNodes)

{

TreeNode newNode = new TreeNode(childNode.Description);

LoadChildren(ref newNode, childNode.ChildrenNodes);

treeNode.Nodes.Add(newNode);

}

}

Com os códigos acima, você conseguirá salvar a estrutura da TreeView na tabela NodesTable e posteriormente carregar a mesma do Banco de Dados.

4. Conclusão

Como explicado na introdução deste artigo, esse é um dos métodos que poderiam ser utilizados para salvar a estrutura da TreeView no Banco de Dados.

Em futuros artigos, apresentarei outras formas de obtermos o mesmo resultado utilizando outros métodos de persistência.

Vamos ficando por aqui. Espero que tenham gostado. Qualquer dúvida é só entrar em contato! Até a próxima!

André Alves de Lima

André Alves de Lima - http://andrealveslima.spaces.live.com