que tal?
Bueno paso a comentarles mi inquietud. No tuve problemas al usar un control TreeView en vb6, pero cuando migre a .NET se me dificulto la cosa. No puedo agregar lo que yo quiero como yo quiero.
Pongo un code de ejemplo:
treeview.Nodes.Add("Raiz")
treeview.Nodes(0).Nodes.Add("Primero")
treeview.Nodes(0).Nodes.Add("Segundo")
treeview.Nodes(0).Nodes.Add("Tercero")
con ese code creo una raiz y colgando de esa raiz los items Primero, Segundo y Tercero.
Ahora... yo quiero colgar items del item "Primero" y eso es lo que no puedo hacer
Saludos.
CitarTreeView1.Nodes.Add("Raiz 1")
TreeView1.Nodes(0).Nodes.Add("Primero R1")
TreeView1.Nodes(0).Nodes.Add("Segundo R1")
TreeView1.Nodes(0).Nodes(0).Nodes.Add("Sub Primero 1")
TreeView1.Nodes(0).Nodes(0).Nodes.Add("Sub Primero 2")
TreeView1.Nodes(0).Nodes(1).Nodes.Add("Sub segundo 1")
TreeView1.Nodes(0).Nodes(1).Nodes.Add("Sub segundo 2")
si, esta perfecto eso, ya me habia dado cuenta
muchas gracias :)
el problema mio ahora es el siguiente
es urgente, necesito hacer este arbol mañana :S
el arbol lo tengo q hacer en base a una tabla sql
con los sig campos "CODIGO(string)" "DESCRPCION(string)" "PADRE(string)"
el tema es que no puedo hacerlo :S encontre un code en google q parece andar pero no me anda tiene un problema
suponiendo que el arbol no tiene mas de 6 niveles
por favor si alguien sabe como hacer esto q me ayude
es bastante muy distinto a vb6 :S
un saludo grande a todso y gracais por la colaboracion
NO entiendo que quieres decir...quieres llenar los datos de una table en un treeview?. En el caso que asi sea, que dato es el que deseas mostrar ( CODIGO - DESCRIPCION - PADRE ). En el caso que quieras mostrar los datos de esa tabla el control solo tendria un nivel:
Citardim con as new sqlconnection(".....")
dim da as sqldataadapter
dim dtb as data.datatable
sub Form_Load(byval.........)
da= new sqldataadapter("select * from tabla",con)
dtb = new data.datatable
da.fill(dtb)
dim a as integer
for a=0 to dtb.rows.count-1
treeview1.nodes.add dtb.rows(a)("COLUMNA").tostring
end for
end sub
te explico a lo que me refiero, es que escribi apurado porque me estaba llendo.
una parte de la tabla supongamos es asi:
CODIGO DESCRIPCION PADRE
001 Item 1 (en blanco)
002 Item 2 001
003 Item 3 001
004 Item 4 001
005 Item 5 002
006 item 6 002
007 Item 7 005
008 Item 8 005
009 Item 9 005
010 Item 10 006
el arbol quedaria de la siguiente manera:
Item 1
|____Item 2
| |____Item 5
| | |___Item 7
| | |___Item 8
| | |___Item 9
| |
| |____Item 6
| |___Item 10
|
|____Item 3
|____Item 4
creo que quedo claro, el dato que se muestra es la descripcion.
hace un rato estaba pensando en agregar los controles de vb6 a vb.net y usar la funcion que hize hace un tiempo para el mismo fin. pero tambien quiero saber como hacerlo directamente desde los controles de vb.net.
muchas gracias por las respeustas.
Saludos.
Recursividad ¿?
Sabras que es eso, supongo.
exacto, si se que es la recursividad. la funcion que hize en vb6 era recursiva, pero como en .net hay variaciones en el codigo todadvia no pude hacer una funcion semejante, ni usando la anterior como "base", hace 3 dia utilizo .net.
es posible hacer un llenado recursivo? sin limitacion? como la que hize en vb6 ya que la unica q encontre tenia un limite, si querias mas niveles habria que agregar codigo y era cada vez mas por cada agregado, pero no funcionaba
es posible?con o sin limitacion.
Saludos nuevamente
En SQL
CitarCreate database Ejemplo
go
use ejemplo
go
create table rutina
(codigo char(3) primary key,
descripcion varchar(7),
padre char(3))
go
insert into rutina values ('001','Item 1','')
insert into rutina values ('002','Item 2','001')
insert into rutina values ('003','Item 3','001')
insert into rutina values ('004','Item 4','001')
insert into rutina values ('005','Item 5','002')
insert into rutina values ('006,'Item 6','002')
insert into rutina values ('007','Item 7','005')
insert into rutina values ('008','Item 8','005')
insert into rutina values ('009','Item 9','005')
insert into rutina values ('010','Item 10','006')
En .NET
Crea un nuevo proyecto, 1 formulario(Form1) y un control treeview(treeview1)
Citar
Imports System.Data.SqlClient
Public Class Form1
Dim con As New SqlConnection("integrated security=sspi;data source=(local);initial catalog=ejemplo")
Dim da As SqlDataAdapter
Dim dtb As DataTable
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
da = New SqlDataAdapter("select * from rutina", con)
dtb = New DataTable
da.Fill(dtb)
Dim a As Integer
For a = 0 To dtb.Rows.Count - 1
If dtb.Rows(a)("padre").ToString = " " Then
TreeView1.Nodes.Add(dtb.Rows(a)("descripcion").ToString)
añade(dtb.Rows(a)("codigo").ToString, TreeView1.Nodes(TreeView1.Nodes.Count - 1))
End If
Next
End Sub
'Añade, funcion recursiva
Sub añade(ByVal cod As String, ByVal node As TreeNode)
da = New SqlDataAdapter("select * from rutina", con)
dtb = New DataTable
da.Fill(dtb)
'variable que recorre las filas de la tabla
Dim a As Integer
For a = 0 To dtb.Rows.Count - 1
If dtb.Rows(a)("padre").ToString = cod Then
node.Nodes.Add(dtb.Rows(a)("descripcion").ToString)
añade(dtb.Rows(a)("codigo").ToString, node.Nodes(node.Nodes.Count - 1))
End If
Next
End Sub
End Class
Espero sea util, mas demore poniendole color .... :xD :xD :xD :xD :xD
Necesito explicar ¿? :rolleyes: :rolleyes: :rolleyes:
muchisimas gracias por tu tiempo
explico nuevamente mi situacion, cada vez mas oscura jaja
utilize tu code pero despues de algun que otro retoque(por ejemplo la forma en que me conecto.) es como que nunca llega a su fin la ejecucion, no se porque sera, no se si sera la funcion o porq estoy procesando 7 mil registros.
dejo el codigo "modificado" para mirar y analizar.
En un modulo:
Public ex As Exception 'variable que guardará una exepcion (error)
Public MyConexion As New OleDb.OleDbConnection() 'objeto de ADO.net para conectar con la BD
Public MiAdaptador As New OleDb.OleDbDataAdapter 'adaptador de datos
Public dsDataSet As New Data.DataSet() ' objeto que guardará los resultados de la consulta
Public strSQL As String 'para crear la consulta SQL
En el load del formulario(el formulario se llama frm_dimproducto)
Private Sub frm_dimproducto_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
strSQL = "SELECT * FROM DimTempCustomer"
MiAdaptador = New OleDb.OleDbDataAdapter(strSQL, MyConexion.ConnectionString)
MiAdaptador.Fill(dsDataSet, "MiTabla")
Dim a As Integer
Dim Codigo, Descripcion, Padre As String
For a = 0 To dsDataSet.Tables("MiTabla").Rows.Count - 1
Codigo = Trim(dsDataSet.Tables("MiTabla").Rows(a).Item("DimT_Codigo"))
Descripcion = Trim(dsDataSet.Tables("MiTabla").Rows(a).Item("DimT_Descripcion"))
Padre = Trim(dsDataSet.Tables("MiTabla").Rows(a).Item("DimT_Padre"))
If Padre = "" Then
TreeView1.Nodes.Add(Descripcion)
añade(Codigo, TreeView1.Nodes(TreeView1.Nodes.Count - 1))
End If
Application.DoEvents()
Next
End Sub
En el sub añade:
Sub añade(ByVal cod As String, ByVal node As TreeNode)
strSQL = "SELECT * FROM DimTempCustomer"
MiAdaptador = New OleDb.OleDbDataAdapter(strSQL, MyConexion.ConnectionString)
MiAdaptador.Fill(dsDataSet, "MiTabla2")
'variable que recorre las filas de la tabla
Dim a As Integer
Dim Codigo, Descripcion, Padre As String
For a = 0 To dsDataSet.Tables("MiTabla").Rows.Count - 1
Codigo = Trim(dsDataSet.Tables("MiTabla2").Rows(a).Item("DimT_Codigo"))
Descripcion = Trim(dsDataSet.Tables("MiTabla2").Rows(a).Item("DimT_Descripcion"))
Padre = Trim(dsDataSet.Tables("MiTabla2").Rows(a).Item("DimT_Padre"))
If Padre = cod Then
node.Nodes.Add(Descripcion)
añade(Codigo, node.Nodes(node.Nodes.Count - 1))
End If
Application.DoEvents()
Next
End Sub
yo quisiera creer que es por un tema del dataset, repito que mi experiencia con .net es de solo 1 semana.
tambien dejo el codigo de la funcion que realize en vb6 con el treeview perteneciente a los controles com, el cual no funciona por razones que desconozco, algun tipo de incopatibilidad.(directamente el treeview no funciona como deberia con .NET)
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
'On Error Resume Next
Dim Codigo, Descripcion As String
Dim TotalReg As Long
Dim Registro As DataRow
Dim Nombre, Hijos, Child
'Me.MousePointer = 11
tv.Nodes.Clear()
strSQL = "SELECT * FROM DimTempCustomer WHERE DimT_Padre=''"
MiAdaptador = New OleDb.OleDbDataAdapter(strSQL, MyConexion.ConnectionString)
MiAdaptador.Fill(dsDataSet, "Raiz")
Codigo = Trim(dsDataSet.Tables("Raiz").Rows(0).Item("DimT_Codigo"))
Descripcion = Trim(dsDataSet.Tables("Raiz").Rows(0).Item("DimT_Descripcion"))
tv.Nodes.Add(, , "Cabecera", "[" & Codigo & " ]" & "[" & Descripcion & "]")
'padres e hijos :)
strSQL = "SELECT * FROM DimTempCustomer WHERE DimT_Padre='" & Codigo & "'"
MiAdaptador = New OleDb.OleDbDataAdapter(strSQL, MyConexion.ConnectionString)
MiAdaptador.Fill(dsDataSet, "Primero")
TotalReg = 0
For Each Registro In dsDataSet.Tables("Primero").Rows
TotalReg = TotalReg + 1
Codigo = Trim(Registro.Item("DimT_Codigo"))
Descripcion = Trim(Registro.Item("DimT_Descripcion"))
Nombre = Codigo & "A"
Hijos = Hijos & "-//-" & Codigo
tv.Nodes.Add("Cabecera", Child, Nombre, "[" & Codigo & "]" & "[" & Descripcion & "]")
Application.DoEvents()
Next
'si no contiene hijos lo borro despues de la confirmacion
If TotalReg <> 0 Then
Verificar_hijos(Hijos)
End If
End Sub
Function Verificar_hijos(ByVal Hijos)
'On Error Resume Next
Dim i As Integer
Dim Codigo, Descripcion, Nombre, Child, Check_Hijo, Hijos2 As String
Dim Hijo
Dim TotalReg
Dim Registro As DataRow
'desgloso la variable Temp, y recorro en un bucle para ver si tienen hijos
Hijo = Split(Hijos, "-//-")
For i = 1 To UBound(Hijo)
Check_Hijo = Trim(Hijo(i))
strSQL = "SELECT * FROM DimTempCustomer WHERE DimT_Padre='" & Check_Hijo & "'"
MiAdaptador = New OleDb.OleDbDataAdapter(strSQL, MyConexion.ConnectionString)
MiAdaptador.Fill(dsDataSet, Check_Hijo)
TotalReg = 0
For Each Registro In dsDataSet.Tables("Primero").Rows
TotalReg = TotalReg + 1
Codigo = Trim(Registro.Item("DimT_Codigo"))
Descripcion = Trim(Registro.Item("DimT_Descripcion"))
Nombre = Codigo & "A"
tv.Nodes.Add(Check_Hijo + "A", Child, Nombre, "[" & Codigo & "]" & " " & Descripcion)
Hijos2 = Hijos2 & "--" & Codigo
Application.DoEvents()
Next
'si ese hijo tiene hijos
If Not TotalReg = 0 Then
Verificar_hijos(Check_Hijo)
End If
Next i
Timer1.Enabled = False
End Function
Disculpen lo extenso del post.
Saludos
Recomendaria que uses un Data.DataTable ya que el manejo de datos entre el Dataset y datatable no es exactamente igual. Hazlo, y si te funciona lo posteas, de esa forma te podria explicar como van algunas lineas del codigo.
EDITO: Ademas que el usar el table ahorrara algo de codigo... :rolleyes: :rolleyes: :rolleyes:
exelente, mañana probare usar un datatalbe en lugar de dataset y luego lo comento, si funciona posteo el code.
Saludos
bueno, al fin. pude cargar el treeview. con exactamente el code q postiastes.
lo unico que me surgio un gran gran problema
al cargar los 7000 registros el tiempo de espera es alto
tarda aproximadamente 12 minutos, entre que hace las consultas revisa y carga.
no hay forma de guardar el control junto con sus datos de tal forma que cuando el usuario quiera ver el arbol no lo tenga que volver a cargar, sino simplemente cargar el control con los datos previamente cargados.
muchas gracias nuevamente
Bueno no sabria decirte porque nunca he hecho algo parecido, pero podria sugerir que intentes un par de cosas.
Lo primero seria que ese formulario cuando no lo necesites no lo cierres, sino que lo ocultes, y cuando lo quieras usar nuevamente lo haces visible, con esto el treeview ya no tendria que llenarse cada vez que cargues el formulario.
Ocultar formulario
CitarForm.hide()
Mostrar formulario
CitarForm.show()
si, podria ser. pero el usuario no va a querer esperar 11 minutos desde un principio, y sin contar que los registros pueden aumentar un poco.
bueno, voy a tratar de buscar otra solucion. muchisimas gracias por tu ayuda hadess_inf
Bueno claro que la cantidad de tiempo que demore en llenarse el control sera bastante, bueno todo eso depende del equipo en el cual se este trabajando(me refiero al hardware), aun asi, buscare una alternativa y vere si se puede agilizar ese proceso, saludos. Si encuentras una respuesta a tu problema posteala.
Bueno hadess_inf, te cuento. Encontre la solucion al 100% de mi problema.
Hize lo siguiente:
En lugar de cargar todo el arbol al cargar el formulario, decidi solo cargar la raiz del arbol, osea, un solo item.
Luego si se quieren ver los que cuelgan del item se le hace doble click y se cargan los items del segundo nivel.
Si se queire ver lo que cuelga de alguno de esos items recien cargados, se le hace doble click. Y asi hasta llegar a donde quiera sin necesidad de cargar datos innesesarios que el usuario no va a mirar.
El tiempo es altamente importante en estas situaciones, el cual fue reducido a una respuesta casi instantanea en el peor de los casos.
El codigo esta muy interesante y es muy sencillo y la idea me la dio mi jefe cuando me dije: "Mostra lo que necesitas"
El lunes temprano posteo el codigo para que este disponible, ya que esta en el trabajo y no en mi casa.
Saludos y muchas gracias por tu colaboracion.
Es una buena salida.. :xD :xD :xD :xD
Lo prometido es deuda.
En el Load del formulario:
Dim Host As String = "tuservidor"
Dim con As New OleDb.OleDbConnection("Provider=SQLOLEDB; Data Source=" & Host & "; Initial Catalog=TuBase; integrated security=SSPI; persist security info=True;")
Dim da As OleDb.OleDbDataAdapter
Dim dtb As DataTable
Dim a As Integer
Dim Codigo As String
da = New OleDb.OleDbDataAdapter("select * from dimtempcustomer where dimt_padre=''", con)
dtb = New DataTable
da.Fill(dtb)
TreeView1.Nodes.Add(Trim("[" & dtb.Rows(a)("dimt_codigo").ToString) & "]-- " & Trim(dtb.Rows(0)("dimt_descripcion").ToString))
Codigo = Trim(dtb.Rows(0)("dimt_codigo").ToString)
En el evento DoubleClick del TreeView:
Dim Host As String = "tuservidor"
Dim con As New OleDb.OleDbConnection("Provider=SQLOLEDB; Data Source=" & Host & "; Initial Catalog=TuBase; integrated security=SSPI; persist security info=True;")
Dim da As OleDb.OleDbDataAdapter
Dim dtb As DataTable
Dim a, i As Integer
Static Cargados As String
Dim Codigo, Descripcion As String
Dim parte = Split(TreeView1.SelectedNode.Text, "]-- ")
Dim flag = Split(Cargados, "--")
Me.Cursor = Cursors.WaitCursor
Codigo = Trim(Mid(parte(0), 2))
For i = 1 To UBound(flag)
If Codigo = flag(i) Then
Me.Cursor = Cursors.Default
Exit Sub
End If
Next
Cargados += "--" & Codigo
da = New OleDb.OleDbDataAdapter("select * from dimtempcustomer where dimt_padre='" & Codigo & "'", con)
dtb = New DataTable
da.Fill(dtb)
For a = 0 To dtb.Rows.Count - 1
Codigo = Trim(dtb.Rows(a)("dimt_codigo").ToString)
Descripcion = Trim(dtb.Rows(a)("dimt_descripcion").ToString)
TreeView1.SelectedNode.Nodes.Add("[" & Codigo & "]-- " & Descripcion)
Next
TreeView1.SelectedNode.Expand()
Me.Cursor = Cursors.Default
Lo de la conexion se puede arreglar para que sea menos codigo.
Espero les sirva el codigo, le agradezco mucho a hadess_inf por responder mis preguntas.
Gracias.
Usa TreeView1.BeginUpdate() antes de comenzar a actualizar el treeview y TreeView1.EndUpdate() cuando acabes, de esta forma evitas que se redibuje el control mientras estás añadiendo nuevos elementos.
Un saludo
Gracias gusman, ya agregue lo que me sugueriste :)
Saludos