Správičky 2 800 Blogy 945 Fórum 18 574

Rekonštrukcia ViewState dynamicky pridaných kontrolov

jradoslav - 27. 12. 2008 20:20 - 16233 views

Rekonštrukcia ViewState dynamicky pridaných kontrolov.

Pred nedávnom som riešil problém ako rekonštruovať viewstate v postbacku dynamicky vytvorených kontrolov ako je napr Label, alebo iný control (napr. vlastný).

Dynamicky pridávané servrové kontroly majú široké využitie, napr. renderovanie šablón, ktoré obsahujú istú servrovskú funkčnosť (bežné formuláre). A zároveň chceme aby zmeny v šablónach boli vykonávané za behu aplikácie, čiže nieje potrebná kompilácia aspx stránok.

Toto je riešenie ktoré nám fungovať bude iba ak nieje postovaný formulár, to znamená že pridaný Label sa nám v postbacku stratí.

     protected override void OnInit(EventArgs e)
   
{
       
base.OnInit(e);
       
if (!IsPostBack)
       
{
            Label newLabel
= new Label();
           
this.Controls.Add(newLabel);
            newLabel.Text
= retrieveTextFromDatabase();
        }

     }

Chceme predsa, aby sa v postbacku Label zobrazil správne bez dotazovania sa na databázu.

Tu je riešenie:

     protected override void OnInit(EventArgs e)
   
{
       
base.OnInit(e);
       
if (!IsPostBack)
       
{
            Label newLabel
= new Label();
           
this.Controls.Add(newLabel);
            newLabel.Text
= retrieveTextFromDatabase();
        }

       
else
       
{
            Label newLabel
= new Label();
           
this.Controls.Add(newLabel);
        }

    }

  1. Podstata je v tom že poradie pridávaných dynamických kontrolov musí byť v PostBacku rovnaké ako v Not PostBacku
  2. Dôležitá zásada je poradie inicializácie premennej Text. táto inicializácia sa musí vykonať až po pridaní kontrolu do rodiča. Jedine vtedy sa zosynchronizujú indexy Viewstatu a prevedie sa správna inicializácia kontrolu. Volaná metóda  'this.Controls.Add(newLabel);' musí byť pred 'newLabel.Text = retrieveTextFromDatabase(); '
  3. Premenná Text musí byť uložená vo ViewState

Ak používate vlastný kontrol ako je to v tomto pripade, je dôležité aby premenná InnerHTML bola ukladaná vo ViewState so svojím Indexom.

    public class RawHtmlContainer :Control
   
{
       public
string InnerHTML
       
{
           
get { return ViewState["InnerHTML"] == null ? String.Empty : ViewState["InnerHTML"] as String; }
           
set { ViewState["InnerHTML"] = value; }
        }

       
protected override void Render(HtmlTextWriter writer)
       
{
            writer.Write(InnerHTML);
        }

    }

Príklad inicializácie:

protected override void OnInit(EventArgs e)
   
{
       
base.OnInit(e);
        
if (!IsPostBack)
       
{
            Label newLabel
= new Label();
            RawHtmlContainer container
= new RawHtmlContainer();
           
           
this.Controls.Add(newLabel);
           
this.Controls.Add(container);
            container.InnerHTML
= retrieveHtmlFromDatabase();
            newLabel.Text
= retrieveTextFromDatabase();
        }

       
else
       
{
            Label newLabel
= new Label();
            RawHtmlContainer container
= new RawHtmlContainer();

           
this.Controls.Add(newLabel);
           
this.Controls.Add(container);
        }

  }


Ing Radoslav Jízdný

Radoslav Jízdný RHalotel s.r.o.

Článkov: 1, Správičiek: 1, Príspevkov vo fóre: 81, Príspevkov v blogu: 0, Bodov: 485
Najaktívnejší č.: 42
Profil používateľa

Reakcie

# RE: Rekonštrukcia ViewState dynamicky pridaných kontrolov 14. 1. 2009 17:10:55 T

Citacia:
1. Podstata je v tom že poradie pridávaných dynamických kontrolov musí byť v PostBacku rovnaké ako v Not PostBacku


Poradie nie je dolezite, dolezite je, aby mali kontajnery aj controly takto generovane nastavene na pevno idcko, teda aby nedochadzalo v pripade, ze nie su explicitne nastavene ku ich pregenerovaniu po postbacku na ine a ASP .NET framework potom nevie naparovat samozrejme viewState
-------------------------------
Citacia:
2. Dôležitá zásada je poradie inicializácie premennej Text. táto inicializácia sa musí vykonať až po pridaní kontrolu do rodiča. Jedine vtedy sa zosynchronizujú indexy Viewstatu a prevedie sa správna inicializácia kontrolu. Volaná metóda 'this.Controls.Add(newLabel);' musí byť pred 'newLabel.Text = retrieveTextFromDatabase();

