ASP.NET - Dynamické vytváření ovládacích prvků
Co tento článek ukazuje
- Jak lze dynamicky vytvářet ovládací prvky
- Jak přímo přistupovat k datům z HTML formuláře
- Jak je možné ovlivnit ukládání ViewState
Při tvorbě webových aplikací se můžete dostat do situace, kdy nevíte kolik ovládacích prvků budete potřebovat na stránce zobrazit (např. pokud chcete uživateli zobrazit CheckBoxy s možnostmi, které jsou uložené v databázi). V této situaci je potřeba vytvářet ovládací prvky dynamicky, tedy z kódu stránky.
Vytváření ovládacích prvků
Pokud chcete vytvářet ovládací prvky dynamicky je potřeba tyto prvky vytvořit
dříve, než dojde k načtení stránky (pokud je budete vytvářet později, prvky
se sice zobrazí, ale po provedení postbacku se ztratí v nich uložená data).
Obvykle je nejlepší řešení vytvářet ovládací prvky v metodě OnInit
.
Vytvořené ovládací prvky si ASP.NET při post-backu automaticky nepamatuje
a proto je potřeba vytvářet ovládací prvky ne jednou, ale při každém dotazu
na stránku. Při vytváření ovládacích prvků je také potřeba vědět kam se prvky
mají na stránku vkládat (je také důležité, aby se prvky vkládaly mezi form
,
který má nastavený atribut runat=server
). K tomuto účelu je v ASP.NET
ovládací prvek PlaceHolder
, do kterého je možné pouze vkládat
vytvářené ovládací prvky.
Kód, který vytvoří v metodě OnInit
několik tlačítek a přidá je do
PlaceHolderu placeCtrls
vypadá takto:
// Vytvori 5 buttonu a prida je do placeCtrls override protected void OnInit(EventArgs e) { for(int i=1; i<=5; i++) { // Vytvori ovladaci prvek.. Button btn=new Button(); btn.ID=string.Format("btn{0}",i); btn.Text=string.Format("Cudlik {0}",i); // .. a prida ho do placeCtrls placeCtrls.Controls.Add(btn); } // Volani nutne pro Asp.Net InitializeComponent(); base.OnInit(e); }
Zpracování událostí
Pokud již vytváříte nějaké ovládací prvky, budete také pravděpodobně potřebovat k těmto ovládacím prvkům nějak přistupovat a nebo zachytávat jejich události. Nejprve se podíváme jak lze rozšířit předchozí ukázku tak, aby aplikace po stisknutí tlačítka vypsala jaké tlačítko bylo stisknuto. Nejprve je potřeba přidat kód, který přiřadí kliknutí na tlačítko nějakou událost. Pokud tuto událost přiřadíte všem generovaným tlačítkům, budete při její vyvolání potřebovat rozlišit, které tlačítko ji vyvolalo. Kvůli tomu předává ASP.NET jako první parametr události objekt který událost vyvolal (v našem případě stisknuté tlačítko).
// Prirazeni udalosti - // radku pridejte ke kodu generujicimu tlacitka btn.Click+=new EventHandler(btn_Click); ... // Metoda ktera zpracovava kliknuti private void btn_Click(object sender, EventArgs e) { // Zjisti objekt stisknuteho tlacitka Button clicked=(Button)sender; // Vypise text zobrazeny na tlacitku lblMessage.Text="Klikli jste na tlacitko: "+clicked.Text; }
Přídávání ovládacích prvků
Kód ukázaný v předchozí ukázce ve většině případů plně postačuje. Občas je ale potřeba aby počet (typ a nebo nějaké jiné nastavení) ovládacích prvků mohl uživatel při práci se stránkou měnit. Tím se situace zkomplikuje hned ze dvou důvodů. Za prvé si stránka musí nějakým způsobem ukládat toto nastavení aby mohla při načítání vytvářet příslušné ovládací prvky a za druhé je potřeba aby aplikace nepřidávala ovládací prvky při zpracování nějaké události ale dříve (Například pokud uživatel klikne na tlačítko, které má přidat textové pole, je potřeba toto pole přidat ještě dříve než se událost ve skutečnosti vyvolá). Naznačení, jak řešit tyto problémy naleznete ve zbývající části článku, pro kompletní řešení se podívejte do zdrojových kódů.
Aplikace, která umožňuje přídávání textových polí
Přidávání textových polí
Nejprve se podíváme na druhý problém, tedy jak při kliknutí na tlačítko Přidat (btnAdd
)
vytvořit textové pole dříve než dojde k vyvolání události. Vzhledem k tomu,
že ASP.NET generuje tlačítka jako input type="submit"
, lze k
zachycení události využít vlastnosti HTML forumláře. Při kliknutí
na submit tlačítko se předává v kolekci Request.Form
jeho hodnota
a tato kolekce je přístupná již v metodě OnInit
. Pokud tedy máme na stránce
tlačítko (btnAdd
) a textové pole (txtName
), je možné
zjistit zda uživatel kliknul na tlačítko a jaký zadal text následujícím způsobem:
override protected void OnInit(EventArgs e) { // Pokud uzivatel kliknul na tlacitko // bude zde vyplneno jmeno tlacitka if (Request.Form["btnGenerate"]!=null) { // Jmeno je nutne zjistit take pres Form, // protoze Asp.Net data jeste nenacetlo string jmeno=Request.Form["txtName"]; ... } InitializeComponent(); base.OnInit(e); }
Ukládání nastavení ovládacích prvků
Druhým problémem, o kterém jsem se zmiňoval je potřeba ukládat nastavení
o generovaných ovládacích prvcích. V ukázkové aplikaci (viz obrázek) je
potřeba ukládat jména checkboxů, které se dynamicky vytvářejí. Když se podíváte,
v jakém pořadí se zpracovávají ASP.NET stránky (viz [1])
je vidět, že toto nastavní se musí nastavit před načítáním dat ovládacích
prvků (Process postback data). Pokud chceme toto nastavení ukládat do ViewState
(což je nejrozumnější místo) tak ale nemůžeme ovládací prvky vytvářet již
při OnInit
, protože ViewState
se načítá až později.
Potřebujeme tedy nějakou metodu, která se volá pří, nebo po druhém kroku
(Load view state). Tato metoda se (kupodivu) jmenuje LoadViewState
,
spolu s metodou SaveViewState
je pomocí těchto dvou metod možné
ovlivnit způsob jakým se ukládá ViewState stránky.
V ukázkové aplikaci bude tedy nastavení checkboxů ukládaáno v SaveViewState
a toto nastavení budeme načítat ve volání LoadViewState
(v tento okamžik
je možné vytvářet ovládací prvky). Tyto metody obstarávají v ASP.NET stránce
celé ukládání ViewState, takže při jejich úpravě je potřeba volat metodu předka,
která zajišťuje zpracování ViewState všech ovládacích prvků na stránce.
// Zde si pri nacteni ulozime nastaveni string gen=""; // Uklada nastaveni do view state // Metoda musi take ulozit nastaveni cele stranky protected override object SaveViewState() { object[] vs=new object[2]; // Do pole se ulozi nastaveni ovladacich prvku vs[1]=gen; // .. a puvodni ViewState vs[0]=base.SaveViewState(); return vs; } // Nacita nastaveni z view state // Jako parametr Asp.Net predava cela data ve ViewState protected override void LoadViewState(object savedState) { object[] vs=(object[])savedState; string savedGen=(string)vs[1]; ... VytvoritOvladaciPrvkyPodleNastaveni(savedGen); ... // Nacist puvodni ViewState pro zbytek stranky base.LoadViewState(vs[0]); }
Soubory na stažení a odkazy
- Control Execution Lifecycle [^] - MSDN Library