Un ejemplo practico
con el cual haras uso de tablas y algoritmos recursivos para recuperar tu
información. Esto es aplicable a foros aunque tambien puedes usarlo para
información que requiera vinculación padre-hijo en tablas de bd, además de la
creacion y uso de controles en tiempo de ejecución.
La idea general
parte de una tabla recursiva de la siguiente forma:
taMensajesForo(
CodigoTemaForo
char(3)
CodigoMensajeForo char(3)
tituloMensajeForo char(50)
descripcionMensajeForo char(1000)
CodigoMensajeForoPadre char(15)
usuariocrea char(20)
)
Tenemos esta tabla donde registramos los mensajes para un tema especifico (para
estos casos el idMensajePadre quedaria vacio o nulo).. luego en algun momento
respondemos a un determinado mensaje entonces el campo idMensajePadre
almacenará el codigo del mensaje al cual respondemos.
La información se almacena sin mayor dificultad el problema es cuando queremos
recuperar la información,
Ok aqui vamos.. lo
primero es generar dos procedimientos almacenados uno para recuperar los
mensajes que no tengan hijos y el otro para obtener mensajes hijos de un
mensaje padre
1er
procedimiento:
CREATE PROCEDURE
spObtenerMensajesTema
(
@CodigoTemaForo CHAR(15)
)
AS
SELECT
CodigoTemaForo,
CodigoMensajeForo,
CodigoMensajeForoPadre,
TituloMensajeForo,
DescripcionMensajeForo,
usuariocrea
FROM
taMensajesForo
WHERE
CodigoTemaForo = @CodigoTemaForo and
CodigomensajeForoPadre = '000000000000000' // Usamos
este codigo para decir que no tiene hijos
2do procedimiento
CREATE PROCEDURE
spObtenerMensajesHijo
(
@CodigoMensajeForoPadre CHAR(15)
)
AS
SELECT
CodigoTemaForo,
CodigoMensajeForo,
CodigoMensajeForoPadre,
TituloMensajeForo,
DescripcionMensajeForo,
usuariocrea
FROM
saelse.taMensajeForo
WHERE
CodigomensajeForoPadre = @CodigoMensajeForoPadre//
obtenemos todos los mensajes de un mensaje padre
OK ,... hasta aqui
hemos generados los 2 procedimientos almacenados que luego invocaremos desde
.net. Ahora nos toca generar nuestro webform para obtener la data
Web form mensaje.aspx
Creamos el form
mensajel archivo .aspx y su codebehind .aspx.vb
En el archivo aspx Agregamos 1 datagrid que hara enlace con la data
<asp:datagrid
id="dgMensajesTema" runat="server" Width="100%"
OnItemCommand="panel_click" AutoGenerateColumns="False"
GridLines="Horizontal">
<Columns>
... aqui agregaremos las columnas
</Columns>
</asp:datagrid>
A este datagrid lo
llamamos dgMensajesTema le dimos el evento panel_click en el evento
OnItemCommand y ahora le vamos a agregar las columnas
<asp:BoundColumn
DataField="CodigoMensajeForoPadre"
Visible="false"></asp:BoundColumn>
<asp:BoundColumn DataField="CodigoTemaForo"
Visible="false"></asp:BoundColumn>
<asp:BoundColumn DataField="CodigoMensajeForo"
Visible="false"></asp:BoundColumn>
Tres campos enlazados pero que no los mostraremos, esto nos servira para hacer
las consultas a la BD, debes tener en cuenta que codigomensajeforopadre esta en
la columna 0, codigotemaforo en la columna 1 y asi sucesivamente... luego
agregamos la columna donde mostraremos los mensajes sin padre (un template column)
y un panel donde agregaremos sus hijos
<asp:TemplateColumn
HeaderText="Mensaje">
<ItemTemplate>// insertamos una tabla solo para
q la info salga ordenada
<table width="100%" border="0" cellSpacing="0"
cellPadding="0" borderColor="gainsboro">
<tr>
<td colspan="2" height="20px" >
<asp:ImageButton id="Imagebutton2" commandname="panel"
runat="server"
ImageUrl="../imagenes/plus.gif"></asp:ImageButton>
Mensaje creado por <%#
DataBinder.Eval(Container.DataItem,"usuarioCrea") %> :
<asp:HyperLink id="hlMensajes" runat="server" tooltip=
'<%# DataBinder.Eval(Container.DataItem,"DescripcionMensajeForo")
%>' NavigateUrl='enlace a un webform detalle' text = '<%#
DataBinder.Eval(Container.DataItem,"TituloMensajeForo") %>' >
</asp:HyperLink>
</td>
<td bgcolor="#e6eefb" height="20px"
class="normal" align="right">
<asp:Label id="Label5" runat="server"
CssClass="normal">
<%# DataBinder.Eval(Container.DataItem,"FechaCreacion") %>
</asp:Label>
</td>
</tr>
</table>// fin de la tabla.
// aqui
insertamos el panel para mostrar y ocultar los mensajes hijo
<asp:Panel id="Panel2" runat="server"
Width="100%" Visible="false">
<TABLE id="Table3" cellSpacing="0"
cellPadding="0" width="100%" border="0">
<TR vAlign="top">
<TD id="PanelIzquierdo" vAlign="top"
width="60%" bgColor="#f9f8f7" rowSpan="2"
runat="server"></TD>
</TR>
</TABLE>
</asp:Panel>
</ItemTemplate>
</asp:TemplateColumn>
Bueno doy la
aclaración de que en un primer momento "PanelIzquierdo" no va a
aparecer (es obvio verdad?) y tan solo se mostraran los mensajes padre tal como
muestra la figura:
Y solo haciendo click en la
cruz al lado de cada mensaje obtendremos todos los mensajes hijo
Ahora nos vamos al
codigo behind osea al mensaje.aspx.vb
En el PanelIzquierdo mostraremos la info de los hijos insertando dinamicamente
controls , para nuestro caso hyperlinks e imagenes entonces
Primero declaramos
nuestras variables
Dim codigoTemaForo As String Nuestros controles para insertarlos dinamicamente Dim WithEvents hlResponder As HyperLink Dim WithEvents hlnodo As HyperLink Dim WithEvents hlTituloAs HyperLink Dim iDinamico As System.Web.UI.WebControls.Image en el Load Private Sub Page_Load(......) CodigoTemaForo="001200500000002" 'Si la pagina es accesada por primera vez If Page.IsPostBack = false then 'La idea es cargar los mensajes que no tengan hijos, dgMensajesTema.DataSource = f_Obtenermensajetema(CodigoTemaForo) dgMensajesTema.DataBind() End If End Sub Luego vamos declarando todas las funciones definidas y las que nos serviran
Las dos funciones que devuelven datasets y llaman a los procedimientos almacenados que creamos Function f_Obtenermensajetema(ByVal paramCodigoTemaForo As String) As DataSet
' Crea instancia de conexion y el objeto Command
Dim cnxDBINTRANET As New SqlConnection(ConfigurationSettings.AppSettings("connectionString"))
Dim sqlObtenerMensajeTemaForo As New SqlDataAdapter("spObtenerMensajesTema", cnxDBINTRANET)
' Marcamos el Command como un SPROC
sqlObtenerMensajeTemaForo.SelectCommand.CommandType = CommandType.StoredProcedure
' Agregamos los parametros al procedimiento
Dim parametercodigoTema As New SqlParameter("@CodigoTemaForo", SqlDbType.Char, 15)
parametercodigoTema.Value = paramCodigoTemaForo
sqlObtenerMensajeTemaForo.SelectCommand.Parameters.Add(parametercodigoTema)
Dim dsObtenerMensajeTema As New DataSet
' Creamos y llenamos el DataSet
sqlObtenerMensajeTemaForo.Fill(dsObtenerMensajeTema)
Return dsObtenerMensajeTema
End Function Function f_ObtenermensajesHijo(ByVal paramcodigoMensajePadre As String) As DataSet
' Crea instancia de conexion y el objeto Command
Dim cnxDBINTRANET As New SqlConnection(ConfigurationSettings.AppSettings("connectionString"))
Dim sqlObtenerMensajeTemaForo As New SqlDataAdapter("spObtenerMensajesHijo", cnxDBINTRANET)
' Marcamos el Command como un SPROC
sqlObtenerMensajeTemaForo.SelectCommand.CommandType = CommandType.StoredProcedure
' Agregamos los parametros al procedimiento
Dim parametercodigoTema As New SqlParameter("@CodigoMensajePadre", SqlDbType.Char, 15)
parametercodigoTema.Value = paramcodigoMensajePadre
sqlObtenerMensajeTemaForo.SelectCommand.Parameters.Add(parametercodigoTema)
Dim dsObtenerMensajeTema As New DataSet
' Creamos y llenamos el DataSet
sqlObtenerMensajeTemaForo.Fill(dsObtenerMensajeTema)
Return dsObtenerMensajeTema
End Function
Luego el evento que se lanza al hacer clic sobre la cruz (Imagebutton2), es aqui donde llamamos al algoritmo recursivo Public Sub panel_click(ByVal sender As System.Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)
If e.CommandName = "panel" Then 'ocultamos o mostramos el panel de resultados
Dim temp1 As Panel = CType(e.Item.FindControl("Panel2"), Panel)
temp1.Visible = Not (temp1.Visible) 'recuerdan los campos ocultos? pues bien es aqui donde los usamos 'en esta caso al codigoMensajeForoPadre
obtenerhijos(e.Item.Cells(2).Text, 1, temp1)
Dim temp2 As ImageButton = CType(e.Item.FindControl("Imagebutton2"), ImageButton)
If temp1.Visible Then 'cambiamos el icono del imagebutton
temp2.ImageUrl = "../imagenes/minus.gif"
Else
temp2.ImageUrl = "../imagenes/plus.gif"
End If
End If
End Sub
Ahora definimos a
nuestro obtenerhijos. Este metodo hace uso de llamadas recursivas como veremos
Sub obtenerhijos(ByVal codigomensaje As String, ByVal nivel As Integer, ByVal panel As Panel)
Dim dr_ As DataSet = f_ObtenerMensajesHijo(codigomensaje)
Dim dr As DataRow
For Each dr In dr_.Tables(0).Rows Dim mensajePadre As String
Dim TituloPadre As String
Dim DescripcionPadre As String
Dim usuarioPadre As String
Dim fechaPadre As String
Dim nroarchivos As Integer mensajePadre = CType(dr("CodigomensajeForo"), String)
TituloPadre = CType(dr("TituloMensajeForo"), String)
DescripcionPadre = CType(dr("DescripcionMensajeForo"), String)
usuarioPadre = CType(dr("usuarioCrea"), String)
fechaPadre = CType(dr("Fechacreacion"), DateTime).ToShortDateString() 'ubicamos al panel donde insertaremos los mensajes hijo Dim parent As Control = panel.FindControl("PanelIzquierdo") hlResponder = New HyperLink
hlTitulo = New HyperLink
hlnodo = New HyperLink With hlTitulo
.CssClass = "normal"
.Visible = True
.Text = "Creado por " + usuarioPadre + " : " + TituloPadre + ". Fecha: " + fechaPadre
.NavigateUrl = Request.ApplicationPath + " pagina de detalle de mensaje.."
End With
With hlResponder
.ImageUrl = "../imagenes/1x1.gif"
.Width = New System.Web.UI.WebControls.Unit(10)
.Height = New System.Web.UI.WebControls.Unit(30)
End With
With hlnodo
.ImageUrl = "../imagenes/node.gif"
End With
'aqui insertamos imagenes en blanco para dar la apariencia de arbol a nuestros mensajes obtenerEspacio(nivel, panel) 'aqui agregamos los controles parent.Controls.Add(hlnodo)
parent.Controls.Add(hlTitulo)
parent.Controls.Add(hlResponder) parent.Controls.Add(New LiteralControl("<" & "br" & ">"))
'aqui la llamada recursiva If mensajePadre <> "" Then
obtenerhijos(mensajePadre, nivel + 1, panel)
End If Next dr
End Sub Aqui el módulo para los espacios en blanco esto para dar la apariencia de arbol Sub obtenerEspacio(ByVal entero As Integer, ByVal panel As Panel)
While entero > 0
iDinamico = New System.Web.UI.WebControls.Image
With iDinamico
.Visible = True
.ImageUrl = "../imagenes/1x1.gif"
.Width = New System.Web.UI.WebControls.Unit(30)
End With
Dim parent As Control = panel.FindControl("Panelizquierdo")
parent.Controls.Add(iDinamico)
entero = entero - 1
End While
End Sub
Y listo!! eso es
todo, ya arriba hay una imagen con las muestra del ejemplo ejecutandose
Aclaraciones .
Tenemos una tabla
con SQL Server 2000 llamada taMensajes con las características que mencione
anteriormente. La conexión a la BD es almacenada en el
web.config asi:
<appSettings>
<add key="ConnectionString"
value="server=localhost;database=dbPrueba;uid=sa;pwd=sa;" />
</appSettings>
Dim cnxDBINTRANET as
New SqlConnection(ConfigurationSettings.AppSettings("connectionString"))
Dim
Reeemplazariamos el valor de
ConfigurationSettings.AppSettings("connectionString") por
"server=localhost;data......" y eso es todo.
Vi un ejemplo con algoritmos recursivos pero lo hacia la BD.. eso tambien sirve
aunque cuando el numero de llamadas crece el gestor puede colapsar.
|