Je to absolutne jedno v akom poradi sa to udeje. Za vytvorenie viewState je zodpovedna LoadViewState a SaveViewState ktore vola framework neskor(po OnInite) v ramci lifecycle stranky
-------
Citacia
3. Premenná Text musí byť uložená vo ViewState

Nemusi. Ak je dodrzana zasada z bodu jedna, tak staci

Label newLabel = new Label();
newLabel.Id= "myLabel";
this.Controls.Add(newLabel);

if(!IsPostBack)
newLabel.Text = retrieveTextFromDatabase();

a je po probleme.

Navyse, ak mas dobre vyrieseny caching a/alebo vyuzijes moznosti, ktore mas v tomto smere v ASP.NET Frameworku tak ta nemusi trapit ani ten if(!IsPostBack) v kombinacii s viewState.

# RE: Rekonštrukcia ViewState dynamicky pridaných kontrolov 14. 1. 2009 17:11:14 T

Citacia:
1. Podstata je v tom že poradie pridávaných dynamických kontrolov musí byť v PostBacku rovnaké ako v Not PostBacku


Poradie nie je dolezite, dolezite je, aby mali kontajnery aj controly takto generovane nastavene na pevno idcko, teda aby nedochadzalo v pripade, ze nie su explicitne nastavene ku ich pregenerovaniu po postbacku na ine a ASP .NET framework potom nevie naparovat samozrejme viewState
-------------------------------
Citacia:
2. Dôležitá zásada je poradie inicializácie premennej Text. táto inicializácia sa musí vykonať až po pridaní kontrolu do rodiča. Jedine vtedy sa zosynchronizujú indexy Viewstatu a prevedie sa správna inicializácia kontrolu. Volaná metóda 'this.Controls.Add(newLabel);' musí byť pred 'newLabel.Text = retrieveTextFromDatabase();

Je to absolutne jedno v akom poradi sa to udeje. Za vytvorenie viewState je zodpovedna LoadViewState a SaveViewState ktore vola framework neskor(po OnInite) v ramci lifecycle stranky
-------
Citacia
3. Premenná Text musí byť uložená vo ViewState

Nemusi. Ak je dodrzana zasada z bodu jedna, tak staci

Label newLabel = new Label();
newLabel.Id= "myLabel";
this.Controls.Add(newLabel);

if(!IsPostBack)
newLabel.Text = retrieveTextFromDatabase();

a je po probleme.

Navyse, ak mas dobre vyrieseny caching a/alebo vyuzijes moznosti, ktore mas v tomto smere v ASP.NET Frameworku tak ta nemusi trapit ani ten if(!IsPostBack) v kombinacii s viewState.

# RE: Rekonštrukcia ViewState dynamicky pridaných kontrolov 14. 1. 2009 17:11:40 T

Citacia:
1. Podstata je v tom že poradie pridávaných dynamických kontrolov musí byť v PostBacku rovnaké ako v Not PostBacku


Poradie nie je dolezite, dolezite je, aby mali kontajnery aj controly takto generovane nastavene na pevno idcko, teda aby nedochadzalo v pripade, ze nie su explicitne nastavene ku ich pregenerovaniu po postbacku na ine a ASP .NET framework potom nevie naparovat samozrejme viewState
-------------------------------
Citacia:
2. Dôležitá zásada je poradie inicializácie premennej Text. táto inicializácia sa musí vykonať až po pridaní kontrolu do rodiča. Jedine vtedy sa zosynchronizujú indexy Viewstatu a prevedie sa správna inicializácia kontrolu. Volaná metóda 'this.Controls.Add(newLabel);' musí byť pred 'newLabel.Text = retrieveTextFromDatabase();

Je to absolutne jedno v akom poradi sa to udeje. Za vytvorenie viewState je zodpovedna LoadViewState a SaveViewState ktore vola framework neskor(po OnInite) v ramci lifecycle stranky
-------
Citacia
3. Premenná Text musí byť uložená vo ViewState

Nemusi. Ak je dodrzana zasada z bodu jedna, tak staci

Label newLabel = new Label();
newLabel.Id= "myLabel";
this.Controls.Add(newLabel);

if(!IsPostBack)
newLabel.Text = retrieveTextFromDatabase();

a je po probleme.

Navyse, ak mas dobre vyrieseny caching a/alebo vyuzijes moznosti, ktore mas v tomto smere v ASP.NET Frameworku tak ta nemusi trapit ani ten if(!IsPostBack) v kombinacii s viewState.

# RE: Dodatok Rekonštrukcia ViewState dynamicky pridaných kontrolov 18. 1. 2009 13:56:48

Dakujem za anonymny prispevok.
No prax a teoria ukazala ze je dolezite poradie pridavanych kontrolov. Bez toho aby idcka boli generovane explicitne.

ViewState tree sa synchronizuje podla nazvu indexu ktory je pouzity v kontrole a podla indexu kontrolu ktory je pridavany.

