AJAX Control Toolkit –
DynamicPopulateExtender
Ez egy példaalkalmazáshoz tartozó leírás! Az alkalmazás erről a címről tölthető el:
http://www.devportal.hu/portal/Detailed.aspx?NewsId=ee62366d-0b1d-4ba2-bc7e-0febaad87391 vagy
http://cid-8dcaf3b0da4fb828.skydrive.live.com/embedrowdetail.aspx/ACTsorozat/ACT|_XIII|_DynamicPopulateExtender.zip
Ebben a cikkben a DynamicPopulateExtender-rel ismerkedünk meg, ami leginkább az UpdatePanel + UpdateProgress vezérlők összegyúrására hasonlít!
DynamicPopulateExtender alapok
A DPE nagy vonalakban arra való, hogy aszinkron kérések segítségével ki tudjuk cserélni az oldalunk egy bizonyos markup részét, egy WebService vagy egy Script által visszaadott HTML markuppal. Ehhez mindösszesen 3 dologra van szükségünk. Egy vezérlőre, amelynek az egyik eseményéhez egy trigger-t (kioldó-t) rendelhetünk. Fontos, és jegyezzük is meg, hogy csak olyan HTML vezérlőt használhatunk erre a célra, amely nem generál automatikusan Postback-et. Tehát az ASP.NET-es button, linkbutton nem jó, sőt a „sima” html-es submit se! Az <input type="button" viszont már igen, ha mindenféleképpen gombhoz ragaszkodunk. (Mint ahogy fentebb is szó volt róla, bármilyen olyan HTML vezérlőhöz kapcsolható trigger, ami nem generál postbacket, tehát a radiobutton, checkbox, stb. is jó (lentebb látunk majd ezekre is egy példát!)).
A másik vezérlő, amire feltétlenül szükségünk van, az egy konténervezérlő, amelynek a tartalmát tudjuk kicserélni. Tehát nem egy vezérlő markup-ját tudjuk kicserélni, hanem a vezérlőn belül eltárolt szöveget! Így az alábbi pár vezérlő használható konténerként: Panel, Label (Repeater/DataList – ezeket nem volt időm kipróbálni, de állítólag működik velük is!)
A harmadik dolog, amire szükségünk van egy DPE és egy hozzátartozó script vagy webservice, ami generálja a kódot. Nézzünk is, egyből két példát a DynamicPopulate használatára!
DynamicPopulateExtender használata
Egy egyszerű példa
Most egy olyan alkalmazást fogunk elkészíteni, ami egy címke szövegét cseréli le postback nélkül. (A stílusosztályok, melyekre hivatkozok a kódokban, a letölthető példaalkalmazásban megtalálhatóak!) Lássunk is neki!
Először is szükségünk lesz egy HTML button vezérlő, NEM Submit-ra, hanem sima button-re. Ezek után, kell még nekünk egy Label vezérlő és egy DPE. Állítsuk be őket az alábbi módon:
<input id="btn" type="button" value="Kattanj rám" runat="server" /><br/>
<asp:Label ID="lbl_container" runat="server">
Alapból beállított szöveg
</asp:Label>
<ajaxToolkit:DynamicPopulateExtender ID="DPE_1" runat="server"
TargetControlID="lbl_container"
PopulateTriggerControlID="btn"
CustomScript="GetMarkup()">
</ajaxToolkit:DynamicPopulateExtender>
A TargetControlID-val azt állíthatjuk be, hogy mely konténervezérlő szövegrészét szeretnénk majd lecseréltetni!
A PopulateTriggerControlID azt a vezérlőt szabja meg, amely default eseményének bekövetkeztekor, végrehajtódjon a markup csere. Jelenestben ez a btn nyomógomb, melynek a click eseményékor hajtódik majd végre a populate trigger.
A CustomScript-nél megadott script hajtódik végre, amikor a trigger kiold. (Fontos, hogy a zárójelek ne maradjanak le a függvény végéről, mert különben a függvény kódja lesz az új markup kód! )
Most már csak annyi dolgunk van, hogy megírjuk a GetMarkup() függvényünket. Egyetlen egy megkötésünk van csak a függvénnyel kapcsolatban, hogy string-gel térjen vissza. Íme egy egyszerű példa a megvalósítására:
<script type="text/jscript">
function GetMarkup()
{
return "<h1>Dinamikusan generált HTML szöveg</h1>";
}
</script>
És készen vagyunk! Futtassuk, nézegessük!
Ha összesen ennyit tudna ez a vezérlő, akkor eléggé rossz pontozást kapnának tőlem az ACT fejlesztői, de szerencsére ennél azért valamivel többre is képes a DPE. Na, lássuk!
Egy kicsit bonyolultabb példa
Egy olyan alkalmazást szeretnénk megvalósítani, ami azt tudja, hogy választókapcsolók segítségével dinamikusan változzon egy Panel szövege. Itt egyből több problémába is belefutunk.
Az első probléma az, hogy több objektumunk is van, amiknél a trigger-nek ki kell oldani, de csak egyetlen egy vezérlőt tudunk megadni a PopulateTriggerControlID tulajdonságánál. Ezt a problémát úgy fogjuk megoldani, hogy mi „kézzel” (java script függvény segítségével) fogjuk kikényszeríteni, hogy kioldjon a trigger.
Ez mind szép és jó, de hogyan fogjuk azonosítani, hogy melyik vezérlő hatására oldott ki a trigger? Eszünk be jut, hogy a többi ACT vezérlőnél erre a problémára a contextKey stringet használtunk. A GetMarkup() függvényünknek adhatunk egy contextKey paramétert, de sajnos automatikusan nem fogja az AJAX rendszer neki átadni a contextKey értékeket. (Ha megnézzük az AjaxControlToolkit\DynamicPopulate\DynamicPopulateBehavior.js fájlt, akkor láthatjuk, hogy tényleg nem passzolja át a rendszer, hanem csak egyszerűen meghívja a CustomScript metódust). Erre a megoldás, a jól bevált WebService barátunk lesz.
Most, hogy a felmerült problémákat orvosoltuk, ideje belefogni az alkalmazás kifejlesztésébe.
Először adjunk az oldalhoz 4db radio típusú HTML input vezérlőt, és állítsuk be őket az alábbi módon: (adjunk az oldalhoz egy Panel-t is!)
<input type="radio" name="rbFormat" id="r1" value=’1′
onclick="CallUpdate(this.value);" checked="checked" /> H1
<input type="radio" name="rbFormat" id="r2" value=’2′
onclick="CallUpdate(this.value);" /> H2
<input type="radio" name="rbFormat" id="r3" value=’3′
onclick="CallUpdate(this.value);" /> H3
<input type="radio" name="rbFormat" id="r4" value=’4′
onclick="CallUpdate(this.value);" /> H4
<asp:Panel ID="pnl_container" runat="server" CssClass="dynamicPopulate_Normal" />
Ami a kódból egyedül magyarázatra szorul az a CallUpdate metódus. Ahhoz, hogy bármilyek radio gomb hatására kioldódjon a trigger, mi nekünk kell kézzel meghívnunk a DPE populate metódusát. Ehhez egy segédmetódust használnunk (a CallUpdate-t), amelynek átadjuk paraméterül a kiválasztott radiobutton értékét, ami ezentúl már contextKey-ként funkcionálni. Nézzük, hogyan is néz ki a CallUpdate metódusunk:
<script type="text/jscript">
function CallUpdate(value)
{
var extender= $find(‘DPE1’);
if (extender)
{
extender.populate(value);
}
}
Sys.Application.add_load(function(){CallUpdate(‘1’);});
</script>
Ez a függvény, akkor fog meghívódni, amikor rákattintunk valamelyik választókapcsolóra, vagyis amikor a kiválasztott elem megváltozik.
Először a rendszertől el kell kérnünk a DynamicPopulateExtender-t (mi a példaalkalmazásban DPE1 azonosítóra kereszteltük el a DPE-nket). Ezt eltároljuk egy extender nevű változóban, majd megvizsgáljuk, hogy létezik-e az objektum. (Ez a vizsgálat, azért került bele a kódba, hogy ha nincs meg a vezérlő, akkor ne dobjon hibát a java script).
Utána meghívjuk az DPE populate metódusát és átadjuk neki paraméterként a contextKey-t.
A CallUpdate function után lévő sor feladata az, hogy az oldal betöltődésekor is kioldódjon a trigger, vagyis kerüljön valamilyen szöveg a panelünkbe már a legelején is.
Adjunk az oldalhoz egy DPE vezérlőt, és az alábbi módon állítsuk be:
<ajaxToolkit:DynamicPopulateExtender ID="DPE1" runat="server"
TargetControlID="pnl_container"
UpdatingCssClass="dynamicPopulate_Updating"
ClearContentsDuringUpdate="true"
PopulateTriggerControlID="pnl_container"
ServiceMethod="GetHTMLCode">
</ajaxToolkit:DynamicPopulateExtender>
Az UpdatingCssClass tulajdonság segítségével, az UpdateProgress-hez hasonló dolgot tudunk megvalósítani, vagyis a HTML content generálás alatt megszabhatjuk, hogy mi jelenjen meg a felhasználónak. Általában egy animált töltés gif-et szokás beállítani háttérként.
A ClearContentsDuringUpdate-tel mindösszesen annyit állíthatunk be, hogy amíg végrehajtódik az aszinkron kérés, addig maradjon-e az „előző” szöveg, vagy törölje a teljes context-et. (alapértelmezetten true)
A ServiceMethod értelemszerűen a webmetódus nevét szabja meg. Azért nincs ServicePath tulajdonságunk, mert a GetHTMLCode-ot az aspx fájlban tároljuk. Íme a kódja:
<script runat="server">
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static string GetHtmlCode(string contextKey){
System.Threading.Thread.Sleep(800);
return String.Format("<h{0}>Minta szöveg</h{0}>",contextKey);
}
</script>
Két fontos dolog:
– Ne felejtsük el egyik attribútumot se, mert különben nem fog működni. (Az első azt mondja meg a rendszer, hogy ő egy webmetódus, a másik pedig, hogy a scriptek számára is elérhető!)
– Csak úgy fog működni a webmetódus, ha static-ra állítjuk a láthatóságát a függvényünket.
Természetesen éles projekt esetén a szálaltatás nem kell, most csak azért van benne, hogy localhost-on is ki tudjuk próbálni, hogy működik-e az UpdateCssClass.