none
Treeview recursivo com c# RRS feed

  • Pergunta

  • Olá a todos!

    Tenho uma tabela com as seguintes colunas e informações:
    IDGRUPO, DESCRICAO, IDPAI
    1               root              null
    2               Nive1            1 1               Nivel1           1
    3               Nivel1           1
    4               Nivel2           2
    5               Nivel2           2
    6               Nivel3           4
    7               Nivel4           6

    Preciso preencher uma Treeview com as informções que estão contidas neste banco de dados de forma hierarquica
    sendo que pode existe N níveis.

    Como fazer isso?

    Desde já agradeço a todos.
    • Editado Rapapell segunda-feira, 30 de dezembro de 2013 11:45
    segunda-feira, 30 de dezembro de 2013 11:44

Respostas

  • Olá Fulvio, primeiramente Feliz ano novo !

    Testei seu código em windows forms e funcionou perfeitamente.

    Porém o projeto que estou desenvolvendo é WEB e as funções contidas no treeview do web forms são diferentes do windows forms.

    Peço desculpas por não ter informado no cabeçalho, mas como sou iniciante, imaginei que o componente treeview seria igual tanto no windows quanto no web.

    Seria possível você fazer a mesma solução no projeto web pois tentei converter e não conseguiu.

    Um abraço

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:TreeView ID="TreeView1" runat="server"></asp:TreeView>
        </div>
        </form>
    </body>
    </html>


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    public class Layout
    {
        public int IDGRUPO { get; set; }
        public string DESCRICAO { get; set; }
        public int? IDPai { get; set; }
    }
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
                Carregar_TreeView();
        }
        protected void Carregar_TreeView()
        {
            var Listas = new Layout[] {
    	          new Layout{ IDGRUPO = 1, DESCRICAO = "root", IDPai = null },                       
    	          new Layout{ IDGRUPO = 2, DESCRICAO = "Nivel1 - Pai 1 - 2", IDPai = 1 },
    	          new Layout{ IDGRUPO = 3, DESCRICAO = "Nivel1 - Pai 1 - 3", IDPai = 1 },
    	          new Layout{ IDGRUPO = 4, DESCRICAO = "Nivel1 - Pai 1 - 4", IDPai = 1 }, 
    	          new Layout{ IDGRUPO = 6, DESCRICAO = "Nivel2 - Pai 2 - 6", IDPai = 2 },                      
    	          new Layout{ IDGRUPO = 7, DESCRICAO = "Nivel3 - Pai 4 - 7", IDPai = 4 },
    	          new Layout{ IDGRUPO = 8, DESCRICAO = "Nivel4 - Pai 6 - 6", IDPai = 6 },
    	          new Layout{ IDGRUPO = 9, DESCRICAO = "Nivel4 - Pai 9 - 100", IDPai = 8 }
                };
            var itemRoot = Listas.FirstOrDefault(x => x.IDPai == null);
            if (itemRoot != null)
            {
                TreeView1.Nodes.Add(new TreeNode(itemRoot.DESCRICAO, itemRoot.IDGRUPO.ToString(), "", "", ""));            
            }
            TreeNode nodeRoot = TreeView1.Nodes.OfType<TreeNode>().FirstOrDefault(x => x.Text == "root");
            foreach (Layout lista in Listas.Where(x => x.IDPai != null).OrderBy(o => o.IDGRUPO).ThenBy(t => t.IDPai).ToList())
            {
                TreeNode node = Find(nodeRoot.ChildNodes, lista.IDPai);
                if (node != null)
                {                   
                    node.ChildNodes.Add(new TreeNode(lista.DESCRICAO, lista.IDGRUPO.ToString(), "", "", ""));
                }
                else
                {                 
                    nodeRoot.ChildNodes.Add(new TreeNode(lista.DESCRICAO, lista.IDGRUPO.ToString(), "", "", ""));
                }
            }        
        }
        protected TreeNode Find(TreeNodeCollection nodes, int? IdPai)
        {
            foreach (TreeNode node in nodes)
            {
                if (node.Value == IdPai.ToString())
                {
                    return node;
                }
                else
                {
                    if (node.ChildNodes.Count > 0)
                    {
                        TreeNode nodeFind = Find(node.ChildNodes, IdPai);
                        if (nodeFind != null)
                        {
                            return nodeFind;
                        }
                    }
                }
            }
            return null;
        }
    }




    Fulvio Cezar Canducci Dias

    • Marcado como Resposta Rapapell segunda-feira, 6 de janeiro de 2014 11:17
    sexta-feira, 3 de janeiro de 2014 00:08

