Visual Basic.NET - Llenar TreeView mas rapido

   
Vista:

Llenar TreeView mas rapido

Publicado por Miguel Angel (1 intervención) el 11/06/2008 19:03:22
Hola que tal, espero me puedan echar una mano.

Estoy programando en VB .net 2005, y mi problema es que, a la hora de llenar un TreeView tarda demasiado. Intento llenar un arbol con más de 14mil nodos, los cuales tardan aproximadamente en repartirse en todo el arbol entre 10 y 15 minutos. Lo que hago es llenar un DataSet con la información que necesita mi función para llenar el TreeView. La función que agrega los nodos al arbol, es recursiva.

Mi BD está en MySQL, no tengo problemas a la hora de conexión ni nada parecido, es más, mi DataSet lo llena en menos de 1seg., el problema como les comento, es a la hora de llenar el TreeView.

Les dejo mi codigo:

Declaro mi DataSet

Private dataSetArbol As System.Data.DataSet

Aqui tengo mi evento Load, donde llamo a la funcion que me crea el DataSet, terminando, llamo a la función que me crea los nodos en el TreeView:

Private Sub frmDesplegaCta_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
CrearDataSet()
' 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

Esta es mi funcion que crea el DataSet, tengo mi consulta hecha y ahi llamo a la funcion que me llena el DataSet.

Private Sub CrearDataSet()
Dim tablaArbol As DataTable
Dim orden_ant As Integer = 0
Dim strQuery As String

dataSetArbol = New DataSet("DataSetArbol")

strQuery = "select concat(`ecuenta`.`cuenta`,' - ',`ecuenta`.`nombre`) AS `NombreNodo`, `ecuenta`.`cuenta` AS `Cuenta`, " & _
"if(`ecuenta`.`nivel`=1,'0',`ectasoc`.`ctasup`) AS `CuentaSuperior` " & _
"from `ecuenta` left join `ectasoc` on(`ecuenta`.`cuenta` = `ectasoc`.`subcta`) order by `cuenta`"
If Not LlenaDataSet(strQuery, dataSetArbol) Then
MessageBox.Show("Error al conectar a BD", ":S", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If

End Sub

Esta funcion llena el DataSet con la query que envío de parametro, así como el DataSet

Public Function LlenaDataSet(ByVal sQuery As String, ByRef Ds As DataSet) As Boolean
Dim Adaptador As New MySqlDataAdapter(sQuery, Conexion.cn)
Ds.Tables.Clear()
Adaptador.Fill(Ds, "TablaArbol")
If Ds.Tables("TablaArbol").Rows.Count > 0 Then
Return True
Else
Return False
End If
End Function

Esta es la funcion recursiva, que llena el TreeView

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("CuentaSuperior").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("Cuenta").ToString()), nuevoNodo)
Next dataRowCurrent

End Sub

Gran parte del código que les presento, lo saque de la página de El Guille, donde tiene un ejemplo de cómo llenar un TreeView, si alguien tiene una mejor forma de llenar un TreeView, adelante, me interesa mucho que esto se haga más rápido.

Gracias :)
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Llenar TreeView mas rapido

Publicado por jAVIER (1 intervención) el 12/09/2008 20:59:39
Miguel,

He utilizado tu codigo para rellenar un TreeView desde una tabla de Access, pero no consigo que me funcione.

No me da ningun error pero el contro se queda en blanco.

El codigo se sale del bucle en la primera pasada

El codigo que he puesto es el siguiente:

'Declarando DataAdapter, DataSet, Parametro a utilizar
Private oDA As OleDbDataAdapter
Private oDS As DataSet

conexion = New OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & My.Settings.CadenaDeConexion)

Dim SQLZONAS As String

SQLZONAS = "SELECT ZONAS.ID_Zona, ZONAS.ZONA, ZONAS.Nodo, ZONAS.NodoPadre FROM ZONAS ORDER BY ZONAS.Nodo, ZONAS.NodoPadre;"

oDA = New OleDbDataAdapter(SQLZONAS, conexion) 'SqlDataAdapter '("", oCNT)
oDS = New DataSet
oDA.Fill(oDS, "ZONAS")

If oDS.Tables("ZONAS").Rows.Count > 0 Then
GoTo Continua
Else
MsgBox("La consulta esta vacia", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End If

Continua:

'Llamar al Método Recurrente por primera vez que llenará el TreeView()
CrearNodosDelPadre("0", Nothing)

'Destruyendo(Objetos)
oP1 = Nothing
oDA = Nothing
oDS = Nothing

'Cerrando la Coneccion
conexion.Close()

End Sub

Private Sub CrearNodosDelPadre(ByVal indicePadre As Integer, ByVal nodePadre As TreeNode)
'Esta es la funcion recursiva, que llena el TreeView

Dim dataViewHijos As DataView


dataViewHijos = New DataView(oDS.Tables("ZONAS"))

dataViewHijos.RowFilter = oDS.Tables("ZONAS").Columns("NODO").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("ZONA").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
TreeView_Edificios.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("NodoPadre").ToString()), nuevoNodo)
Next dataRowCurrent

End Sub

La tabla de la que cojo los datos es la siguiente:

Campo "NODO" tipo Integer
Campo "NodoPadre" tipo integer
Campo "ZONA" tipo text 8 (Es el nombre del nodo a mostrar en el TreeView)

Los datos de prueba que tengo, son:

NODO NodoPadre ZONA

1 0 Nodo1
2 1 Nodo11
3 1 Nodo12
4 2 Nodo111
5 0 Nodo2

La version que utilizo es Visual Studio 2005

Si puedes ayudarme, te lo agradeceria, estoy totalmente atancado con este asunto. No tengo ni idea de por que no entre en el bucle.

Muchas gracias
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Llenar TreeView mas rapido

Publicado por jonathan (1 intervención) el 17/12/2008 23:14:57
lo q yo te recomendaria es q uses una vista, y desde ahi, ejecutes una funcion

esta es la q yo hice, le pasas el treeview y el nombre de la vista

Private Function LlenarTreeveiw(ByVal TvwObjeto As System.Windows.Forms.TreeView, ByVal Vista As String)
TvwObjeto.Nodes.Clear()
Dim Padre As TreeNode
Dim sPadre As String = ""
Dim iSql As String = "Select * from " & Vista & " order by 1"
Dim cmd As New SqlCommand(iSql, ocnxSql)
ocnxSql.Open()
Dim dr As SqlDataReader = cmd.ExecuteReader
With TvwObjeto
If dr.HasRows Then
Do While dr.Read
If sPadre <> dr.GetString(0) Then
sPadre = dr.GetString(0)
Padre = .Nodes.Add("", sPadre)
Padre.Nodes.Add(dr.GetString(1))
Else
Padre.Nodes.Add(dr.GetString(1))
End If
Loop
End If
ocnxSql.Close()
End With
Return TvwObjeto
End Function


ojala te funcione.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar