Llenar un TreeView desde un DataSet usando un método recurrente
Utilizar la jerarquía definida en los datos de una tabla para llenar el TreeView con un método recurrente sencillo.

Fecha: 13/Ene/2005 (12/Ene/05)
Autor: Serge Valsse (svalsse@hotmail.com)

 


En muchas oportunidades he necesitado llenar un TreeView con los datos contenidos en una tabla de mi base de datos. Normalmente se tiene bien clara la jerarquía de los datos que se desean mostrar en la misma estructura de la tabla y esto se puede aprovechar para evitar estar definiendo nodo por nodo en el TreeView.

De igual manera si los datos que llenarán el TreeView no están en una tabla se puede generar un DataSet con los diferentes modos que existen y obtener la estructura que se requiere para este método que describiré en este artículo.

Supongamos que tenemos una tabla en nuestra base de datos con la siguiente estructura y datos:


Figura 1. Estructura de Tabla de origen de datos para llenar TreeView.



Obviamente los nombres pueden ser diferentes, pero para el ejemplo se necesitan que se llamen así.

NombreNodo: Deberá contener el texto que se desea desplegar en el TreeView como nodo.

IdentificadorNodo: Un número único que identifica a cada nodo. Puede ser el valor de la llave primaria de la tabla o algún otro campo calculado pero que sea único. Para este ejemplo es númerico pero puede ser string si así se requiere haciendo los cambios respectivos en el código desde luego.

IdentificadorPadre: Este campo debe contener el IdentificadorNodo del Nodo del cual depende es Nodo representado en el registro.

Para el ejemplo vamos a utilizar los siguientes datos:


Figura 2. Ejemplo de datos con jerarquía definida para llenar TreeView.



Si observamos el IdentificadorNodo del "Nodo 1" (que es 1), está en el campo IdentificadorPadre del "Nodo 1.1" y "Nodo 1.2", esto indica que serán hijos de "Nodo 1", de igual manera "Nodo 1.1.1" y "Nodo 1.1.2" serán hijos de "Nodo 1.1" ya que contienen en IdentificadorPadre el IdentificadorNodo que corresponde a este (2 para este caso).

Observe que los Nodos del primer nivel, es decir los que no tienen Padre deben llevar el valor 0 (cero) en el campo IdentificadorPadre ya que no dependen de nadie.

Bien, veamos ahora cual es el código del método que hará el trabajo de llenar el TreeView utilizando toda esta estructura de datos.



Creación de un formulario que llene un TreeView desde un DataSet usando un método recurrente

Para el ejemplo seguiremos los siguientes pasos:

1. Crear un proyecto de tipo Proyectos de Visual C#, Aplicación para Windows y llámelo EjemploTreeView.

2. En el formulario generado (Form1) agrege dos controles, un TreeView y un Button. Desde la ventana de propiedades del botón asignar la propiedad Text = "Llenar TreeView".

3. Declare un DataSet que pueda ser vista por toda la clase Form1.

    System.Data.DataSet dataSetArbol;


4. En la ventana de Código agrege el método que se ejecutará recurrentemente llamándolo CrearNodosDelPadre.

    private void CrearNodosDelPadre(int indicePadre, TreeNode nodePadre) 
    {   
        // Crear un DataView con los Nodos que dependen del Nodo padre pasado como parámetro.
        DataView dataViewHijos = new DataView(dataSetArbol.Tables["TablaArbol"]);
        dataViewHijos.RowFilter = dataSetArbol.Tables["TablaArbol"].Columns["IdentificadorPadre"].ColumnName + " = " + indicePadre;

        // Agregar al TreeView los nodos Hijos que se han obtenido en el DataView.
        foreach(DataRowView dataRowCurrent in dataViewHijos) 
        {
            TreeNode nuevoNodo = new TreeNode();                                                                
            nuevoNodo.Text = dataRowCurrent["NombreNodo"].ToString().Trim();

            // si el parámetro nodoPadre es nulo es porque es la primera llamada, son los Nodos
            // del primer nivel que no dependen de otro nodo.
            if(nodePadre == null) 
            {
                treeView1.Nodes.Add(nuevoNodo);
            } 
            // se añade el nuevo nodo al nodo padre.
            else 
            {
                nodePadre.Nodes.Add(nuevoNodo);
            }

            // Llamada recurrente al mismo método para agregar los Hijos del Nodo recién agregado.

            CrearNodosDelPadre(Int32.Parse(dataRowCurrent["IdentificadorNodo"].ToString()), nuevoNodo);
        }                        
    }
5. Para simplificar el ejemplo, adicione los siguientes métodos que simularán los datos obtenidos desde una base de datos.


    // Los siguientes dos métodos son para el ejemplo, el dataset puede ser llenado desde una tabla
    // de la base de datos. Lo importante es que contenga un equivalente a los tres campos que se
    // llenan aqui.
    private void CrearDataSet()
    {
        dataSetArbol = new DataSet("DataSetArbol");

        DataTable tablaArbol = dataSetArbol.Tables.Add("TablaArbol");
        tablaArbol.Columns.Add("NombreNodo",typeof(string));
        tablaArbol.Columns.Add("IdentificadorNodo",typeof(Int32));
        tablaArbol.Columns.Add("IdentificadorPadre",typeof(Int32));

        InsertarDataRow("Nodo 1",1,0);
        InsertarDataRow("Nodo 1.1",2,1);
        InsertarDataRow("Nodo 1.1.1",3,2);
        InsertarDataRow("Nodo 1.1.2",4,2);
        InsertarDataRow("Nodo 1.2",5,1);

        InsertarDataRow("Nodo 2",6,0);
        InsertarDataRow("Nodo 2.1",7,6);
        InsertarDataRow("Nodo 2.2",8,6);

        InsertarDataRow("Nodo 3",9,0);
        InsertarDataRow("Nodo 3.1",10,9);
        InsertarDataRow("Nodo 3.2",11,9);
    }

    private void InsertarDataRow(string column1, int column2, int column3)
    {
        DataRow nuevaFila = dataSetArbol.Tables["TablaArbol"].NewRow();
        nuevaFila["NombreNodo"] = column1;
        nuevaFila["IdentificadorNodo"] = column2;
        nuevaFila["IdentificadorPadre"] = column3;
        dataSetArbol.Tables["TablaArbol"].Rows.Add(nuevaFila);
    }
6. En el constructor de la clase Form1() ingrese la llamada al método que llenará el DataSet. El código quedará como sigue:


    public Form1()
    {
        //
        // Required for Windows Form Designer support
        //
        InitializeComponent();

        //
        // TODO: Add any constructor code after InitializeComponent call
        //
        CrearDataSet();
    }
7. Finalmente en el evento Click del boton button1 asocie el método siguiente que llamará al método para el llenado del TreeView.


    private void button1_Click(object sender, System.EventArgs e)
    {
        // Llamar al método por primera vez que llenará el TreeView, este método se llamará luego
        // a sí mismo recurrentemente.
        CrearNodosDelPadre(0, null);
    }
8. Compile y ejecute el proyecto. Lo que obtendremos es lo siguiente:


Figura 3. Resultado después de hacer Click en el botón "Llenar TreeView".



Si necesitas obtener el IdentificadorNode del Nodo que el usuario selecciona se puede utilizar la propiedad Tag del nodo, por supuesto si previamente en la creación del nodo se almacenó dicho valor en esta propiedad.

Por favor no olvides calificar el artículo en la caja de PanoramaBox que se muestra al inicio de la página.

Serge Valsse
svalsse@hotmail.com


 


ir al índice