2009-02-20 7 views
5

¡esta es mi primera publicación! Estoy bastante desesperado, así que voy más allá de mi búsqueda en Google estándar. Creo que esta es una pregunta .NET avanzada o de nivel experto.Inserte controles dinámicos en la mitad de la colección de controles

El problema es que he creado una aplicación web .NET que necesita poder insertar controles de usuario dinámicamente en el medio de una lista. Estoy bastante cómodo con los controles dinámicos, siempre y cuando solo necesiten agregarse al final de la lista (es decir, estoy familiarizado con artículos como este: http://msdn.microsoft.com/en-us/library/ms972976.aspx). Sin embargo, si necesito agregar un UserControl al frente de una colección de controles o en algún lugar en el medio, estoy bastante perdido ya que el UniqueID del control se descarta.

Como ejemplo simplificado, digamos que tengo un Panel al que agrego una lista de UserControls llamada MyControl.ascx. También tengo algún evento que pueda ser activado en la página para que se necesite insertar dinámicamente un MyControl.ascx en el índice especificado de la colección Controls del panel. También tengo uno o más eventos en MyControl.ascx a los que debo suscribirme. Esto significa que los controles deben cargarse ANTES de que los eventos en estos controles se disparen o de lo contrario no se dispararán. Si usted no sabe a lo que me refiero entonces ya sea redactado la pregunta mal o esta pregunta podría ser demasiado difícil para ti :)

A continuación se muestra un poco de C# pseudocódigo para demostrar el problema. El problema es que el método Controls.AddAt (índice, control) NO ajusta los valores UniqueID de los controles en consecuencia. Por ejemplo, considere los siguientes controles en una colección de controles:

Si estoy escribiendo código que dependa directamente de UniqueID o no, .NET usa indirectamente UniqueID para vincular los eventos que se activaron en la devolución de datos anterior. con los controles cargados en la nueva devolución de datos. Tomando mi ejemplo anterior de:

en posición inicial Page Load (Page.IsPostback == false)

<table> 
    <tr> 
    <td width='100'>Control index</td> 
    <td width='75'>UniqueID</td> 
    <td>Value</td> 
    </tr> 
    <tr> 
    <td>0</td> 
    <td>ctl00</td> 
    <td>value1</td> 
    </tr> 
    <tr> 
    <td>1</td> 
    <td>ctl01</td> 
    <td>value2</td> 
    </tr> 
    <tr> 
    <td>2</td> 
    <td>ctl02</td> 
    <td>value3</td> 
    </tr> 
</table> 

Después de una devolución de datos (Page.IsPostback == false) de algún otro control que quiere insertar el control en el índice 0:

si hago un Controls.AddAt(0, newControl) entonces la colección Controls es como la siguiente:

<table> 
    <tr> 
    <td width='100'>Control index</td> 
    <td width='75'>UniqueID</td> 
    <td>Value</td> 
    </tr> 
    <tr> 
    <td>0</td> 
    <td>ctl03</td> 
    <td>value0 <== the controls' unique IDs do not shift!</td> 
    </tr> 
    <tr> 
    <td>1</td> 
    <td>ctl00</td> 
    <td>value1</td> 
    </tr> 
    <tr> 
    <td>2</td> 
    <td>ctl01</td> 
    <td>value2</td> 
    </tr> 
    <tr> 
    <td>3</td> 
    <td>ctl02</td> 
    <td>value3</td> 
    </tr> 
</table> 

Así que si yo fuera a hacer clic en un LinkButton en el control con Value == value0 y UniqueID == ctl03, los controles se ordenarían como los siguientes en post-back y los UniqueID no estarían en el orden que deseo. Esto hará que el evento click para insertarse en el control equivocado:

<table> 
    <tr> 
    <td width='100'>Control index</td> 
    <td width='75'>UniqueID</td> 
    <td>Value</td> 
    </tr> 
    <tr> 
    <td>0</td> 
    <td>ctl00</td> 
    <td>value0 <== the control i wanted to throw the event</td> 
    </tr> 
    <tr> 
    <td>1</td> 
    <td>ctl01</td> 
    <td>value1</td> 
    </tr> 
    <tr> 
    <td>2</td> 
    <td>ctl02</td> 
    <td>value2</td> 
    </tr> 
    <tr> 
    <td>3</td> 
    <td>ctl03</td> 
    <td>value3 <== the actual control to which the event is attached</td> 
    </tr> 
</table> 

Si yo no tuviera que manejar eventos de estos controles dinámicos esto probablemente no sería un problema. Aquí está mi código:

// on init i just need to pull the records from the DB, turn them 
// into a MyControl.ascx, and then add them to my panel 
protected override void OnInit(EventArgs e) 
{ 
    base.OnInit(e); 

    // get my List<SomethingFromDB> ordered by value and iterate through, 
    // adding controls to the control collection 
    List<SomethingFromDB> myList = remoteService.GetSomeListFromTheDB(); 
    foreach(SomethingFromDB something in List<SomethingFromDB>) 
    { 
     // load a new MyControl.ascx 
     MyControl myControl = (MyControl)LoadControl("~/Controls/MyControl .ascx"); 
     // populate the values of myControl with the "something" 
     this.populateMyControl(something); 
     // dynamically add the control to my panel 
     this.myPanel.Add(myControl);  
     // subscribe to event 
     myControl.SomeArbitraryEvent += new EventHandler(MyArbitraryHandler); 
    } 

    // This event gets fired by a magical control on the page and passes a 
    // new SomethingFromDB which needs to be inserted into the DB and then 
    // dynamically inserted into the Controls collection at the specified index 
    private void SomeOtherControl_ClickInsert(object sender, MyControlEventArgs e) 
    { 
     // insert this record into the DB    
     remoteService.InsertIntoDB(e.SomethingFromDB);  
     // dynamically load this control 
     MyControl myControl = (MyControl)LoadControl("~/Controls/MyControl .ascx"); 
     // get the index into which we will be inserting this control 
     int index = e.NewIndex;     
     //dynamically add the control to my panel at the specified index. 
     // THIS DOES NOT ADJUST THE UNIQUEID VALUES ACCORDINGLY 
     // AND IS THE SOURCE OF MY PROBLEM! 
     this.myPanel.AddAt(index, myControl); 
    } 

Por favor ayuda. Este me está matando. Si necesita más información o tiene preguntas, hágamelo saber y estaremos encantados de brindarle más información. ¡GRANDEMENTE aprecio tu ayuda!

+0

Ahora, no va por el camino correcto, está explicando su problema en lugar de explicar lo que quiere lograr. Hay una diferencia en eso que hace que sea difícil sugerir mejores formas (que a veces son las formas correctas) de abordar un problema en particular. Edita tu pregunta! –

Respuesta

5

Para realizar la numeración automática, desea que los controles se agreguen al panel en el mismo orden para cada devolución. Obviamente, en una devolución de datos, los controles deben tener sus identificaciones únicas asignadas, o no obtendría el evento de control.

UniqueID es inicializado en el primer uso al valor de la propiedad * Control.ID.Si esa propiedad no está configurada, se genera automáticamente como ctlxx, como ha observado. Una vez asignado, el control UniqueID es de solo lectura.

Por lo tanto, si tiene algún tipo de clave principal, puede establecer la propiedad ID del control cuando lo crea basándose en esa clave principal. El UniqueID se establecerá en ese valor cuando la página cargue su estado.

  • Nota: la propiedad UniqueID es en realidad una combinación de prefijo del contenedor de nomenclatura y la propiedad ID.
+0

Gracias por la respuesta, Luz del sol. UniqueID se configura tan pronto como lo agregue a myPanel. El problema es que cuando se llama al "SomeOtherControl_ClickInsert", los controles ya están en el panel y se le ha asignado un UniqueID. Cuando voy a insertar mi conrol, ya es demasiado tarde. – jakejgordon

+0

Realmente odio este límite de 300 caracteres. De todos modos, soy consciente de que UniqueID es una combinación de los controles principales y la página, así como el índice del control en la colección de controles. Simplemente no veo cómo puedo poner un control en el medio de la colección y engancharme al evento correcto – jakejgordon

+0

... enganchar al evento correcto en la devolución de datos si se hace clic en uno de los controles dinámicos. ¿Podrías elaborar un poco más? Pude haber formulado mi pregunta mal, no estoy seguro. – jakejgordon

0

Utilice el siguiente atributo en la directiva de la página.

MaintainScrollPositionOnPostback = true 

Esto ayuda, creo.

Cuestiones relacionadas