2009-02-20 13 views
5

questo è il mio primo post! Sono piuttosto disperato, quindi vado oltre il mio standard googling. Credo che questa sia una domanda .NET avanzata o di livello esperto.Inserire i controlli dinamici nel mezzo della collezione di controlli

Il problema è che ho creato un'applicazione Web .NET che deve essere in grado di inserire i controlli utente dinamicamente nel mezzo di un elenco. Sono abbastanza a mio agio con i controlli dinamici, a tal punto che devono essere aggiunti solo alla fine dell'elenco (ad es .: ho familiarità con articoli come questo: http://msdn.microsoft.com/en-us/library/ms972976.aspx). Tuttavia, se ho bisogno di aggiungere un UserControl alla parte anteriore di una collezione di controlli o da qualche parte nel mezzo sono praticamente perso dal momento che l'UniqueID del controllo viene eliminato.

Come esempio semplificato, diciamo che ho un Pannello a cui sto aggiungendo un elenco di UserControls chiamato MyControl.ascx. Ho anche alcuni eventi che possono essere attivati ​​nella pagina a cui è necessario inserire dinamicamente un MyControl.ascx nell'indice specificato dell'insieme Controlli del pannello. Ho anche uno o più eventi su MyControl.ascx a cui devo iscrivermi. Ciò significa che i controlli devono essere caricati PRIMA che gli eventi su questi controlli si attivino o che non si attivino. Se non sai a cosa mi riferisco allora ho formulato la domanda male o questa domanda potrebbe essere troppo difficile per te :)

Di seguito è riportato uno pseudocodice C# per dimostrare il problema. Il problema è che il metodo Controls.AddAt (index, control) NON aggiusta di conseguenza i valori UniqueID dei controlli. Ad esempio, considerare i seguenti controlli in una raccolta Controls:

Indipendentemente dal fatto che sto scrivendo codice che dipende direttamente dall'ID Unique o meno, .NET utilizza indirettamente UniqueID per collegare insieme gli eventi che sono stati generati nel postback precedente con i controlli vengono caricati sul nuovo postback. Prendendo mio precedente esempio di:

Su iniziale 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> 

Dopo un postback (Page.IsPostback == false) da qualche altro controllo che vuole inserire il controllo in corrispondenza dell'indice 0:

Se faccio un Controls.AddAt(0, newControl) poi la collezione Control si presenta in questo modo:

<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> 

Quindi, se dovessi fare clic su un pulsante di collegamento in il controllo con Value == value0 e UniqueID == ctl03, i controlli sarebbero ordinati come il seguente sul post-back e gli UniqueIDs non sarebbero nell'ordine che voglio. Questo farà sì che l'evento click di allegare al controllo sbagliato:

<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> 

Se io non ho dovuto gestire gli eventi da questi controlli dinamici questo probabilmente non sarebbe un problema. Ecco il mio codice:

// 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); 
    } 

Si prega di aiuto. Questo mi sta uccidendo. Se hai bisogno di maggiori informazioni o hai domande per favore fammelo sapere e sarei felice di fornire ulteriori informazioni. Apprezzo molto il tuo aiuto!

+0

Vedi ora, stai andando in questo modo nel modo sbagliato, stai spiegando il tuo problema piuttosto che spiegare cosa vuoi ottenere. C'è una differenza in ciò che rende difficile suggerire modi migliori (che a volte sono i giusti modi) di affrontare un particolare problema. Modifica la tua domanda! –

risposta

5

Per eseguire la numerazione automatica, è necessario aggiungere i controlli al pannello nello stesso ordine per ogni postback. Ovviamente, su un postback, i controlli devono avere i loro ID univoci assegnati o non si ottiene l'evento di controllo.

UniqueID viene inizializzato al primo utilizzo sul valore della proprietà Control.ID *.Se questa proprietà non è impostata, viene generata automaticamente come ctlxx, come è stato osservato. Una volta assegnato, il controllo UniqueID è di sola lettura.

Pertanto, se si dispone di una qualche forma di chiave primaria, è possibile impostare la proprietà ID del controllo quando la si crea in base a tale chiave primaria. Il UniqueID verrà quindi impostato su tale valore quando la pagina carica il suo stato.

  • Nota: la proprietà UniqueID è in realtà una combinazione di prefisso del contenitore di denominazione e la proprietà ID.
+0

Grazie per la risposta, Sunlight. UniqueID viene impostato non appena lo aggiungo a myPanel. Il problema è che quando viene chiamato "SomeOtherControl_ClickInsert", i controlli sono già presenti sul pannello e viene assegnato un UniqueID. Quando vado a inserire il mio controllo è già troppo tardi. – jakejgordon

+0

Odio davvero questo limite di 300 caratteri. In ogni caso, sono a conoscenza del fatto che UniqueID è una combinazione del controllo (i) principale e della pagina e dell'indice del controllo nella raccolta di controlli. Semplicemente non vedo come posso mettere un controllo nel mezzo della collezione e collegarmi all'evento giusto – jakejgordon

+0

... agganciare all'evento giusto sul postback se si fa clic su uno dei controlli dinamici. Potresti elaborare un po 'di più? Potrei aver formulato la mia domanda male, non ne sono sicuro. – jakejgordon

0

Utilizzare il seguente attributo nella direttiva della pagina.

MaintainScrollPositionOnPostback = true 

Questo aiuta, credo.