Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Carga de Treeview desde una tabla

2,518 views
Skip to first unread message

Geovanny Quirós C.

unread,
Jul 31, 2008, 4:31:12 PM7/31/08
to
Hola grupo,
estoy cargando un treeview desde una tabla, el asunto es que me da un error y no se como solucionarlo.
Les explico:
tengo una tabla que tiene los padres y los hijos de los nodos, los diferencio por un codigo y hago dos consultas a la misma tabla para poder armar el arbol.
Adjunto el trozo de codigo y la linea del error es esta:

dvHijos.RowFilter = "codpadre = " & dr("codpadre"

Aqui me dice  " Cannot find column [CR]."  y "CR" es justamente el valor del campo no el nombre de la columna

 

codigo:

'Instancias de los objetos

Dim cncadena As String

cncadena = connectionString01

cn =

New SqlConnection(cncadena) 'Conexi¢n

'Adaptadores

daPadres =

New SqlDataAdapter("Select * from arbol01 where padre=1", cn)

daHijos =

New SqlDataAdapter("Select * from arbol01 where padre=0", cn)

'DataSet

dsDatos =

New DataSet

'Llenar el DataSet

daPadres.Fill(dsDatos,

"Padres")

daHijos.Fill(dsDatos,

"Hijos")

'La vista

dvHijos = dsDatos.Tables(

"Hijos").DefaultView

'El TreeView - Nodo Ra¡z

TRVMenu.Nodes.Add(

"Menu principal")

'Llenar el TreeView

Dim dr As DataRow

Dim nodo As TreeNode

For Each dr In dsDatos.Tables("Padres").Rows

'Llenar todos los padres - Textopadre

nodo = TRVMenu.Nodes(0).Nodes.Add(dr(

"textopadre"))

'Llenar los hijos de cada padre

dvHijos.RowFilter =

"codpadre = " & dr("codpadre")

Dim i As Integer

For i = 0 To dvHijos.Count - 1

nodo.Nodes.Add(dvHijos.Item(i).Row(

"textohijo"))

Next

Next

_______________
 
Geovanny Quirós C.
Heredia, Costa Rica

SoftJaén

unread,
Aug 1, 2008, 1:31:19 AM8/1/08
to
"Geovanny Quirós C." escribió:

> estoy cargando un treeview desde una tabla, el asunto es que me
> da un error y no se como solucionarlo.
>
> Les explico:
> tengo una tabla que tiene los padres y los hijos de los nodos, los
> diferencio por un codigo y hago dos consultas a la misma tabla para poder
> armar el arbol.
>
> Adjunto el trozo de codigo y la linea del error es esta:
> dvHijos.RowFilter = "codpadre = " & dr("codpadre")
>
> Aqui me dice " Cannot find column [CR]." y "CR" es justamente el valor
> del campo no el nombre de la columna

Hola, Geovanny:

Ese error lo obtienes porque no estás encerrando entre comillas simples el
valor devuelto por el objeto DataRow:

dvHijos.RowFilter = "codpadre ='" & dr("codpadre").ToString & "'"

De todas maneras, y observando el código fuente que has publicado, creo que
te estás complicando la vida para rellenar el objeto TreeView.

Lo habitual en estos casos es disponer de dos tablas en la base de datos
para poder relacionarlas a través de un campo común: una tabla sería la
tabla Padres y otra la tabla Hijos, donde ambas tendría un campo llamado
«IdPadre» que sería el que utilizarías para crear una relación «uno a
varios» entre las tablas Padres e Hijos.

Pero no es necesario que establezcas la relación en la misma base de datos,
porque la podemos crear en tiempo de ejecución, tal y como muestra el
siguiente ejemplo, que asume que en tu base de datos SQL Server tienes las
siguientes tablas:

Tabla Padres
==========

IdPadre Clave principal
Nombre

Tabla Hijos
========

IdHijo Clave principal
Nombre
IdPadre Igual al IdPadre de la tabla Padres

Para rellenar el objeto TreeView ejecutarías lo siguiente:

' Conexión con la base de datos
'
Dim cnn As New SqlConnection("Data Source=(local);" & _
"Initial Catalog=Nombre_Base_Datos;" & _
"Integrated Security=SSPI")

' DataAdapters
Dim daPadres As New SqlDataAdapter("Select * from Padres", cnn)
Dim daHijos As New SqlDataAdapter("Select * from Hijos", cnn)

' DataSet
Dim dsDatos As New DataSet

' Llenar el DataSet
daPadres.Fill(dsDatos, "Padres")
daHijos.Fill(dsDatos, "Hijos")

' Creamos una relación a través del campo IdPadre común en
' ambos objetos DataTable.
'
Dim parentColumn As DataColumn = _
dsDatos.Tables("Padres").Columns("IdPadre")

Dim childColumn As DataColumn = _
dsDatos.Tables("Hijos").Columns("IdPadre")

Dim rel As DataRelation = _
New DataRelation("Padres_Hijos", _
parentColumn, childColumn, True)

' Añadimos la relación al objeto DataSet.
'
dsDatos.Relations.Add(rel)

' Para que no se repinte el control TreeView hasta que
' se hayan creado los nodos.
'
TreeView1.BeginUpdate()

' Limpiamos el control TreeView.
TreeView1.Nodes.Clear()

' Añadimos un objeto TreeNode ra¡z para cada objeto Padre
' existente en el objeto DataTable llamado Padres.
'
For Each padre As DataRow In dsDatos.Tables("Padres").Rows

' Creamos el nodo padre.
Dim parentNode As TreeNode = _
New TreeNode(padre.Item("Nombre").ToString)

' Lo añadimos a la colección Nodes del control TreeView.
TreeView1.Nodes.Add(parentNode)

' Añadimos un objeto TreeNode hijo por cada objeto Hijo existente
' en el objeto Padre actual.
'
For Each hijo In padre.GetChildRows("Padres_Hijos")
' Creamos el nodo hijo
Dim childNode As TreeNode = _
New TreeNode(hijo.Item("Nombre").ToString)

' Lo añadimos al nodo padre
parentNode.Nodes.Add(childNode)
Next

Next

' Repintamos TreeView.
'
TreeView1.EndUpdate()

¡Eso es todo! Como podrás comprobar, utilizando una relación entre ambas
tablas, no tienes que estar filtrando datos en un objeto DataView porque no
sería necesario utilizarlo.

Para probar el ejemplo, mejor será que crees un nuevo proyecto, añadas al
formulario de inicio un control TreeView, y modifiques la cadena de conexión
para que se adapte a tus necesidades. Por supuesto, vuelvo a insistir que en
el ejemplo se asume que en la base de datos existen dos tablas llamadas
Padres e Hijos (u otras tablas con otros nombres), que más o menos tengan la
misma estructura que he indicado anteriormente.

Un saludo

--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.

AlanCSR

unread,
Aug 1, 2008, 9:17:35 AM8/1/08
to
Hola Enrique:

Una vez cargado el treeview con las opciones, como podria hacer para que al
dar un CLICK sobre un nodo, se cargue un formulario asociado al nodo?.
Asumiendo que en la tabla Hijos he añadido un campo llamado formulario el
cual contendra el nombre del formulario ha cargar.

Alan

AlanCSR

unread,
Aug 1, 2008, 9:17:35 AM8/1/08
to

SoftJaén

unread,
Aug 1, 2008, 9:51:44 AM8/1/08
to
"AlanCSR" preguntó:

Hola, Alan:

Entiendo que lo que deseas hacer es referenciar un formulario por el nombre
de éste, es decir, si seleccionas un elemento del control TreeView llamado
«Form23» que se muestre dicho formulario. Para ello tendrás que utilizar el
espacio de nombres System.Reflection. Si por ejemplo, tu proyecto se llama
«WindowsApplication1», y dentro de él tienes una clase Form llamada
«Form23», referenciarías dicho formulario ejecutando el siguiente código en
el evento «NodeMouseClick» del control TreeView:

Private Sub TreeView1_NodeMouseClick( ... )

' Referenciamos el nodo donde se ha efectuado el clic
'
Dim childNode As TreeNode = e.Node

' Si no es un nodo hijo, abandonamos el procedimiento
'
If childNode.Parent Is Nothing Then Return

Try
' Referenciamos el ensamblado que se está ejecutando.
'
Dim asm As System.Reflection.Assembly = _
System.Reflection.Assembly.GetExecutingAssembly()

' Obtenemos una referencia de un objeto Form por su nombre.
'
Dim frm As Form = _
DirectCast(asm.CreateInstance("TreeViewDemo." & _
childNode.Text), Form)

frm.Show()

Catch ex As Exception
MessageBox.Show(ex.Message)

End Try

End Sub

Geovanny Quirós C.

unread,
Aug 1, 2008, 10:18:42 AM8/1/08
to
Excelente Enrique, voy a realizar los cambios que me recomiendas.
Muchas gracias

________________

Geovanny Quirós C.
Heredia, Costa Rica


"SoftJaén" <grupo_n...@softjaen.es> escribió en el mensaje de
noticias:OzNyaf5...@TK2MSFTNGP02.phx.gbl...

Alan Salazar Romero

unread,
Aug 3, 2008, 1:12:49 AM8/3/08
to
Hola Enrique:

Probe el codigo que enviaste.

Hice dos correciones para que corriera:

> Private Sub TreeView1_NodeMouseClick( ... )

> .....
> Try
> .....


> Dim frm As Form = _
> DirectCast(asm.CreateInstance("TreeViewDemo." & _
> childNode.Text), Form)

Private Sub TreeView1_NodeMouseClick( ... )

.....
Try
.....


Dim frm As Form = _

DirectCast(asm.CreateInstance("WindowsApplication1." & _
childNode.Text.Trim), Form)


Ahora, segun el ejemplo por lo que pude ver trabaja con un arbol a dos
niveles (padre-hijo), que tan complicado se pone si desearamos que tuviera
"n" niveles y siguieramos utilizando tablas para construir el TreeView ?

Con guias como las que siempre nos proporcionas, creeme que aprendemos
mucho.

Gracias nuevamente por tus enseñanzas.

Alan


Alan Salazar Romero

unread,
Aug 3, 2008, 1:12:49 AM8/3/08
to
Hola Enrique:

Probe el codigo que enviaste.

Hice dos correciones para que corriera:

> Private Sub TreeView1_NodeMouseClick( ... )
> .....
> Try
> .....


> Dim frm As Form = _
> DirectCast(asm.CreateInstance("TreeViewDemo." & _
> childNode.Text), Form)

Private Sub TreeView1_NodeMouseClick( ... )

.....
Try
.....


Dim frm As Form = _

SoftJaén

unread,
Aug 3, 2008, 1:42:34 AM8/3/08
to
"Alan Salazar Romero" escribió:

>
> segun el ejemplo por lo que pude ver trabaja con un arbol a dos niveles
> (padre-hijo), que tan complicado se pone si desearamos que tuviera "n"
> niveles y siguieramos utilizando tablas para construir el TreeView ?

Complicado sería a la hora de rellenar de elementos el control TreeView,
porque al seleccionar un elemento cualquiera, con independencia del orden
que tenga, siempre se desencadenará el evento «NodeMouseClick», y es aquí
donde tendrás que detectar si el nodo actual tiene un nodo padre,
consultando para ello la propiedad «Parent» del nodo donde se ha efectuado
el clic.

Si dicha propiedad devuelve el valor «Nothing», se entiende que el nodo no
tiene un nodo padre, por lo que se tratará de un nodo superior. En caso
contrario, devolverá el objeto «TreeNode» correspondiente al nodo padre.

-- Padre
-- Hijo
-- Nieto
-- Bisnieto
-- Tataranieto

Como podrás observar, comenzando de abajo a arriba, cada elemento tiene su
nodo padre, que serán los nodos Bisnieto, Nieto, Hijo y Padre
respectivamente, y éste último será el único que no tendrá un elemento
padre, por lo que su propiedad «Parent» devolverá el valor Nothing.

Y en cuanto a rellenar de elementos el control TreeView, si estos los tomas
desde tablas de una base de datos, se aplica la misma técnica que expliqué
anteriormente: la tabla Padre está relacionada con la tabla Hijo, y ésta a
su vez, está relacionada con la tabla Nieto, y ésta con la tabla Bisnieto, y
por último, ésta última con la tabla Tataranieto. En definitiva, tendrás que
crear tantas relaciones como elementos del control desees relacionar, que
para el ejemplo expuesto serían cuatro relaciones.

AlanCSR

unread,
Aug 19, 2008, 11:04:15 AM8/19/08
to
Encontre este articulo, aca se puede crear un treeview con "n" nodos:

////////////////////////////////////////////////////////////////////////////////
Llenar un TreeView desde un DataSet en VB .NET
Utilizar la jerarquía definida en los datos de una tabla para llenar un
TreeView con un método recurrente sencillo (en VB. NET).

Fecha: 25/Jul/2005 (24/07/2005)
Autor: Serge Valsse (sva...@hotmail.com)

Atendiendo a la solicitud de muchos programadores que necesitaban el código
en VB del ejemplo del artículo: Llenar un TreeView desde un DataSet usando
un método recurrente que está escríto en C# y que fue publicado en este
mismo sitio en la siguiente dirección:
http://www.elguille.info/colabora/NET2005/svalsse_llenar_un_treeview.htm,
publico este mismo ejemplo pero como ya dije en VB .NET.

Si no has leído el artículo anterior, te recomiendo que lo hagas para que
veas el planteamiento del problema a resolver, ya que aquí expondré la
solución en VB directamente para no repetir las partes comunes del artículo
anterior.

Bien, la idea es llenar un TreeView con los datos contenidos en una tabla.
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.
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 Basic, Aplicación para
Windows y llámelo EjemploTreeView.

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

3. Declara un DataSet que pueda ser visto por toda la clase Form1 (para ello
hay que hacer la declaración en la sección "Declarations" del Form1).
Private dataSetArbol As System.Data.DataSet

4. En la ventana de Código agrega el método que se ejecutará recurrentemente
llamándolo CrearNodosDelPadre.
Private Sub CrearNodosDelPadre(ByVal indicePadre As Integer, ByVal nodePadre
As TreeNode)

Dim dataViewHijos As DataView

' Crear un DataView con los Nodos que dependen del Nodo padre pasado
como parámetro.
dataViewHijos = New DataView(dataSetArbol.Tables("TablaArbol"))

dataViewHijos.RowFilter =
dataSetArbol.Tables("TablaArbol").Columns("IdentificadorPadre").ColumnName +
" = " + indicePadre.ToString()

' Agregar al TreeView los nodos Hijos que se han obtenido en el
DataView.
For Each dataRowCurrent As DataRowView In dataViewHijos

Dim nuevoNodo As 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 Is Nothing Then
TreeView1.Nodes.Add(nuevoNodo)
Else
' se añade el nuevo nodo al nodo padre.
nodePadre.Nodes.Add(nuevoNodo)
End If

' Llamada recurrente al mismo método para agregar los Hijos del Nodo
recién agregado.
CrearNodosDelPadre(Int32.Parse(dataRowCurrent("IdentificadorNodo").ToString()),
nuevoNodo)
Next dataRowCurrent

End Sub

5. Para simplificar el ejemplo, adiciona los siguientes métodos que
simularán los datos obtenidos desde una base de datos.
Private Sub CrearDataSet()
Dim tablaArbol As DataTable

dataSetArbol = New DataSet("DataSetArbol")

tablaArbol = dataSetArbol.Tables.Add("TablaArbol")
tablaArbol.Columns.Add("NombreNodo", GetType(String))
tablaArbol.Columns.Add("IdentificadorNodo", GetType(Integer))
tablaArbol.Columns.Add("IdentificadorPadre", GetType(Integer))

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)

