In questo post illustrerò un po' di tips ricavati dalle mie esperienze e ore perse a cercare di capire il problema. Il ViewState è una bella cosa ma bisogna conoscere bene come lavora.
Se lavorate con controlli creati a runtime, vuoi perché interrogate un db o usate trasformazioni xslt, bisogna prestare attenzione ad una cosa. Il punto migliore dove crearli è OnInit della pagina (o del controllo). In questo modo siamo in "linea" con tutto il motore ASP.NET e non incapperemo in problemi di eventi e post dei dati. Si presenta però un problema. I controlli creati salvano nel viewState tutto quello impostato dopo l'init. Questo perché si presume (o presumo io) che i controlli siano stati creati dal parser ASP.NET quindi ogni proprietà e collezione non ha bisogno di essere salvata perché riimpostata ad ogni postback della pagina. Nel nostro caso però non è sempre così. A volte vogliamo risparmiare le interrogazioni del db. Per aggirare il problema ci sono due soluzioni:
- spostare la logica nel Load (a me non piace molto e si risolve in parte, ne parlerò dopo)
- separare creazione dei controlli dal caricamento dei controlli, rispettivamente nell'Init e nel Load
Veniamo a come funziona tutto sotto: dopo la fine della fase di Init viene richiamato per ogni controllo il metodo IStateManager.TrackViewState. Ogni controllo non deve far altro che marcare ogni precedente proprietà impostata come da non salvare nel viewState (al fine di ottimizzarne lo spazio).
L'oggetto StateBag (la proprietà ViewState di ogni controllo) per esempio, segna come non "Dirty" ogni successivo elemento aggiunto. Se volessimo impostare un elemento come da salvare anche se è stato impostato prima della chiamata a TrackViewState potremmo usare il metodo SetItemDirty, es:
ViewState.SetItemDirty("chiave", true);
Purtroppo alcuni controlli non usano solo lo stateBag ma sovrascrivono il metodo IStateManager.SaveViewState e quindi non possiamo intervenire. Il controllo DropDownList per esempio dispone della collezione Items. La classe ListItem dispone di una proprietà IsDirty, ma purtroppo è internal.
Per ultimo, guardate queste righe di codice:
TextBox t = new TextBox();
t.ForeColor = Color.Red;
Controls.Add(t);
oppure
TextBox t = new TextBox();
Controls.Add(t);
t.ForeColor = Color.Red;
Sono la stessa cosa? Io pensavo di sì, invece no. Init di un controllo avviene quando questo viene aggiunto alla collezione Controls. In base a quanto detto prima quindi, nel primo codice il ForeColor non verrà salvato nel viewState, nel secondo verrà salvato. Ovviamente sempre che EnableViewState sia true. Potrà sembrare banale ma a me sembra importante.
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- LINQ, lazy loading e architettura, l'11 marzo 2011 alle 18:42
- MetadataDiffViewer: aggiornato al .NET Framework 4.0, Silverlight 4.0 e Sharepoint 2010, il 7 gennaio 2010 alle 13:58
- .NET Framework 4.0 beta 1: Windows Communication Foundation, il 18 maggio 2009 alle 16:00
- Parallelizzare in Silverlight 2.0, il 21 aprile 2009 alle 00:25
- Silverlight: performance dell'isolated storage, il 16 aprile 2009 alle 17:38
- MetadataDiffViewer: differenze tra i framework, il 15 aprile 2009 alle 18:56