Todas as Respostas

  • Eu fiz uma classe para facilitar nos filtros e pesquisas eu não sei como ta o seu ai! mas, por SQL também dá com um objeto desconectado criando uma lista !!! Primeira eu pego o cara que é o Root de IDPai igual a null, Depois orderno por grupo e vou perguntado se o IDPai tem Grupo e vou adicionando item a item ele procura e adiciona o Nó! Código Referente logo abaixo:

    Código Exemplo:

    public class Layout
    {
    	public int IDGRUPO { get; set; }
    	public string DESCRICAO { get; set; }
    	public int? IDPai { get; set; }
    }
    
    var Listas = new Layout[] {
    	  new Layout{ IDGRUPO = 1, DESCRICAO = "root", IDPai = null },                       
    	  new Layout{ IDGRUPO = 2, DESCRICAO = "Nivel1 - Pai 1 - 2", IDPai = 1 },
    	  new Layout{ IDGRUPO = 3, DESCRICAO = "Nivel1 - Pai 1 - 3", IDPai = 1 },
    	  new Layout{ IDGRUPO = 4, DESCRICAO = "Nivel1 - Pai 1 - 4", IDPai = 1 }, 
    	  new Layout{ IDGRUPO = 6, DESCRICAO = "Nivel2 - Pai 2 - 6", IDPai = 2 },                      
    	  new Layout{ IDGRUPO = 7, DESCRICAO = "Nivel3 - Pai 4 - 7", IDPai = 4 },
    	  new Layout{ IDGRUPO = 8, DESCRICAO = "Nivel4 - Pai 6 - 6", IDPai = 6 },
    	  new Layout{ IDGRUPO = 9, DESCRICAO = "Nivel4 - Pai 9 - 100", IDPai = 100 }
    };
    
    var itemRoot = Listas.FirstOrDefault(x => x.IDPai == null);
    if (itemRoot != null)
    {
    	treeView1.Nodes.Add(itemRoot.IDGRUPO.ToString(), itemRoot.DESCRICAO);
    }
    foreach (Layout lista in Listas.Where(x => x.IDPai != null).OrderBy(o => o.IDGRUPO).ThenBy(t => t.IDPai).ToList())
    {
    	TreeNode node = treeView1.Nodes.Find(lista.IDPai.ToString(), true).FirstOrDefault();
    	if (node != null)
    	{
    		node.Nodes.Add(lista.IDGRUPO.ToString(), lista.DESCRICAO);
    	}
    	else
    	{
    		treeView1.Nodes.Add(lista.IDGRUPO.ToString(), lista.DESCRICAO);
    	}                     
    }


    Fulvio Cezar Canducci Dias

    • Sugerido como Resposta Fulvio Cezar Canducci Dias segunda-feira, 30 de dezembro de 2013 19:33
    • Marcado como Resposta Rapapell segunda-feira, 6 de janeiro de 2014 11:17
    • Não Marcado como Resposta Rapapell segunda-feira, 6 de janeiro de 2014 11:17
    segunda-feira, 30 de dezembro de 2013 14:32
  • Acho que isto resolve o que você está querendo, é só fazer os ajustes para o seu caso:
    Imports Microsoft.Practices.EnterpriseLibrary.Data
    Imports Microsoft.Practices.EnterpriseLibrary.Data.Sql
    Imports System.Collections.Generic
    Imports System.Data.Common
    Imports System.Data
    Imports System.Web.UI.WebControls
    Imports System.Data.SqlClient
    
    Partial Class Main
        Inherits System.Web.UI.Page
    
        Private objDatabase As Database
        Private objDbCommand As DbCommand
        Private objTree As TreeView
        Private objDataSet As DataSet
    
        Private Sub BuildTreeView()
            objDatabase = DatabaseFactory.CreateDatabase()
            objTree = New TreeView()
    
            objDbCommand = objDatabase.GetSqlStringCommand("select id, descricao,idpai from tabela order by descricao")
            objDataSet = objDatabase.ExecuteDataSet(objDbCommand)
    
            Dim nodo As TreeNode = Nothing
            Dim id As Integer = 1
            Try
                For Each row As DataRow In objDataSet.Tables(0).Rows
                    If id <> row("id") Then
                        ''Nodo Pai da Aplicação
                        AddNode(Nothing, row("id"))
                    End If
                    id = row("nroitem")
                Next
                tbTree.Rows(0).Cells(0).Controls.Add(objTree)
            Catch ex As Exception
                Throw ex
            End Try
        End Sub
    
        ''' <summary>
        ''' Método que adiciona os nodos filhos de um determinado nodo 
        ''' </summary>
        ''' <param name="p_pai">Pai do nodo p_Id</param>
        ''' <param name="p_id">Id do nodo a ser verificado os filhos</param>
        ''' <remarks></remarks>
        Private Sub AddNode(ByVal p_pai As TreeNode, ByVal p_id As Integer)
            Dim rows As DataRow()
            Dim node As TreeNode
            If Not p_pai Is Nothing Then
                rows = GetChilds(objDataSet, p_id)
                ''Varrendo todos os filhos do pai
                For Each row As DataRow In rows
                    node = New TreeNode(row("descricao").ToString())
                    p_pai.ChildNodes.Add(node)
                    If HasChilds(row) Then
                        AddNode(node, row("id"))
                    End If
                Next
            Else ''Adicionando o pai
                rows = objDataSet.Tables(0).Select(String.Format("id={0} and idpai is null", p_id.ToString()))
                If rows.Length > 0 Then
                    node = New TreeNode(rows(0)("descricao"))
                    objTree.Nodes.Add(node)
                    AddNode(node, p_id)
                End If
            End If
    
        End Sub
    
        ''' <summary>
        ''' Método que recupera as linhas filhas de um Id no Dataset que representa a listagem dos Menus
        ''' </summary>
        ''' <param name="p_ds">DataSet</param>
        ''' <param name="p_value">Id</param>
        ''' <returns>Lista de linhas do DataSet</returns>
        ''' <remarks></remarks>
        Private Function GetChilds(ByVal p_ds As DataSet, ByVal p_value As Integer) As DataRow()
            Return objDataSet.Tables(0).Select(String.Format("idpai={0}", p_value.ToString()))
        End Function
    
        ''' <summary>
        ''' Método que informa se uma linha possui filhas
        ''' </summary>
        ''' <param name="p_row">Linha do DataSet a ser verificada</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function HasChilds(ByVal p_row As DataRow) As Boolean
            Return objDataSet.Tables(0).Select(String.Format("idpai={0}", p_row("id").ToString())).Length > 0
        End Function
    
    End Class
    
    Espero que ajude.
    segunda-feira, 30 de dezembro de 2013 19:15
  • Olá Fulvio, primeiramente Feliz ano novo !

    Testei seu código em windows forms e funcionou perfeitamente.

    Porém o projeto que estou desenvolvendo é WEB e as funções contidas no treeview do web forms são diferentes do windows forms.

    Peço desculpas por não ter informado no cabeçalho, mas como sou iniciante, imaginei que o componente treeview seria igual tanto no windows quanto no web.

    Seria possível você fazer a mesma solução no projeto web pois tentei converter e não conseguiu.

    Um abraço

    quinta-feira, 2 de janeiro de 2014 20:43
  • Agradeço a atenção Bahia, mas ainda não conheço VB =/
    quinta-feira, 2 de janeiro de 2014 20:51
  • Olá Fulvio, primeiramente Feliz ano novo !

    Testei seu código em windows forms e funcionou perfeitamente.

    Porém o projeto que estou desenvolvendo é WEB e as funções contidas no treeview do web forms são diferentes do windows forms.

    Peço desculpas por não ter informado no cabeçalho, mas como sou iniciante, imaginei que o componente treeview seria igual tanto no windows quanto no web.

    Seria possível você fazer a mesma solução no projeto web pois tentei converter e não conseguiu.

    Um abraço

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:TreeView ID="TreeView1" runat="server"></asp:TreeView>
        </div>
        </form>
    </body>
    </html>


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    public class Layout
    {
        public int IDGRUPO { get; set; }
        public string DESCRICAO { get; set; }
        public int? IDPai { get; set; }
    }
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
                Carregar_TreeView();
        }
        protected void Carregar_TreeView()
        {
            var Listas = new Layout[] {
    	          new Layout{ IDGRUPO = 1, DESCRICAO = "root", IDPai = null },                       
    	          new Layout{ IDGRUPO = 2, DESCRICAO = "Nivel1 - Pai 1 - 2", IDPai = 1 },
    	          new Layout{ IDGRUPO = 3, DESCRICAO = "Nivel1 - Pai 1 - 3", IDPai = 1 },
    	          new Layout{ IDGRUPO = 4, DESCRICAO = "Nivel1 - Pai 1 - 4", IDPai = 1 }, 
    	          new Layout{ IDGRUPO = 6, DESCRICAO = "Nivel2 - Pai 2 - 6", IDPai = 2 },                      
    	          new Layout{ IDGRUPO = 7, DESCRICAO = "Nivel3 - Pai 4 - 7", IDPai = 4 },
    	          new Layout{ IDGRUPO = 8, DESCRICAO = "Nivel4 - Pai 6 - 6", IDPai = 6 },
    	          new Layout{ IDGRUPO = 9, DESCRICAO = "Nivel4 - Pai 9 - 100", IDPai = 8 }
                };
            var itemRoot = Listas.FirstOrDefault(x => x.IDPai == null);
            if (itemRoot != null)
            {
                TreeView1.Nodes.Add(new TreeNode(itemRoot.DESCRICAO, itemRoot.IDGRUPO.ToString(), "", "", ""));            
            }
            TreeNode nodeRoot = TreeView1.Nodes.OfType<TreeNode>().FirstOrDefault(x => x.Text == "root");
            foreach (Layout lista in Listas.Where(x => x.IDPai != null).OrderBy(o => o.IDGRUPO).ThenBy(t => t.IDPai).ToList())
            {
                TreeNode node = Find(nodeRoot.ChildNodes, lista.IDPai);
                if (node != null)
                {                   
                    node.ChildNodes.Add(new TreeNode(lista.DESCRICAO, lista.IDGRUPO.ToString(), "", "", ""));
                }
                else
                {                 
                    nodeRoot.ChildNodes.Add(new TreeNode(lista.DESCRICAO, lista.IDGRUPO.ToString(), "", "", ""));
                }
            }        
        }
        protected TreeNode Find(TreeNodeCollection nodes, int? IdPai)
        {
            foreach (TreeNode node in nodes)
            {
                if (node.Value == IdPai.ToString())
                {
                    return node;
                }
                else
                {
                    if (node.ChildNodes.Count > 0)
                    {
                        TreeNode nodeFind = Find(node.ChildNodes, IdPai);
                        if (nodeFind != null)
                        {
                            return nodeFind;
                        }
                    }
                }
            }
            return null;
        }
    }




    Fulvio Cezar Canducci Dias

    • Marcado como Resposta Rapapell segunda-feira, 6 de janeiro de 2014 11:17
    sexta-feira, 3 de janeiro de 2014 00:08
  • Obrigado pelo apoio Fúlvio ! Funcionou Perfeitamente !

    Sem querer abusar mas gostaria de saber duas coisas para complementar meus estudos:

    Essa técnica que você utiliza (Listas.Where(x => x.IDPai != null) é o Linq ?

    Este trecho do seu código:

    var Listas = new Layout[] {
    	          new Layout{ IDGRUPO = 1, DESCRICAO = "root", IDPai = null },                       
    	          new Layout{ IDGRUPO = 2, DESCRICAO = "Nivel1 - Pai 1 - 2", IDPai = 1 },
    	          new Layout{ IDGRUPO = 3, DESCRICAO = "Nivel1 - Pai 1 - 3", IDPai = 1 },
    	          new Layout{ IDGRUPO = 4, DESCRICAO = "Nivel1 - Pai 1 - 4", IDPai = 1 }, 
    	          new Layout{ IDGRUPO = 6, DESCRICAO = "Nivel2 - Pai 2 - 6", IDPai = 2 },                      
    	          new Layout{ IDGRUPO = 7, DESCRICAO = "Nivel3 - Pai 4 - 7", IDPai = 4 },
    	          new Layout{ IDGRUPO = 8, DESCRICAO = "Nivel4 - Pai 6 - 6", IDPai = 6 },
    	          new Layout{ IDGRUPO = 9, DESCRICAO = "Nivel4 - Pai 9 - 100", IDPai = 8 }
                };

    Irei preecher obtendo os dados do banco de dados.  Eu tenho uma classe que possui um método que busca essas informações, porém não estou conseguindo implementar. 

    Poderia me ajudar mais uma vez neste desafio?

    Mais uma vez muito obrigado!


    segunda-feira, 6 de janeiro de 2014 11:41
  • A Primeira Dúvida: é o LINQ !!!

    A Segunda Dúvida: se você tem o método que implementa essa busca é melhor você postar o método para que possa adpatar ao seu programa, sem ele fica dificil ajudar porque não sei como você traz isso da base!!!


    Fulvio Cezar Canducci Dias

    segunda-feira, 6 de janeiro de 2014 12:39
  • Esta é a classe que tem dois construtores:

    public class modelgrupo
        {
            public string IdGrupo { get; set; }
            public string Descricao { get; set; }
            public string IdPai { get; set; }

            public modelgrupo()
            {
            }

            public modelgrupo(string pIdGrupo, string pDescricao, string pIdPai)
            {
                IdGrupo = pIdGrupo;
                Descricao = pDescricao;
                IdPai = pIdPai;
            }

            public DataTable BuscarGrupos()
            {            
                using (SqlConnection Con = new SqlConnection())
                {
                    Con.ConnectionString = Properties.Settings.Default.CS1;
                    Con.Open();

                    SqlCommand Cmd = new SqlCommand();
                    string SqlAnos = "SELECT IDGRUPO, DESCRICAO, IDPAI FROM GRUPO";
                    Cmd.CommandText = SqlAnos;
                    Cmd.CommandType = CommandType.Text;
                    Cmd.Connection = Con;

                    using (SqlDataReader DR = Cmd.ExecuteReader())
                    {
                        DataTable DT = new DataTable();
                        {
                            DT.Load(DR);
                        }
                        Con.Close();
                        return DT;
                    }              
                }            
            }
        }

    O método BuscarGrupos() retorna um datatable, não sei se é ai que estou errando.

    Abraço

    terça-feira, 7 de janeiro de 2014 18:20
  • public class Layout
    { 
            public int IDGRUPO { get; set; }
            public string DESCRICAO { get; set; }
            public int? IDPai { get; set; }
    }

    Essa classe acima coloque ela no seu projeto num arquivo criando um class !!! ok!

    Depóis

    adicione um método a mais na sua página assim

    public IEnumerable<Layout> BuscarGrupos()
    {
    	using (SqlConnection Con = new SqlConnection())
    	{
    		Con.ConnectionString = Properties.Settings.Default.CS1;
    		Con.Open();
    
    		SqlCommand Cmd = new SqlCommand();
    		string SqlAnos = "SELECT IDGRUPO, DESCRICAO, IDPAI FROM GRUPO ORDER BY IDGRUPO ASC, IDPAI ASC";
    		Cmd.CommandText = SqlAnos;
    		Cmd.CommandType = CommandType.Text;
    		Cmd.Connection = Con;
    
    		using (SqlDataReader DR = Cmd.ExecuteReader())
    		{
    			if (DR.HasRows)
    			{
    				while (DR.Read())
    				{
    					yield return new Layout()
    					{
    						IDGRUPO = DR.IsDBNull(0) == false ? DR.GetInt32(0): 0,
    						DESCRICAO = DR.IsDBNull(1) == false ? DR.GetString(1) : string.Empty,
    						IDPai = DR.IsDBNull(2) == false ? (int?)DR.GetInt32(2): null
    					};
    				}
    			}
    		}
    	}
    }

    no código que eu te passei no lugar de:

    var Listas = new Layout[] {
    	          new Layout{ IDGRUPO = 1, DESCRICAO = "root", IDPai = null },                       
    	          new Layout{ IDGRUPO = 2, DESCRICAO = "Nivel1 - Pai 1 - 2", IDPai = 1 },
    	          new Layout{ IDGRUPO = 3, DESCRICAO = "Nivel1 - Pai 1 - 3", IDPai = 1 },
    	          new Layout{ IDGRUPO = 4, DESCRICAO = "Nivel1 - Pai 1 - 4", IDPai = 1 }, 
    	          new Layout{ IDGRUPO = 6, DESCRICAO = "Nivel2 - Pai 2 - 6", IDPai = 2 },                      
    	          new Layout{ IDGRUPO = 7, DESCRICAO = "Nivel3 - Pai 4 - 7", IDPai = 4 },
    	          new Layout{ IDGRUPO = 8, DESCRICAO = "Nivel4 - Pai 6 - 6", IDPai = 6 },
    	          new Layout{ IDGRUPO = 9, DESCRICAO = "Nivel4 - Pai 9 - 100", IDPai = 8 }
                };

    Coloque isso:

    var Listas = BuscarGrupos().ToArray();

    e siga o código todo abaixo igual o que eu te mandei

    Cara ta fácil, é só seguir os passos!


    Fulvio Cezar Canducci Dias


    terça-feira, 7 de janeiro de 2014 18:36
  • Cara funcionou perfeitamente ! Que legal !!!! Vou estudar essas técnicas muito bacanas. Muito obrigado Fúlvio você é ótimo. Grande abraço.
    terça-feira, 7 de janeiro de 2014 20:55
  • Cara funcionou perfeitamente ! Que legal !!!! Vou estudar essas técnicas muito bacanas. Muito obrigado Fúlvio você é ótimo. Grande abraço.

    Por nada!

    Vlw!


    Fulvio Cezar Canducci Dias

    terça-feira, 7 de janeiro de 2014 21:07