Serverové ovládací prvky v ASP.NET 3.

17. června 2003

V dnešním článku o serverových ovládacích prvcích se budeme zabývat mapováním klientských událostí na serverové události. Článek je vhodný i pro „nevěřící Tomáše“, kteří s technologií ASP.NET přišli do styku pouze povrchně a od kterých je možné občas slyšet, že serverové události a další pokročilé vlastnosti v ASP.NET jsou hezká věc, ale že je možné používat je jen s Internet Explorerem. To samozřejmě není pravda a jak sami uvidíte, serverové události v ASP.NET jsou z hlediska použité infrastruktury zcela transparentní a plně funkční ve všech prohlížečích podporujících javascript.

Typy serverových událostí

Serverové události je možné rozdělit na dva základní typy. Události prvního typu jsou vyvolány, pokud se změní stav serverového ovládacího prvku. Například standardní textbox má událost TextChanged, jež je vyvolána při změně textu. Druhým typem události jsou „akční“ události, které nám dovolují reagovat na požadavek uživatele. Příkladem je tlačítko ze standardních ovládacích prvků a jeho událost Click.

Oba typy událostí jsou vyvolány při takzvaném postbacku. Termín postback se používá pro odeslání WWW formuláře pomocí metody POST. ASP.NET umožňuje serverovým ovládacím prvkům podílet se na zpracování dat odeslaných z WWW formuláře.

Události informující o změně stavu prvku

Pro zpracování prvního typu událostí musí serverový ovládací prvek implemetovat rozhraní IPostBackDataHandler. Rozhraní IPostBackDataHandler obsahuje dvě metody. Metoda LoadPostData je volána vždy, když dojde k postbacku a dovoluje nám aktualizovat hodnoty vlastností serverového ovládacího prvku daty z WWW formuláře. Metoda má následující signaturu:

bool LoadPostData(string postDataKey, NameValueCollection postCollection);

V argumentu postDataKey je předán unikátní identifikátor našeho prvku. Identifikátor můžeme použít při vybírání hodnoty z  kolekce postCollection. Argument postCollection obsahuje všechna data odeslaná z WWW formuláře. Návratovým typem metody je typ bool. Metoda vrací true, pokud se stav prvku změnil a je nutné vyvolat příslušnou událost. Samozřejmě, když se stav prvku nezměnil nebo žádnou událost informující o změně vyvolávat nechceme, z metody vrátíme false.

Pouze pokud z metody LoadPostData byla vrácena hodnota true, je ASP.NET runtimem volána další metoda z rozhraní IPostBackDataHandler s názvem RaisePostDataChangedEvent. V této metodě dojde k vyvolání patřičné události. Metoda RaisePostDataChangedEvent vypadá takto:

void RaisePostDataChangedEvent();

Jak ale ASP.NET runtime pozná, s jakým identifikátorem má volat metodu LoadPostData? Aby došlo k vyvolání metody, musí serverový ovládací prvek svoji vlastnost UniqueId na klientské straně vykreslit jako HTML atribut name. Při postbacku ASP.NET runtime hledá všechny prvky, jejichž vlastnost UniqueId je shodná s HTML atributem name a pokud takový prvek nalezne, zavolá jeho metodu LoadPostData. Toto je doporučený způsob vyvolání metody LoadPostData. Pokud ale z nějakého důvodu nechceme nebo nemůžeme vlastnost UniqueId mapovat na HTML atribut name, můžeme si účast na zpracování POST dat vynutit voláním metody RegisterRequiresPostback třídy Page.

„Akční“ události

Pokud chceme vyvolávat „akční“ události, musí prvek implementovat rozhraní IPostbackEventHandler. Rozhraní IPostBackEventHandler obsahuje pouze jednu metodu.

void RaisePostBackEvent(string eventArgument);

Metoda RaisePostBackEvent má jeden argument a tím je řetězec, který blíže identifikuje událost, jež má být vyvolána. Tento argument je nenahraditelný v případě, že náš serverový ovládací prvek vyvolává více událostí, protože nám dovoluje události mezi sebou rozlišit. V těle metody RaisePostBackEvent samozřejmě vyvoláme událost i s případnými upřesňujícími parametry. Jak ale zajistíme, že například po stisknutí tlačítka dojde k vyvolání serverové události? Musíme klientskou událost namapovat na serverovou – to provedeme voláním metody GetPostBackEventReference třídy Page, která je přetížena a vrací vždy řetězec, který vyvolá postback. První varianta metody přejímá pouze serverový ovládací prvek, pro kterého má být zajištěno vyvolání události, druhá varianta metody navíc přijímá libovolný řetězec, který je námi zvoleným identifikátorem události.

Žádná alchymie

Co přesně dělá metoda GetPostBackEventReference? Do HTML stránky je vložen speciální skript s názvem __doPostBack, který odešle formulář. Před odesláním formuláře jsou ale navíc dosazeny hodnoty do speciálních „hidden“ polí s názvy __EVENTTARGET a __EVENTARGUMENT. Pole __EVENTTARGET jednoznačně identifikuje zdroj události, protože obsahuje hodnotu vlastnosti UniqueId příslušného serverového ovládacího prvku. Hodnota v poli EVENTARGUMENT odpovídá řetězci, který byl zadán jako druhý argument metody GetPostBackEventReference a který používáme pro rozlišování událostí. Při postbacku si ASP.NET runtime hodnoty z „hidden“ polí „přečte“ a vyvolá metodu RaisePostBackEvent serverového ovládacího prvku, ve které, jak jsme již řekli, dojde k vyvolání serverové události. Tím je mapování klientských událostí na serverovové dokončeno. Jak sami vidíte, žádná magie mezi Internet Explorerem a a ASP.Net runtimem se nekoná a využit je pouze javascript a „hidden“ pole, tedy zcela standardní možnosti webu.

