10 septiembre 2008

Creación de controles dinámicos en ASP.NET

Una de las cosas que siempre quise realizar en .NET fué la creación de controles dinámicos en tiempo de ejecución pero como nunca me había visto en la necesidad de crearlos no lo había hecho... hasta hoy :) que requerí generar controles dinámicos de acuerdo a las necesidades de los usuarios de cierta aplicación.


Para el siguiente ejemplo voy a explicar cómo crear cuántos textboxs y dropdownlist sean necesarios en tiempo de ejecución. Lo primero que se necesita realizar es la declaración de los arreglos de los controles requeridos de la siguiente manera:


static TextBox[] arregloTextBoxs;
static DropDownList[] arregloCombos;
static int contadorControles;


Luego defino la creación de los controles dinámicos en el evento del botón que creará dichos controles


protected void btnAgregar_Click(object sender, EventArgs e)
{
try
{
int numeroRegistro = contadorControles;
TextBox nuevoTxt = new TextBox();
nuevoTxt.ID = "txt" + numeroRegistro.ToString();
nuevoTxt.Width = 400;
arregloTextBoxs[numeroRegistro] = nuevoTxt;
DropDownList nuevoCmb = new DropDownList();
nuevoCmb.ID = "cmb" + numeroRegistro.ToString();
nuevoCmb.Items.Add("---Seleccione el Plazo---");
nuevoCmb.Items.Add("Corto Plazo");
nuevoCmb.Items.Add("Mediano Plazo");
nuevoCmb.Items.Add("Largo Plazo");
nuevoCmb.SelectedIndex = 0;
arregloCombos[numeroRegistro] = nuevoCmb;
AgregarControles(nuevoTxt, nuevoCmb);
contadorControles++;
}
catch (Exception ex)
{
lblContador.Text = ex.Message;
}
}


El método que agrega los controles dinámicos en un control Panel para que el usuario los pueda utilizar


protected void AgregarControles(TextBox txt, DropDownList cmb)
{
try
{
pnlMain.Controls.Add(txt);
pnlMain.Controls.Add(new LiteralControl(" "));
pnlMain.Controls.Add(cmb);
pnlMain.Controls.Add(new LiteralControl("
"));
}
catch (Exception ex)
{
lblContador.Text = ex.Message;
}
}


OJO: pnlMain es un control de tipo Panel en el cual voy agregando los controles dinámicos.


Finalmente, en el evento Page_Load de la página se debe "redibujar" los controles cada vez que se recargue la página:


protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
lblContador.Text = "";
arregloTextBoxs = new TextBox[20];
arregloCombos = new DropDownList[20];
contadorControles = 0;
}

try
{
for (int i = 0; i < contadorControles; i++)
AgregarControles(arregloTextBoxs[i], arregloCombos[i]);
}
catch (Exception ex)
{
lblContador.Text = ex.Message
}
}

Eso es todo!!!! espero que a alguien le sea útil como lo fue para mi el día de hoy :)


Saludos!!!

PD: asi queda la página...


33 comentarios:

Anónimo dijo...

Q tal sabes q tu codigo no funciona (o falta explicación)! espero lo mejores!!

Viktor dijo...

Si funciona, de hecho lo tengo implementado en un sistema en este momento. Si no funcionara, no lo habría publicado...

Creo que debes de leer mejor el post e implementarlo en tu desarrollo.

Anónimo dijo...

Yo pienso que es un buen trabajo y que bien que lo hayas publicado.

Saludos.

Viktor dijo...

Gracias por tus comentarios :)

Siempre la idea de haber creado este blog es compartir esos peuqeños tips que en algun momento nos pueden ser muy útiles.


Saludos

Anónimo dijo...

Bueno les platico como lo resolvi yo. les dejo mi correo para preguntas luisalberto456@yahoo.com.mx

