Crear Controles Dinamicos ASP .Net a partir de una base de datos
Dentro del codigo HTML de una página aspx llamada SmartControls por ejemplo, tengo una estructura X, pero lo importante es que ubiques dentro del codigo siguiente la asp:TableCell llamada “TDCentral” que se va a convertir en nuestro contenedor master de nuestros controles dinamicos:
<asp:TableCell runat=”server” ColumnSpan=”2″>
<asp:Table CssClass=”tabla” ID=”TBCentral” runat=”server”>
<asp:TableRow runat=”server”>
<asp:TableCell runat=”server”>Working… please wait…
</asp:TableCell>
</asp:TableRow>
<asp:TableRow>
<asp:TableCell runat=”server”mso-bidi-font-weight:normal”>TDCentral” VerticalAlign=”Top” HorizontalAlign=”Left”>
</asp:TableCell>
</asp:TableRow>
</asp:Table>
</asp:TableCell>
Ok, luego en el codigo VB:
OJO esto debe ir dentro del SUB LOAD de la pagina:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
‘Aquí tengo una clase llamada LION que es la que hace muchas cosas entre ellas la conexion con la base de datos y dentro de esta clase implemento una función llamada DATARECOVERY que es la que me entrega una syste.data.Datatable como resultado de un query que solicito se ejecute. Mira:
Lion.DataRecovery(“select * from ws_smartpages_controls where menucode = ‘ ” & Request.QueryString(“cdi”).ToString.Trim & ” ‘ order by ControlOrder”, TBDetails)
‘En la sentencia anterior puedes fijarte que con mi clase LION ejecuto un sql que me trae el resultado en la tabla “TBDetails”, y es que en esta tabla ws_smartpages_controls tengo almacenados los controles que voy a usar en esta página.
‘Para darte una idea más clara del asunto te debo indicar que :
‘ Request.QueryString(“cdi”).ToString.Trim es el parámetro que me pasa la pagina menú al hacer clic en uno de sus submenús de tal manera que la consulta en la base me devuelve todo lo que tiene la tabla ws_smartpages_controls pero que el menucode sea igual a este request
‘Así entonces, tu puedes crear una tabla con una estructura en la que estén los parámetros más relevantes para crear los controles automáticos o dinámicos.
‘Ahora, creare un asp:Table para que contenga a los controles que vamos creando y que a su vez luego la incluiré en la TDCentral, recuerdan.., la TableCEll que les pedí que identificaran en el código HTML.
Dim TBContainer as new Table
‘Luego crearé un bucle FOReach “que significa por cada”, para leer una a una las ROWS de la tabla TBDetails
Foreach R as system.data.datarow in TBDetails.Rows ‘Es decir, por cada DataRow que tenga la DataTable TBDetails
‘Ahora, usando la característica polimórfica de una variable tipo Objeto, cambiaré o transmutaré éste al objeto que necesito,
‘Sin embargo, se debe recordar que luego de mutado el Objeto, no se podrá cambiar su tipo sin perder su estructura y contenidos en general, y esto hay que tenerlo muy presente al manejar el nuevo Objeto.
Dim Ctrl As Object
‘En el siguiente SELECT CASE pregunto el contenido de la ROW R en su columna CONTROLTYPE, que en realidad es un campo que contiene las tres primeras letras del tipo de control que deseo implementar.
Select Case R(“ControlType”).ToString.ToUpper.Trim.Substring(0, 3)
Case “LBL”
Ctrl = New Label ‘ Transmuto el Objeto CTRL a un asp:Label
Case “TXT”
Ctrl = New TextBox ‘ Transmuto el Objeto CTRL a un asp:Textbox
Case “LON”
Ctrl = New TextBox ‘ Transmuto el Objeto CTRL a un asp:Textbox
‘Ctype se usa para identificar un objeto con un tipo. Aquí indico que el textbox admitirá múltiples líneas:
CType(Ctrl, TextBox).TextMode = TextBoxMode.MultiLine
Case “PWD”
Ctrl = New TextBox
CType(Ctrl, TextBox).TextMode = TextBoxMode.Password ‘Aquí indico que el textbox será de tipo password por así decirlo
Case “CMB”
Ctrl = New DropDownList ‘ Transmuto el Objeto CTRL a un asp: DropDownList
‘ Para este control usare un campo de la tabla que he llamado QueryControl en el que almaceno una consulta SQL que poblara o llenara el control DropDownList, bueno y de hecho utilizo este campo para llenar también un RadioButomList o un CheckBoxList o el contenido por defecto de un label o un textbox, pero eso se los indicare más adelante. Por el momento recordemos que un DropDownList o un RadioButonList implementan dos valores, el primero es el VALUE que va escondido o detrás del segundo o TEXT que muestra cada listItem, es decir, estos controles se llenan con listItems, y cada listItem tiene un VALUE y un TEXT. Siendo así, el query o consulta sql que contiene este campo de la tabla debe traer dos valores, por ejemplo:
‘Select CodigoArticulo, DescripcionArticulo from articulos
‘Así, siempre tomare el primer campo para el Value del DropDownList y el segundo para mostrar al usuario, asi:
If R(“QueryControl”).ToString.ToLower.Trim <> “” And R(“QueryControl”).ToString.ToLower.Trim.Length > 0 Then ‘Pregunto si el campo no está vacio
Dim TBAux as new system.data.datatable
Lion.DataRecovery(R(“QueryControl”).ToString.ToLower.Trim, TBAux)
‘ para efectos del ejemplo esto sería como si ejecutara:
Lion.DataRecovery(“select CodigoArticulo, DescripcionArticulo from articulos”, TBAux)
‘Como te indique antes esta clase me retorna una tabla llena, en este caso con dos columnas
‘Indico que el nombre de la columna cero, llenara el value del control:
CType(Ctrl, DropDownList).DataValueField = TBAux.Columns(0).ColumnName
‘Indico que el nombre de la columna uno, llenara el text del control:
CType(Ctrl, DropDownList).DataTextField = TBAux.Columns(1).ColumnName
‘Acá indico que el datasource de mi control se llenara con el contenido de la TBAux resultante del sql:
CType(Ctrl, DropDownList).DataSource = TBAux
End If
Case “OPT”
Ctrl = New RadioButtonList ‘ Transmuto el Objeto CTRL a un asp: RadioButtonList
‘Para este control usare un campo de la tabla que he llamado QueryControl en el que almaceno una consulta SQL que poblara o llenara el control RadioButtonList, bueno y de hecho utilizo este campo para llenar también un RadioButomList o un CheckBoxList o el contenido por defecto de un label o un textbox, pero eso se los indicare más adelante. Por el momento recordemos que un DropDownList o un RadioButonList implementan dos valores, el primero es el VALUE que va escondido o detrás del segundo o TEXT que muestra cada listItem, es decir, estos controles se llenan con listItems, y cada listItem tiene un VALUE y un TEXT. Siendo así, el query o consulta sql que contiene este campo de la tabla debe traer dos valores, por ejemplo:
‘Select CodigoArticulo, DescripcionArticulo from articulos
‘Así, siempre tomare el primer campo para el Value del RadioButtonList y el segundo para mostrar al usuario, así:
If R(“QueryControl”).ToString.ToLower.Trim <> “” And R(“QueryControl”).ToString.ToLower.Trim.Length > 0 Then ‘Pregunto si el campo no está vacio
Dim TBAux as new system.data.datatable
Lion.DataRecovery(R(“QueryControl”).ToString.ToLower.Trim, TBAux)
‘para efectos del ejemplo esto sería como si ejecutara:
Lion.DataRecovery(“select CodigoArticulo, DescripcionArticulo from articulos”, TBAux)
‘Ahora, como te indique antes esta clase me retorna una datatable llena, en este caso con dos columnas:
‘Indico que el nombre de la columna cero, llenara el value del control:
CType(Ctrl, RadioButtonList).DataValueField = TBAux.Columns(0).ColumnName
‘Indico que el nombre de la columna uno, llenara el text del control:
CType(Ctrl, RadioButtonList).DataTextField = TBAux.Columns(1).ColumnName
‘Aca indico que el datasource de mi control se llenara con el contenido de la TBAux resultante del sql:
CType(Ctrl, RadioButtonList).DataSource = TBAux
End If
Case “CHK”
Ctrl = New CheckBoxList
Case “FIL”
Ctrl = New FileUpload
Case “CAL”
‘Aquí implementare un control para fechas usando Ajax, específicamente el AjaxControlToolkit.CalendarExtender, pero creare un textbox que a la final será el control que contendrá la fecha, luego al AjaxCalendar le indicaremos que se vincule a este textbox y listo.
Ctrl = New TextBox ‘ Transmuto el Objeto CTRL a un asp: DropDownList
‘Luego creare el control calendar de Ajax
Dim Cal As New AjaxControlToolkit.CalendarExtender()
Cal.FirstDayOfWeek = WebControls.FirstDayOfWeek.Sunday
Cal.Format = “dd/MM/yyyy”
Dim CalMask As New AjaxControlToolkit.MaskedEditExtender ‘ Este para indicarle que mascara contendrá nuestro control de fechas
CalMask.Mask = “99/99/9999″
CalMask.MessageValidatorTip = True
CalMask.OnFocusCssClass = “MaskedEditFocus”
CalMask.OnInvalidCssClass = “MaskedEditError”
CalMask.MaskType = AjaxControlToolkit.MaskedEditType.Date
CalMask.ClearMaskOnLostFocus = True
CalMask.InputDirection = AjaxControlToolkit.MaskedEditInputDirection.LeftToRight
CalMask.ErrorTooltipEnabled = True
‘Aquí vinculo el resultado del uso del calendar al textbox, claro, poniendo el nombre del textbox:
Cal.TargetControlID = R(“IDControl”).ToString.ToLower.Trim
‘Aquí vinculo la máscara del calendar al textbox:
CalMask.TargetControlID = R(“IDControl”).ToString.ToLower.Trim
Case “NEW”
‘Este es un control de usuario propio para mostrar noticias, si están interesados en este control posteen y con gusto les indicare su implementación
Ctrl = New Control
Ctrl = LoadControl(“News.ascx”)
Case “LGI”
‘Este es un control de usuario propio para solicitar login, si están interesados en este control posteen y con gusto les indicare su implementación
Ctrl = New Control
Ctrl = LoadControl(“Login.ascx”)
End Select
‘Asigno un nombre único al control que asimismo lo tengo almacenado en la tabla:
Ctrl.Id = R(“IDControl”).ToString.ToLower.Trim
‘Exijo que se construya el control con sus datos y características:
Ctrl.DataBind()
‘Ahora incluiremos el control dentro de nuestra asp:Table que creamos antes de entrar en este bucle y que la llamamos TBContainer, entonces:
‘como una asp:Table debe contener un TR o TableRow, y cada TR o TableRow debe contener uno o varios TD o TableCells entonces primero crearemos las TDs o TableCell para en ellas incluir nuestros controles, recuerden también que no se puede incluir un control dentro de un TR directamente asi que por ello:
Dim TR as new TableRow
‘Ahora crearemos dos TDs o TableCells que las pondremos dentro de nuestra TR
‘Crearemos dos TDs para que la primera contenga una referencia para el usuario al respecto de lo que deberá introducir sobre este control y la segunda TD que contendrá nuestro control, este control, así:
Dim TD1 as new TableCell
‘Ponemos la descripción que queremos aparezca junto a nuestro control:
TD1.text = R(“DescripcionControl”).ToString.ToLower.Trim
Dim TD2 as new TableCell
‘Adicionamos el control al TD2
TD2.controls.add(Ctrl)
TR.Cells.Add(TD1) ‘ Adicionamos el TD1 al TR
TR.Cells.Add(TD2) ‘ Adicionamos el TD1 al TR
TBContainer.Rows.Add(TR) ‘ Adicionamos el TR a la asp:Table TBContainer
‘Recuerden que estamos dentro de un bucle por lo tanto esto ocurrirá cuantas filas tenga nuestra TBDetails que a su vez serian los controles que deseamos
‘Así se irán creando cada control y este se irá metiendo dentro de un nuevo TD y estos TDs metiendo dentro de un nuevo TR y este a su vez dentro de la asp:Table
Next ‘ Fin del Bucle
‘Y finalmente adicionaremos nuestra TBContainer “asp:Table” dentro de nuestra TDCentral
Me.TDCEntral.controls.Add(TBContainer)
‘Exigimos que se contruya la asp:Table y Listo colegas.
TBContainer.Databind()
A continuación el código sin mis comentarios:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Lion.DataRecovery(“select * from ws_smartpages_controls where menucode = ‘ ” & Request.QueryString(“cdi”).ToString.Trim & ” ‘ order by ControlOrder”, TBDetails)
Dim TBContainer as new Table
Foreach R as system.data.datarow in TBDetails.Rows
Dim Ctrl As Object
Select Case R(“ControlType”).ToString.ToUpper.Trim.Substring(0, 3)
Case “LBL”
Ctrl = New Label ‘ Transmuto el Objeto CTRL a un asp:Label
Case “TXT”
Ctrl = New TextBox ‘ Transmuto el Objeto CTRL a un asp:Textbox
Case “LON”
Ctrl = New TextBox ‘ Transmuto el Objeto CTRL a un asp:Textbox
CType(Ctrl, TextBox).TextMode = TextBoxMode.MultiLine
Case “PWD”
Ctrl = New TextBox
CType(Ctrl, TextBox).TextMode = TextBoxMode.Password
Case “CMB”
Ctrl = New DropDownList
If R(“QueryControl”).ToString.ToLower.Trim <> “” And R(“QueryControl”).ToString.ToLower.Trim.Length > 0 Then
Dim TBAux as new system.data.datatable
Lion.DataRecovery(R(“QueryControl”).ToString.ToLower.Trim, TBAux)
CType(Ctrl, DropDownList).DataValueField = TBAux.Columns(0).ColumnName
CType(Ctrl, DropDownList).DataTextField = TBAux.Columns(1).ColumnName
CType(Ctrl, DropDownList).DataSource = TBAux
End If
Case “OPT”
Ctrl = New RadioButtonList
If R(“QueryControl”).ToString.ToLower.Trim <> “” And R(“QueryControl”).ToString.ToLower.Trim.Length > 0 Then
Dim TBAux as new system.data.datatable
Lion.DataRecovery(R(“QueryControl”).ToString.ToLower.Trim, TBAux)
CType(Ctrl, RadioButtonList).DataValueField = TBAux.Columns(0).ColumnName
CType(Ctrl, RadioButtonList).DataTextField = TBAux.Columns(1).ColumnName
CType(Ctrl, RadioButtonList).DataSource = TBAux
End If
Case “CHK”
Ctrl = New CheckBoxList
Case “FIL”
Ctrl = New FileUpload
Case “CAL”
Ctrl = New TextBox
Dim Cal As New AjaxControlToolkit.CalendarExtender()
Cal.FirstDayOfWeek = WebControls.FirstDayOfWeek.Sunday
Cal.Format = “dd/MM/yyyy”
Dim CalMask As New AjaxControlToolkit.MaskedEditExtender
CalMask.Mask = “99/99/9999″
CalMask.MessageValidatorTip = True
CalMask.OnFocusCssClass = “MaskedEditFocus”
CalMask.OnInvalidCssClass = “MaskedEditError”
CalMask.MaskType = AjaxControlToolkit.MaskedEditType.Date
CalMask.ClearMaskOnLostFocus = True
CalMask.InputDirection = AjaxControlToolkit.MaskedEditInputDirection.LeftToRight
CalMask.ErrorTooltipEnabled = True
Cal.TargetControlID = R(“IDControl”).ToString.ToLower.Trim
CalMask.TargetControlID = R(“IDControl”).ToString.ToLower.Trim
Case “NEW”
Ctrl = New Control
Ctrl = LoadControl(“News.ascx”)
Case “LGI”
Ctrl = New Control
Ctrl = LoadControl(“Login.ascx”)
End Select
Ctrl.Id = R(“IDControl”).ToString.ToLower.Trim
Ctrl.DataBind()
Dim TR as new TableRow
Dim TD1 as new TableCell
TD1.text = R(“DescripcionControl”).ToString.ToLower.Trim
Dim TD2 as new TableCell
TD2.controls.add(Ctrl)
TR.Cells.Add(TD1)
TR.Cells.Add(TD2)
TBContainer.Rows.Add(TR)
Next
Me.TDCEntral.controls.Add(TBContainer)
TBContainer.Databind()
El siguiente paso de este blog es hacer que estos controles dinámicos afecten una base de datos, o sea que inserten, actualicen o eliminen datos de una o más tablas,
Así podríamos hacer una página dinámica completa que administre una tabla de clientes, creamos los controles dinámicamente y estos guardan, modifican, o eliminan sus contenidos dentro de la tabla de clientes.
Como ven, esto nos da muchas posibilidades, por ejemplo, en la DataTable de la Base pueden adicionar mas campos que nos servirán de atributos de los controls, por ejemplo pueden crear campos que contengan el ancho y alto de los controles, o el número máximo de caracteres que un control puede aceptar y luego lo ligan al maxlength de los textbox, etc.. pueden también indicar qué clase de estilo tendrá cada control, etc, etc… las posibilidades son muchas, y luego pueden crear paginas completamente dinámicas, incluso esta página de creación de controles, podría dinámicamente administrarse a sí misma.
Tengo muchísimo más código que iré publicando en base a su acogida. Por ejemplo, para crear menús dinámicos, o buscadores de datos dinámicos y que sirven para buscar cualquier dato dentro de cualquier tabla o conjunto de tablas, así podríamos incluir este buscador como un control de usuario y adjuntarlo a nuestra página dinámica, imagínense, las posibilidades son muchas y de esta manera podrías crear paginas completamente dinámicas y desde tu mismo sitio Web sin tener que volver a publicar el sitio por cada cambio que te pidan tus jefes o clientes.
De mis sitios web tengo varios que están publicados en la red, los demás corren dentro de las intranet para las instituciones que he trabajado y que a su vez son completamente dinámicos, todo todo lo que ven esta dentro de una base de datos, y todo se construye dinámicamente, por ejemplo los menús superiores, los menús internos, las páginas de mantenimiento de tablas, las búsquedas, etc…
Si gustan pueden visitar:
http://www.uninetbusiness.com
http://www.coopalja.com.ec
http://www.totemdevelopers.com
http://www.facoindustrias.com
http://argudomorillo.martem.org
Si desean mas información, dudas, comentarios o sugerencias por favor posteen. Y si alguien desea colaborar, muy amables, no me caería nada mal y muchas gracias. Pueden usar paypal a la cuenta: fabricioleon@gmail.com
Gracias… totales
Un abrazo y
Good luck!!!