dokazuje to nasledovny priklad:

protected override void OnInit(EventArgs e)

{

base.OnInit(e);

if (!IsPostBack)

{

Button btnClickMe = new Button();

form1.Controls.Add(btnClickMe);

btnClickMe.Text = "Click me";

btnClickMe.CommandName = "XXX";

}

else

{

Label label = new Label();

form1.Controls.Add(label);

}

}

vidime ze premenna text sa inicializuje rovnako v buttone ako v labely.Pritom su to uplne rozdielne kontroly ale maju rovnake indexy.

Samozrejme je dolezite aby premenna bola inicializovana az po pridani do rodica inak to fungovat nebude.

Neviem co tym myslite cachovanie kontrolov, pravda cachovat kontrol ako taky je nevhodne a nespravne pretoze pri ulozeni samotrneho kontrolu do cache vznikne takzvany overheading, nasledna strata akychkolvek handlerov, a odpojenie od aktualneho threadu.

Cachovanie dat v backende a nasledna inicializacia kontrolu je mimo temy ktoru som opisoval.

Samozrejme nema zmysel Vam oponovat, treba si odskusat priklady, ktore som prezentoval.
Kde pri nedodrzani popisanych zasad priklad prestane fungovat.Dakujem.

# RE: Dodatok Rekonštrukcia ViewState dynamicky pridaných kontrolov 18. 1. 2009 14:31:35

Nieje pravda ze:
"Poradie nie je dolezite, dolezite je, aby mali kontajnery aj controly takto generovane nastavene na pevno idcko, teda aby nedochadzalo v pripade, ze nie su explicitne nastavene ku ich pregenerovaniu po postbacku na ine a ASP .NET framework potom nevie naparovat samozrejme viewState
"

Nema to ziadnu spojitost s ideckom kontrolu, podla toho sa viewstate parovanie vobec neriadi.riadi sa podla indexu v ktory nadobuda kontrol po pridani na rodica.Controls.Add().

# RE: Rekonštrukcia ViewState dynamicky pridaných kontrolov 19. 1. 2009 17:58:06 T

Pisal som to ja. Mylil som sa, naozaj sa loaduje viewstate by default podla indexu controlu, ospravedlnujem sa. Viem vsak toto spravanie lahko zmenit - Control.LoadViewStateByID; ak je na to dovod - a to v tomto pripade je.

Cize sme tam, o com som pisal vyssie, nemusime sa trapit s indexami/poradim(ak sme uz fanusikmi viewState) a tych par byteov na menej efektivny sposob serializacie podla Id v containery, kam generujeme dynamicky controly mozeme uz fakt ozeliet, ak ideme cestou viewState extenzivneho kodu.
---------------------------
"Dôležitá zásada je poradie inicializácie premennej Text. táto inicializácia sa musí vykonať až po pridaní kontrolu do rodiča. Jedine vtedy sa zosynchronizujú indexy Viewstatu a prevedie sa správna inicializácia kontrolu. Volaná metóda 'this.Controls.Add(newLabel);' musí byť pred 'newLabel.Text = retrieveTextFromDatabase();"

Aj tu som sa mylil, bohuzial nie je to koly nicomu takemu ako pises....
properties nie su serializovane/deserializovane podla indexu, ale string kluca. Staci sa pozriet cez reflector na ControlCollection.Add a Control.AddedControl metody. Pokym control nepridas do controls collection nezapdne sa trackovanie viewstate na nom

+ dalsie vysvetlenie z msdn

StateBag =>
This class is the primary storage mechanism for all HTML and Web server controls. It stores attribute/value pairs as strings associated with the control. It tracks changes to these attributes only after the OnInit method is executed for a page request, and saves the changes to the page's or control's view state.


------

1. mozem cacheovat data server side, to samozrejme robim na urovni DAL, pripadne BLL (napr. nemeniace alebo malo sa meniace hodnoty ktore poloziek v combo).

2. mozem cacheovat cast stranky(control) alebo celu stranku a to so zohladnenim nejakych dynamicky sa meniacich parametrov.
Samozrejme, ze ma zaujima vysledny output
z controlu, teda kus html...nestacam cas nielen dotahovanim dat z datoveho zdroja ale ani na lifecycle controlov v danej cacheovanej area.

a etc.

Pridať reakciu

Titulok:
Meno:
Url:
Koľko je 22 + 4?
(ochrana proti spamu)
Komentár:

Najaktívnejší užívatelia
1. 37750 b. photo vlko
2. 21315 b. photo T
3. 15955 b. photo spigi
4. 15450 b. photo Anonymous
5. 11120 b. photo dudok
6. 9385 b. photo Liero
7. 6885 b. photo siro
8. 6245 b. photo slavof
9. 5355 b. photo duracellko
10. 4445 b. photo xxxmatko