Tips para el TreeView
Estoy empezando a trabajar con una vieja aplicación hecha en Visual Basic 6, para convertirla en Visual Basic .Net y uno de los primeros problemas con los que me he topado es con el uso del control TreeView, que difiere un poco con el viejo VB6, en cuanto a su llenado y en cuanto a encontrar un nodo dentro del "arbol" con el sólo dato de su clave de acceso.
Voy a dejar aquí dos ejemplos, el primero de como llenar un TreeView a partir de un objeto DataTable, que contiene la lectura de una tabla de mi base de datos. Y el segundo ejemplo es como encontrar un nodo conociendo su clave (ahora NAME).
Para el primer ejemplo, suponemos que tienes una conexión establecida a una base de datos, que puede ser mySQL, y que en ella tenemos una tabla que contiene todas las opciones de menú y con ella llenaremos el TreeView. De esta tabla menuKey es el "nombre del menú" (su clave), menuDescription es el texo que aparecerá a la vista del usuario del TreeView, y menuKeyParent es el "nombre del menú" del cual "cuelga" el menú descripto en esta fila.
Para esta tarea, también, me valgo del objeto DataView que permite filtrar los datos del DataTable. Además, observese que la función InsertTVMenuItems es llamada recursivamente. Sobre esto sólo hay que tener en cuenta la cantidad de llamadas recursivas que se van a hacer sin haber retornado (return) de ellas, puesto que en cada llamada el programa creará nuevas variables locales, independientes de las ya creadas, con el consecuente consumo de memoria. Obviamente, cada retorno provoca la liberación de recursos.
'rellena el tree view Private Sub RellenaTreeView1() Dim Itm As New TreeNode() Dim adapter As New MySqlDataAdapter() Dim data As New DataTable() Dim Sql As String System.Windows.Forms.Cursor.Current = Cursors.WaitCursor TreeView1.Nodes.Clear() TreeView1.Refresh() Sql = "SELECT menuKey," Sql = Sql & "menuDescription," Sql = Sql & "menuKeyParent" Sql = Sql & " FROM Menu" Sql = Sql & " ORDER BY menuDescription" adapter.SelectCommand = New MySqlCommand(Sql, dbConn) adapter.Fill(data) If data.Rows.Count = 0 Then data.Dispose() adapter.Dispose() System.Windows.Forms.Cursor.Current = Cursors.Default Exit Sub End If 'comienzo con "0" que es el menuKeyParent que cuelga del root del treeview InsertTVMenuItems("0", Nothing, data) 'libero recursos data.Dispose() adapter.Dispose() System.Windows.Forms.Cursor.Current = Cursors.Default End Sub Private Sub InsertTVMenuItems(ByVal keyParent As String, _ ByVal nodoPadre As TreeNode, _ ByVal data As DataTable) Dim dataFilter As DataView 'Crear un DataView con los Nodos que dependen del Nodo padre pasado como parámetro. dataFilter = New DataView(data) dataFilter.RowFilter = String.Format("menuKeyParent ='{0}'", keyParent.ToString()) 'Agregar al TreeView los nodos Hijos que se han obtenido en el DataView. For Each dataRowCurrent As DataRowView In dataFilter Dim nuevoNodo As New TreeNode With nuevoNodo .Text = dataRowCurrent("menuDescription").ToString().Trim() .Name = dataRowCurrent("menuKey").ToString().Trim() End With '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 nodoPadre Is Nothing Then TreeView1.Nodes.Add(nuevoNodo) Else 'se añade el nuevo nodo al nodo padre. nodoPadre.Nodes.Add(nuevoNodo) End If 'Llamada recurrente al mismo método para agregar los Hijos del Nodo recién agregado. InsertTVMenuItems(dataRowCurrent("menuKey").ToString(), nuevoNodo, data) Next dataRowCurrent End Sub
Sencillo, ¿no?
Bueno, ahora que tenemos nuestro TreeView llenito de datos, se nos viene en ganas de encontrar uno cuya clave (Name) sea X. Para ello definimos una variable privada a nivel de formulario donde almacenaremos el nodo encontrado durante la búsqueda.
Public Class myForm Private myNode As TreeNode
Luego escribimos el procedimiento que hará la búsqueda, que también opera recursivamente
'busca un nodo en el treeview Private Sub SearchNodeRecursive(ByVal nodes As TreeNodeCollection, ByVal key As String) For Each n As TreeNode In nodes If n.Name.Trim() = key.Trim() Then myNode = n Exit Sub End If SearchNodeRecursive(n.Nodes, key) Next End Sub
Y por último hacemos la llamada al procedimiento SearchNodeRecursive
Private Sub myProc() myNode = Nothing SearchNodeRecursive(TreeView1.Nodes, "clave_a_buscar") If IsNothing(myNode) Then MsgBox("No encontrado") Else MsgBox(myNode.Text.Trim()) End If End Sub
De nuevo... tengan en cuenta la cantidad de llamadas recursivas, sobre todo si el programa se instalará en PC's con escasa memoria.
3 Comentarios:
Muy bueno su articulo, ahora necesito saber como puedo llenar el datatable desde una base de datos de una tabla de solo dos columnas por ej, con campo_hijo y campo_padre. Como seria la FUNCION que llenaria el datatable para poder enviar ese datatable al trevieew?
Urge.
Muchas Gracias de antemano.
Jorge
No se si llego a entender tu pregunta, pero en el ejemplo se usan tres campos pues yo agrego la descripción al treeview, pero si obvias la descripción, el ejemplo usa dos campos: un hijo y un padre.
La descripción puede ser lo que tu necesites, esté o no en la tabla. Lo común es que la descripción acompañe a los códigos.
Salu2
Excelente, muy excelente las funciones.
ahora bien para poder seleccionar multiples nodos padres e hijos tendras alguna función ???
mi correo es julioponce@hotmail.com
saludos y gracias de antemano,
Mandar un comentario