none
Error: La colección de controles no puede modificarse porque el control contiene bloques de código RRS feed

  • Pregunta

  • Hola a todos. Estoy probando algo y necesito escribir dentro del cuerpo HTML determinados controles en forma dinámica. Ahora para hacerla fácil, solo quiero poner un botón.

    Tengo mi página .aspx con el siguiente código:

    <%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    </head>
    <body>
        <form id="form1" runat="server">
    		<% escribir(2)  %>
        </form>
    </body>
    </html>
    

    y en el código, defino la SUB ESCRIBIR que es quien escribirá los controles en el HTML:

    Imports System.Web.UI.HtmlControls
    
    Partial Class _Default
        Inherits System.Web.UI.Page
    
        Public Sub escribir(n As Integer)
    
            Dim botoncito As New HtmlInputButton
            Dim idDelBotoncito As String = "botonis"
            botoncito.ID = idDelBotoncito
            botoncito.Value = "PressME"
    
            Dim panel1 As New PlaceHolder
            panel1.Controls.Add(botoncito)
            form1.Controls.Add(panel1)
    
            Dim manager As ClientScriptManager = Page.ClientScript
            Dim jsSCRIPT As String = ""
            jsSCRIPT = jsSCRIPT & "$( ""#" & idDelBotoncito & """ ).click(function() { alert('x') }) "
            manager.RegisterStartupScript(Me.GetType, "muestrabla", jsSCRIPT, True)
    
        End Sub
    
    End Class

    Pero al ejecutar recibo este error:

    Colección modificada; puede que no se ejecute la operación de enumeración.
    
    Descripción: Excepción no controlada al ejecutar la solicitud Web actual. Revise el seguimiento de la pila para obtener más información acerca del error y dónde se originó en el código. 
    
    Detalles de la excepción: System.InvalidOperationException: Colección modificada; puede que no se ejecute la operación de enumeración.
    
    Error de código fuente: 
    
    Se ha generado una excepción no controlada durante la ejecución de la solicitud Web actual. La información sobre el origen y la ubicación de la excepción pueden identificarse utilizando la excepción del seguimiento de la pila siguiente.
    
    Seguimiento de la pila: 
    
    [InvalidOperationException: Colección modificada; puede que no se ejecute la operación de enumeración.]
       System.Web.UI.ControlCollectionEnumerator.MoveNext() +9751373
       System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +137
       System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +13
       System.Web.UI.Page.Render(HtmlTextWriter writer) +29
       System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +66
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1303
    
    Información de versión: Versión de Microsoft .NET Framework:4.0.30319; Versión ASP.NET:4.6.1586.0

    

    Si quito la línea form1.Controls.Add(panel1) no hay error!

    Agradezco cualquier ayuda que me puedan dar!

    jueves, 18 de agosto de 2016 21:13

Respuestas

  • Es sabido que en .Net cuando ejecutas un bucle foreach que recorre una coleccion, no es licito que dentro de ese bucle se modifiquen los miembros de la coleccion. Si lo intentas te sale un error como el que estas viendo.

    Pues bien, este es un caso en el que internamente sucede precisamente eso: Cuando internamente se recorre el aspx para renderizarlo, y el Sistema esta iterando sobre su coleccion de controles (que seguramente debe usar por dentro un foreach), resulta que llamas a la rutina "escribir" que por dentro modifca esa misma coleccion de controles (debido al Controls.Add), y en consecuencia se produce el error.

    En conclusion: Si usas <% escribir(2)  %>, la rutina escribir no debe intentar generar controles de asp.net ni hacer un Add sobre Controls. Si quieres inserter controles en la pagina dinamicamente, no lo hagas con <%...>, usa el Page_Load o el Page_Init para incorporarlos a la coleccion Controls. En otras palabras: Llama a escribir(2) desde el Page_Load, no desde <%..> en el .aspx.

    • Propuesto como respuesta Sergio ParraModerator viernes, 19 de agosto de 2016 10:28
    • Marcado como respuesta Sergio_UY viernes, 19 de agosto de 2016 11:59
    viernes, 19 de agosto de 2016 8:06

Todas las respuestas

  • Es sabido que en .Net cuando ejecutas un bucle foreach que recorre una coleccion, no es licito que dentro de ese bucle se modifiquen los miembros de la coleccion. Si lo intentas te sale un error como el que estas viendo.

    Pues bien, este es un caso en el que internamente sucede precisamente eso: Cuando internamente se recorre el aspx para renderizarlo, y el Sistema esta iterando sobre su coleccion de controles (que seguramente debe usar por dentro un foreach), resulta que llamas a la rutina "escribir" que por dentro modifca esa misma coleccion de controles (debido al Controls.Add), y en consecuencia se produce el error.

    En conclusion: Si usas <% escribir(2)  %>, la rutina escribir no debe intentar generar controles de asp.net ni hacer un Add sobre Controls. Si quieres inserter controles en la pagina dinamicamente, no lo hagas con <%...>, usa el Page_Load o el Page_Init para incorporarlos a la coleccion Controls. En otras palabras: Llama a escribir(2) desde el Page_Load, no desde <%..> en el .aspx.

    • Propuesto como respuesta Sergio ParraModerator viernes, 19 de agosto de 2016 10:28
    • Marcado como respuesta Sergio_UY viernes, 19 de agosto de 2016 11:59
    viernes, 19 de agosto de 2016 8:06
  • Muchas gracias Sergio!
    viernes, 19 de agosto de 2016 12:00