Hola a todos. Después de probar con variso treeviews (supuestamente gratuitos) y el Microsoft.Web.UI.WebControls (que no he conseguido que funcione), me he creado uno un poco precario pero que cumple lo que quería.
Os dejo el código del control ASCX por si a alguien le sirve.
Arbol.ascx.vb
Código:
Public Class Arbol
Inherits System.Web.UI.UserControl
#Region " Código generado por el Diseñador de Web Forms "
'El Diseñador de Web Forms requiere esta llamada.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
End Sub
Protected WithEvents pnlArbol As System.Web.UI.WebControls.Panel
'NOTA: el Diseñador de Web Forms necesita la siguiente declaración del marcador de posición.
'No se debe eliminar o mover.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: el Diseñador de Web Forms requiere esta llamada de método
'No la modifique con el editor de código.
InitializeComponent()
End Sub
#End Region
Public dtGeneral As DataTable
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not Page.IsPostBack Then
dtGeneral = OrigenDatos.EjecutaPA("PA_JerarquiaCompleta", 1).Tables(0)
End If
Recursiva(0)
End Sub
Private Sub Recursiva(ByVal id As Integer)
Dim dr() As DataRow
Dim raiz As Boolean = False
If id = 0 Then
dr = dtGeneral.Select("IDPadre IS NULL", "Nombre")
raiz = True
Else
dr = dtGeneral.Select("IDPadre = " & id, "Nombre")
End If
If dr.Length > 0 Then
For Each r As DataRow In dr
Dim litAbre As New Literal
litAbre.Text = vbNewLine & "<div style='DISPLAY: " & IIf(raiz, "", "none") & ";POSITION: relative; LEFT: 20px;' id='Padre" & r("IDPadre") & "'>"
Me.pnlArbol.Controls.Add(litAbre)
If Not raiz Then
Dim img As New WebControls.Image
img.ImageUrl = "~/Imagenes/subGrupo.gif"
Me.pnlArbol.Controls.Add(img)
End If
If dtGeneral.Select("IDPadre = " & r("ID")).Length > 0 Then
Dim imgNodo As New WebControls.Image
imgNodo.ImageUrl = Request.ApplicationPath & "/Imagenes/plusNodo.gif"
imgNodo.ID = "imgNodo" & r("ID")
imgNodo.ImageAlign = ImageAlign.AbsMiddle
imgNodo.Attributes.Add("onclick", "muestra('imgNodo" & r("ID") & "','Padre" & r("ID") & "')")
imgNodo.Style.Add("cursor", "hand")
imgNodo.ToolTip = "Expandir/ampliar grupo"
Me.pnlArbol.Controls.Add(imgNodo)
End If
Dim hl As New HyperLink
hl.NavigateUrl = "~/Flora/?id=" & r("ID")
hl.ToolTip = "Ver la descripción de " & QuitaEspacios(r("Nombre"))
hl.Text = QuitaEspacios(r("Nombre"))
hl.CssClass = "cientifico"
Me.pnlArbol.Controls.Add(hl)
If r("Sinonimos") <> "" Then
Dim lblSin As New Label
lblSin.Text = " [" & QuitaEspacios(r("Sinonimos")) & "]"
lblSin.CssClass = "mini"
Me.pnlArbol.Controls.Add(lblSin)
End If
If r("Vulgares") <> "" Then
Dim lblVulga As New Label
lblVulga.Text = " " & QuitaEspacios(r("Vulgares"))
Me.pnlArbol.Controls.Add(lblVulga)
End If
Recursiva(r("ID"))
Dim litCierra As New Literal
litCierra.Text = "</div>"
Me.pnlArbol.Controls.Add(litCierra)
Next
End If
End Sub
End Class
Código HTML:
<%@ Control Language="vb" AutoEventWireup="false" Codebehind="Arbol.ascx.vb" Inherits="Clasificaciones.Arbol" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
<script language="javascript">
function muestra(imgNodo,nombrePadre)
{
if(document.getElementById('arbol_'+imgNodo))
{
var objImgNodo = document.getElementById('arbol_'+imgNodo);
objImgNodo.src = (objImgNodo.src.indexOf('plusNodo.gif',0) != -1)? '<% = Request.ApplicationPath %>/Imagenes/minusNodo.gif' : '<% = Request.ApplicationPath %>/Imagenes/plusNodo.gif';
}
if(document.getElementsByName(nombrePadre).length > 0)
{
var objCapas = document.getElementsByName(nombrePadre);
for(var i = 0 ; i < objCapas.length ; ++i)
{
var obj = objCapas[i].style;
obj.display = (obj.display)? '':'none';
}
}
}
</script>
<TABLE id="Table1" cellSpacing="1" cellPadding="1" width="90%" border="0" align="center">
<TR>
<TD vAlign="top" noWrap width="10%">Clasificaciones:</TD>
<TD vAlign="top">
<asp:Panel id="pnlArbol" runat="server" Width="75%"></asp:Panel></TD>
</TR>
</TABLE>
El procedimiento almacenado que utilizo es muy simple. Las columnas Sinonimos y Vulgares se pueden eliminar de la consulta, teniendo la tabla sólo tres columnas: ID (autonumérico), Nombre y IDPadre.
Código:
ALTER PROCEDURE PA_JerarquiaCompleta
(@Root int)
AS
BEGIN
SELECT
dbo.clasificaciones.ID,
dbo.clasificaciones.IDPadre,
dbo.clasificaciones.Nombre,
dbo.FN_BuscaSinonimos(1,dbo.clasificaciones.ID) AS "Sinonimos",
dbo.FN_BuscaVulgares(1,dbo.clasificaciones.ID) AS "Vulgares"
FROM dbo.clasificaciones
WHERE
dbo.clasificaciones.SinonimoDe IS NULL
OR
dbo.clasificaciones.SinonimoDe = ''
ORDER BY dbo.clasificaciones.Nombre
END
Siento no poner comentarios en el código, per estoy un poco apurado de tiempo. No obstante, espero que se entienda bien.
Un saludo.