InsertarDataRow("Nodo 1.1.1.1", 12, 3)
InsertarDataRow("Nodo 1.1.1.1.1", 13, 12)
InsertarDataRow("Nodo 1.1.1.1.2", 14, 12)
InsertarDataRow("Nodo 1.1.1.1.3", 15, 12)
End Sub

Private Sub InsertarDataRow(ByVal column1 As String, ByVal column2 As
Integer, ByVal column3 As Integer)
Dim nuevaFila As DataRow

nuevaFila = dataSetArbol.Tables("TablaArbol").NewRow()

nuevaFila("NombreNodo") = column1
nuevaFila("IdentificadorNodo") = column2
nuevaFila("IdentificadorPadre") = column3
dataSetArbol.Tables("TablaArbol").Rows.Add(nuevaFila)
End Sub

6. En el evento Load de la clase Form1() ingrese la llamada al método que
llenará el DataSet. El código quedará como sigue:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
CrearDataSet()
End Sub

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 Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click

' Llamar al método por primera vez que llenará el TreeView, este método
se llamará luego
' a sí mismo recurrentemente.
CrearNodosDelPadre(0, Nothing)

End Sub
8. Compila y ejecuta el proyecto.

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, eso te lo agradecería mucho.

Serge Valsse
sva...@hotmail.com
________________________________________
Espacios de nombres usados en el código de este artículo:
System.Data


0 new messages