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:

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

    ResponderBorrar
  2. 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.

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

    Saludos.

    ResponderBorrar
  4. 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

    ResponderBorrar
  5. 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

    ResponderBorrar
  6. 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.

    ResponderBorrar
  7. 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!

    ResponderBorrar
  8. 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

    ResponderBorrar
  9. 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.......

    ResponderBorrar
  10. 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í....

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

    ResponderBorrar
  12. 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

    ResponderBorrar
  13. 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.

    ResponderBorrar
  14. 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.

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


    Gran aporte!

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

    ResponderBorrar
  17. 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.

    ResponderBorrar
  18. 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.

    ResponderBorrar
  19. 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.

    ResponderBorrar
  20. 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.

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

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

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

    ResponderBorrar
  24. EXCELENTE VIKTOR Y GRACIAS POR LA INFORMACIÓN

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

    ResponderBorrar
  26. 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

    ResponderBorrar
  27. 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

    ResponderBorrar
  28. Gracias, me sirvió mucho =)

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

    ResponderBorrar
  30. 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

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

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

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

    ResponderBorrar