Dim i_Params As Integer
Dim piña As Integer
Private arrayTextBox As Array
Private TxtBox As TextBox
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
EnsureChildControls()
If Not Page.IsPostBack Then
i_Params = 0
End If
If Session("iCtrls") <> "0" Then
arrayTextBox = Session("arrayTextBox")
For i As Integer = 0 To CInt(Session("iCtrls")) - 1
TxtBox = arrayTextBox(i)
TxtBox.ID = "Param" & i
Panel.Controls.Add(TxtBox)
TxtBox = Nothing
Next
End If
End Sub
Protected Sub bAdd_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles bAdd.Click
arrayTextBox = Array.CreateInstance(GetType(TextBox), 3)
For i As Integer = 0 To 3 - 1
i_Params = i_Params + 1
Session("iCtrls") = i_Params
TxtBox = New TextBox
TxtBox.ID = "Param" & i
arrayTextBox(i) = TxtBox
Panel.Controls.Add(TxtBox)
TxtBox = Nothing
Next
End Sub
Protected Sub bWrite_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles bWrite.Click
Response.Write("Probando :
")
For i As Integer = 0 To CInt(Session("iCtrls")) - 1
TxtBox = Me.FindControl("Param" & i)
arrayTextBox(i) = TxtBox
Response.Write("Probando : " & TxtBox.Text & "
")
TxtBox = Nothing
Next
End Sub
Protected Sub Page_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Unload
If Session("iCtrls") <> "0" Then
If Not Session("arrayTextBox") Is Nothing Then Session.Remove("arrayTextBox")
Session.Add("arrayTextBox", arrayTextBox)
End If
End Sub

Anónimo dijo...

Saludos, el hecho de definir los objetos de tipo static me genera conflictos al cambiar de un navegador a otro. Ejemplo si en ie cree 5 controles TextBox, despues voy a mozilla y cargo la pagina me trae esos 5 textBox que cree en ie.
Se te ocurre de que manera puedo dar solucion a esto.

Anónimo dijo...

Interesante, el codigo no lo he probado, sin embargo tiene unos cuantos detalles muy buenos q me ahn ayudado a solucionar un problema...MUCHAS GRACIAS POR COMPARTIR EL CONOCIMIENTO!

Anónimo dijo...

que tal se me hace interesante tu articulo, hoy en dia yo me encuentro en la situscion de generar controles dinamicos, pero edittemplate de un gridview. podrias asesorarme por donde comenzar

Jaime Altamirano B. dijo...

J' ai essayé ton script, mais la première fois, Ça n'est pas allé
J'ai le solutionné , mais je ne sait pas qu' est ce que que j'ai fait.
Reponds Mois..........

If you are an idol, you can understand me.......

Anónimo dijo...

Que groceria de codigo, donde administra los controles?, como los lee?... donde los busca... es algo vano e inserbible es como para una estudiante de programacion que necesite hacer un tablero de Sudoku o algo así....

Anónimo dijo...

Me uno al comentario anterior, no puedes administrar los controles, que caso tiene generarlos si no los puedes usar?

Anónimo dijo...

hola a todos: en en evento click creé la cantidad de textbox que el usuario especifica en el txtcantentregas de la siguiente manera

Protected Sub linkDetalleEntregas_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles linkDetalleEntregas.Click
dim I As Integer

If txtCantEntregas.Text = "" Or Val(txtCantEntregas.Text) < 1 Or Val(txtCantEntregas.Text) > 12 Or Not IsNumeric(txtCantEntregas.Text) Then
lblErrorCantEntregas.Visible = True
Exit Sub
End If
For I = 1 To Val(txtCantEntregas.Text)
txtCant = New TextBox()
txtFec = New TextBox()
txtCant.Text = "cantidad " & I
txtFec.Text = "fecha " & I
panelTxtCant.Controls.Add(txtCant)
PanelTxtFec.Controls.Add(txtFec)
txtCant.Height = 18
txtCant.Width = 50
txtCant.ID = I
txtCant.AutoPostBack = True
txtCant.CssClass = "campo"
txtFec.Height = 18
txtFec.Width = 100
txtFec.ID = I
txtFec.CssClass = "Campo"

Next I
panelTxtCant.Visible = True
PanelTxtFec.Visible = True
Page.MaintainScrollPositionOnPostBack = True
End Sub

los crea perfectamente bien. Pero en el evento click de otro botón debo validar esos datos.
El problema que tengo es que en ese evento click no me permite acceder a lo que los usuario escriben. No los reconoce. Y además al hacer click en cualquier otro botón de la página desaparecen todos los textbox creads dinámicamente.
Alguien podría orientarme en esto.
Gracias

RamiGlez dijo...

Hola Victor...
He leído tu post, como muchos tantos tratando de encontrar solución a mi problema... y nada.
Estoy tratando de hacer lo que haces en este post, añadir controles de forma dinámica, y establecer el delegado del evento de forma dinámica también... hasta aquí todo genial... tal y como lo haces tu... ahora viene el problema, necesito que en el handler de uno de estos controles me cree otros nuevos controles dinámicos, y poder establacer sus delegados de eventos... y aquí se complica la cosa, puesto que en eventhandler se ejecuta despues del Page_load, y se pierden los delegados, aunque los botones nuevos si se crean...
Si has tenido este problema antes agradezco cualquier ayuda, si no ya tienes una interrogante mas... creo que l a solución sea capturar los argumentos del evento antes del page_load... con el Request.Form, o .Params pero no estoy seguro....
saludos y suerte.

Anónimo dijo...

Online Casino Games tyuueooru
Free Casino Games
There are several things to be considered when selecting the best gambling website.
[url=http://www.nhgaa.org/]No Download Casino[/url]
So, it is vital to be able to find a right online casino website for you if you don't want your online gambling experience to be annoying and regretting.
http://www.nhgaa.org/ - Casinos Online
There are several things to be considered when selecting the best gambling website.

ReinventarMe dijo...

Hola
No acostumbro los Post
Pero esto me ha sido tan util y funcional que no podia dejar de agradecer


Gran aporte!

Anónimo dijo...

aver aver y si requieres esto dentro de un grid view....osea que cada q agregas una fila se agregue un control???..

Ramon dijo...

Es mejor usar un ListView, puedes crear la plantilla que quieras para cada fila, y definirla a tu manera... El ListView ofrece mucha mas versatilidad a la hora de controlar como se muestra la informacion... Saludos.

Clos132 dijo...

pues yo trate de pasarlo a VB ya que es en donde estoy haciendo mi proyect, pero me sale un error en el load, justamente en donde se agrega el valor 20 al textbox y al dropdownlist, me dice "Demasiados argumentos para 'Public Sub New()'."

no se si puedas ayudarme estaria muy agradecido, saludos.

Clos132 dijo...

pues yo trate de pasarlo a VB ya que es en donde estoy haciendo mi proyect, pero me sale un error en el load, justamente en donde se agrega el valor 20 al textbox y al dropdownlist, me dice "Demasiados argumentos para 'Public Sub New()'."

no se si puedas ayudarme estaria muy agradecido, saludos.

Clos132 dijo...

saludos, bueno pase este codigo a VB, y me sale un error en el load justamente cuando se da el valor de 20, q me dice "Demasiados argumentos para 'Public Sub New()'."
estaria agradecido si me ayudaran en esto, saludos.

Francisco dijo...

Hola, Buen Día.. solo para agradecerte el post del código, me fue de gran utilidad, gracias!...

Unknown dijo...

me salvaste la vida. con tu codigo incluí controles de usarios dinamicos y puse un botón para recorrerlos y funcionó perfectamente muchas gracias

Unknown dijo...

me salvaste la vida. con tu codigo incluí controles de usarios dinamicos y puse un botón para recorrerlos y funcionó perfectamente muchas gracias

Anónimo dijo...

EXCELENTE VIKTOR Y GRACIAS POR LA INFORMACIÓN

Unknown dijo...

excelente codigo...... gracias... disculpa una pregunta? y como se podria recuperar los datos de esos controles?

Shuwer David L dijo...

HOLA, TU EJEMPLO ESTÁ BASTANTE BIEN. PERO yo tengo el problema de que la primera vez que le doy click a un combo generado dinámicamente NO lanza el evento, y tengo que darle click dos veces. Para mi no es opción pintar nuevamente la página porque es ENORME.. tienes alguna solución para esto? shuwer@gmail.com

Unknown dijo...

Hola Victor, he visto tu video y es muy interesante, una pregunta puntual, puedo aplicar lo mismo leyendo desde una base de datos, es decir crear los controles dependiendo de lo que tenga en una tabla

Anónimo dijo...

Gracias, me sirvió mucho =)

Catefralo dijo...

Hola, buen ejemplo el código funciona en la primera ejecución, MUCHAS GRACIAS!!!

Roger Rivas dijo...

Hola buen día el codigo funciona a la perfeccion pero tengo una pregunta puedes crear los DropDownList y textbox pero si necesitas tomar esa información como le llamas por que como t¿no tiene un runat="server" y no sabes el nombre del otro lado como obtienes la informcacion ingresada de antemano gracias

MarianoNct dijo...

Excelente articulo Viktor. No hagas caso a los que critican.
Saludos

llama dijo...

Que buena publicación,como guardas la información de cada uno de los componentes.

llama dijo...

Que buena publicación,como guardas la información de cada uno de los componentes.