Opět, pokud z jakéhokoli důvodu nechcete používat metodu GetPostBackEventReference, můžete si vynutit vyvolání metody RaisePostBackEvent pro určitý serverový ovládací prvek tím, že použijete metodu RegisterRequiresRaiseEvent třídy Page.

Pořadí, v jakém jsou události volány

Změnové události jsou vyvolány vždy jako první, teprve potom jsou vyvolány „akční“ události. Předchozí věta vyjadřuje jediné pravidlo, na které se můžete spolehnout. Pořadí, v jakém budou vyvolávány jednotlivé změnové a „akční“ události, není určeno a nelze se tedy spoléhat na to, že například „akční“ událost A je vždy volána před „akční“ událostí B!

Příklad

V příkladu jsou ukázány oba typy událostí (zdrojový kód). Vzniklý serverový ovládací prvek není sám o sobě příliš užitečný, ale názorně ukazuje, jak události vytvářet. Prvek zobrazuje textové pole a tlačítko. Při změně textu v textovém poli je vyvolána změnová událost Change. Po kliknutí na tlačítko je vyvolána „akční“ událost Click.

Vytvoříme třídu SampleEventsControl, která dědí z třídy WebControl a implementuje rozhraní IPostBackDataHandler a IPostBackEventHandler.

[DefaultEvent(„Click“),
DefaultProperty(„Text“),
ToolboxData(„<{0}:SampleEventsControl runat=server></{0}:SampleEventsControl>“)] public class SampleEventsControl : System.Web.UI.WebControls.WebControl, IPostBackDataHandler, IPostBackEventHandler
{

}

Metaatribut DefaultEvent, který ještě neznáme, informuje RAD designéry, že výchozí událostí pro náš prvek je událost Click.

Dále nadeklarujeme události, které náš serverový ovládací prvek poskytuje. Jedná se o události Click a Change. Obě události jsou realizovány standardním delegátem s názvem EventHandler.

public event EventHandler Click;
public event EventHandler Change;

Prvek má vlastnosti TextBoxText a Text. Pokud vlastnost TextBoxText uživatel změní, je vyvolána událost Change. Vlastnost Text je vykreslena jako textový obsah elementu Button. Implementace vlastností byla podrobně popsána v předchozí části seriálu, a proto ji nyní nebudu znovu uvádět a rozebírat.

Prvek dále implementuje metodu LoadPostData. V ní zkontroluje, zda uživatel změnil text v textovém poli. Pokud ano, vrátí z metody true, čímž signalizuje, že chce vyvolat změnovou událost Change .

bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection)
{
  //Hodnota z WWW formuláře
  string newValue = postCollection[postDataKey];
  //Předchozí hodnota
  string oldValue = TextBoxText;
  //Pokud se text změnil, chceme vyvolat událost Change
  if (newValue != oldValue)
  {
    TextBoxText=newValue;
    return true;
  }
  else
    return false;
}

Implementace metody RaisePostDataChangedEvent je jednoduchá, metoda pouze požádá o vyvolání události Change.

Prvek také implementuje metodu RaisePostBackEvent z rozhraní IPostBackEventHandler. Implementace je opět jednoduchá, metoda požádá o vyvolání události Click.

V metodě RenderContents vykreslíme textové pole a tlačítko. HTML atribut name textového pole je vyplněn hodnotou vlastnosti UniqueId serverového ovládacího prvku, čímž zaručíme, že ASP.NET runtime bude volat metodu LoadPostData. Html atribut onclick tlačítka je vyplněn hodnotou vrácenou z metody GetPostBackEventReference. Jak již víme, tato metoda zaručí, že po kliknutí na tlačítko bude proveden postback a my poté můžeme vyvolat serverovou událost Click.

protected override void RenderContents (HtmlTextWriter writer)
{
  writer.AddAttribute(HtmlTextWriterAttribute.Type,“text“);
  //Html atribut name má hodnotu vlastnosti UniqueId, aby ASP.NET runtime volal metodu LoadPostData
  writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
  writer.AddAttribute(HtmlTextWriterAttribute.Value, this.TextBoxText);
  writer.RenderBeginTag(HtmlTextWriterTag.Input);
  writer.RenderEndTag();
  writer.WriteFullBeginTag(„br/“);
  writer.WriteFullBeginTag(„br/“);
  //Mapování klientské události Onclick na sreverovou Click
  writer.AddAttribute(HtmlTextWriterAttribute.Onclick, Page.GetPostBackEventReference(this));
  writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID + „_button“);
  writer.RenderBeginTag(HtmlTextWriterTag.Button);
  writer.Write(this.Text);
  writer.RenderEndTag();
}

Chráněné metody odpovědné za vyvolání událostí jsou zcela v souladu s návrhovým vzorem pro událostní model v .Net Frameworku.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Předchozí článek industrialstudio.cz
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *