Crad's .NET Blog

L'UGIblog di Marco De Sanctis
posts - 190, comments - 448, trackbacks - 70

Viewstate e controlli dinamici

Volevo rispondere a questo post di Gian Maria, poi il testo era un po' lungo e allora ho optato per la modalità stand alone :D

Anche in ASP.NET 2.0, come accadeva nella 1.1, è necessario ricreare controlli dinamici durante la fase di Init al fine di preservare correttamente il viewstate. La ragione risiede nel fatto che il ripristino dello stato dei controlli avviene in maniera posizionale. Consideriamo una pagina con una DropDownList (il cui contenuto è ripristinato tramite Viewstate) e il seguente snippet di codice, che aggiunge un button prima della ddl stessa:

protected void Page_Load(object sender, EventArgs e) { this.form1.Controls.AddAt(0, new Button()); if (!IsPostBack) { ddlTest.DataSource = getDataSource(); ddlTest.DataBind(); } }

Se analizziamo il ciclo di vita della pagina, ad esempio attivando il trace, notiamo che l'ordine degli eventi è il seguente (ho volutamente omesso tutto ciò che non interessa questo discorso):

  1. Init
  2. LoadViewState
  3. Load
  4. SaveViewState

Bene. Visualizziamo nel browser la nostra pagina, LoadViewState non viene sollevato perché non siamo in un postback, Load costruisce il button dinamico, SaveViewState salva lo stato di un albero di oggetti che, grossomodo è

  • Button
  • DropDownList

Supponiamo di effettuare un postback. Cosa accade?

LoadViewState prova a ripristinare lo stato del Button, ma questo ancora non esiste: l'evento Load ancora non si è verificato e l'albero degli oggetti ora è composto dalla sola DropDownList! Il risultato è che LoadViewState invierà i dati del Button al metodo LoadViewState della DropDownList, che ovviamente non sarà in grado di ripristinare correttamente lo stato, proponendoci nel postback una DropDownList vuota.

Creando il button in fase di Init, invece, il problema non si pone, dato che LoadViewState opera in un contesto coerente con quello in cui è stato eseguito il SaveViewState al precedente rendering della pagina.

EDIT: quanto segue è frutto di uno sforzo congiunto da parte mia e del buon Alk :)

In ASP.NET 2.0 (devo verificare cosa accade su 1.1) in realtà è comunque possibile aggiungere controlli dinamici in una fase successiva al LoadViewState: basta utilizzare un placeholder o un qualunque altro controllo contenitore. Come è possibile?

In fase di postback, la Form ripartisce di nuovo il viewstate tra i suoi controlli di primo livello, al PlaceHolder va una porzione di albero e alla DDL un'altra. Quest'ultima, quindi, non si accorge minimamente dell'esistenza di controlli dinamici, riceve dati corretti e può quindi ripristinare il suo stato.

La cosa che sulle prime mi ha sbalordito, è che anche i controlli aggiunti in seguito nel placeholder conservano le informazioni di stato. Non mi spiegavo come ciò fosse possibile, dato che comunque essi vengono creati dopo la fase di LoadViewState. La risposta sta nella classe ControlCollection. Quando viene ripristinato lo stato, un oggetto Control effettua un caching della porzione di viewstate ad esso inviato dal suo contenitore. All'aggiunta di un controllo child

this.plcHolder.Controls.Add(new Button());

viene eseguito il metodo Control.AddedControl che, nel caso la cache interna del viewstate non sia vuota, forza un nuovo Load dello stato per il controllo child (eventualmente anche per Id e non più in base all'ordine).

 

Technorati tags:

Print | posted on mercoledì 16 maggio 2007 16.27 | Filed Under [ ASP.NET 2.0 ]

Feedback

Gravatar

# re: Viewstate e controlli dinamici

Ma che bel tip per ugi... :-D
16/05/2007 16.34 | Lorenzo Barbieri
Gravatar

# re: Viewstate e controlli dinamici

Sei quindi la terza persona che conferma quello che sapevo, i controlli dinamici vanno creati nell'init. Il problema è che ho trovato un libro ed alcuni tutorial che fanno vedere il controllo caricato nell'evento load...facendo delle prove ho visto poi che effettivamente funziona lo stesso. L'unica accortezza è inserire i controlli in dei placeholder, perchè altrimenti il ripristino del viewstate viene fatto in maniera errata.

Alk.
16/05/2007 16.41 | Gian Maria
Gravatar

# re: Viewstate e controlli dinamici

Beh è un tantino piu complesso di così :)
Nel senso che l'esempio che ha fatto marco (cioè aggiungere dei controlli _direttamente_ alla collezione di controlli senza passare da un placeholder) lo sconsiglio vivamente in ogni caso. I Placeholder sono li apposta per essere usati a questo scopo!
Utilizzando un placeholder, è "ininfluente" il posto in cui carichi il controllo dinamico, basta che lo fai prima del render, dove vengono effettivamente richiamate le proprietà dei controlli (text, items, etc) che andranno a guardarsi il ViewState e si popoleranno di conseguenza....
Ovviamente, anche all'interno del PlaceHolder bisogna rispettare il valore posizionale dei controlli o va tutto a donne di facili costumi :)
16/05/2007 16.51 | Alessandro Ghizzardi
Gravatar

# re: Viewstate e controlli dinamici

Ne avevo parlato pure io 1 anno e mezzo fa :)
http://blogs.ugidotnet.org/piyo/archive/2006/01/24/custom_server_controls_ASPNET_ViewState.aspx
16/05/2007 23.48 | simone
Gravatar

# re: Viewstate e controlli dinamici

Qualcuno mi sa dire come posso inserire piu HyperLink in un placeholder ma sistemandoli in colonna?
17/06/2008 11.20 | Nello
Gravatar

# re: Viewstate e controlli dinamici

ok, grazie, è estremamente chiaro il concetto. ma se io dovessi cambiare i controlli nella pagina? cioè se la prima volta carico una text e la seconda sostituisco la text con una label e la terza con una option?
Devo ancora finire e anche se non ho capito mi è bastato rendere enableviewsate= false del placeholder.
12/09/2008 16.05 | [LDT]davraf
Gravatar

# re: Viewstate e controlli dinamici

Ciao!
Ho dei problemi col viewstate e controlli dinamici... e quindi sto cercando di documentarmi sull'argomento, anche usando intensivamente Red Gates's .NET Reflector.

In questo post dici che "la Form ripartisce di nuovo il viewstate tra i suoi controlli di primo livello, al PlaceHolder va una porzione di albero e alla DDL un'altra".

Da Reflector questo non riesco a vederlo. Non c'è nessun riferimento esplicito ai controlli di tipo PlaceHolder. Da dove hai preso questa informazione? E come fa PlaceHolder a dire alla Page di suddividere il viewstate in quel modo?

Ciao e grazie mille! :-)
13/02/2009 23.51 | Filippo D.
Gravatar

# re: Viewstate e controlli dinamici

Ciao a tutti,
sto cercando disperatamente di lavorare con dei controlli creati dinamicamente...
Nella pagina ho un Repeater ed ogni item del repeater ha dentro un PlaceHolder che mi servirà per aggiungere i controlli dall'evento ItemDataBound del repeater...tutto viene creato correttamente, ma poi al postback di un pulsante sparisce tutto.
In questo caso ho un PlaceHolder, ma sparisce tutto cmq...come mai? cosa posso aver sbagliato? come potrei risolvere il problema?
Spero tanto che qualcuno possa aiutarmi!
Grazie mille!
28/01/2010 18.07 | Elisa

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 8 and 3 and type the answer here:

Powered by: