AJAX Control Toolkit –
DropDownExtender
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=7d583c4f-562b-49d7-b435-73e97df628af vagy
http://cid-8dcaf3b0da4fb828.skydrive.live.com/embedrowdetail.aspx/ACTsorozat/ACT|_XI|_DropDownExtender.zip
Ezen a héten a DropDown Extenderrel ismerkedünk meg, amely szinte bármely ASP.NET-es vezérlőhöz hozzárendelhető, és egy SharePoint stílusú legördülő listás menüt tudunk vele megvalósítani. (Hát valahogy eddig megvoltunk e nélkül is…)
DropDownExtender használata
Ahhoz, hogy használni tudjuk ezt a vezérlőt, két dologra van szükségünk. Egy vezérlőre, amit ki akarunk bővíteni, illetve egy Panelra, ami majd le fog gördülni. Vegyük észre, hogy ez a DropDownExtender jóval univerzálisabb annál, minthogy csak SharePoint-féle legördülő listás menüket készítsünk vele. A Panelbe bármit elhelyezhetünk, sőt akár a Panel helyett is választhatunk más vezérlőt, így tehát igazándiból egy olyan kiegészítést kapunk, amely azt eredményezi, hogy ha az adott vezérlőre jobb vagy bal egér gombbal kattintunk, akkor megjelenik alatta egy másik vezérlő a jobb alsó sarkában.
Mi most az egyszerűség kedvéért egy SharePoint-os legördülő menüt fogunk megvalósítani! Húzzunk a formunkra egy Label-t és egy Panel vezérlőt, a Panel-en belül pedig helyezzünk el egymás alatt 4db LinkButton-t. Mindegyik LinkButton Click eseményéhez a Selection metódust rendeljük. Íme a Selection eljárásunk:
protected void Selection(object sender, EventArgs e)
{
string size = ((LinkButton)sender).Text;
lbl_sample.Text = String.Format("<{0}> Minta szöveg </{0}>", size);
}
Az alábbi pár változtatást végezzük el a vezérlőkön:
– lbl_target.Text = Kérlek válassz betűméretet:
– LinkButton1.Text = H1 … LinkButton4.Text = H4; LinkButtoni.ID = Optioni
Hogy ténylegesen Sharepoint-hoz hasonló megjelenést tudjuk kölcsönözni a vezérlőinknek, néhány stílusbeállítást el kell követnünk (pl.: SharePoint betűk: Tahoma 11px). A példaalkalmazásban felhasznált stílusosztályokat most nem részletezném, a letölthető tömörített állomány úgyis tartalmazza az adott stíluslapot.
Nézzük meg, hol is tartunk most markup ügyileg:
<asp:Label ID="lbl_target" runat="server" Text="Kérlek válassz betűméretet:" CssClass="ContectMain" Width="300px" />
<asp:Panel ID="pnl_drop" runat="server" CssClass="ContextMenuPanel" Style="display :none; visibility: hidden;">
<asp:LinkButton runat="server" ID="Option1" Text="H1" CssClass="ContextMenuItem" OnClick="Selection" />
<asp:LinkButton runat="server" ID="Option2" Text="H2" CssClass="ContextMenuItem" OnClick="Selection" />
<asp:LinkButton runat="server" ID="Option3" Text="H3" CssClass="ContextMenuItem" OnClick="Selection" />
<asp:LinkButton runat="server" ID="Option4" Text="H4" CssClass="ContextMenuItem" OnClick="Selection" />
</asp:Panel>
A Panel-t azért rejtjük le stílus beállítások segítségével is, mert különben villanna egyet az oldal betöltődéskor. Alapból egy Java script rejti el a Panelt automatikusan, ami viszont csak azután fut le, hogy letöltődött az oldal.
Még két dolgot kell megvalósítanunk, ahhoz működjön a programunk. Először is kell egy DDE, amit az alábbi módon konfiguráljunk be:
<ajaxToolkit:DropDownExtender ID="DDE_1" runat="server"
TargetControlID="lbl_target"
DropDownControlID="pnl_drop" />
A DropDownControlID által meghatározott vezérlő fog legördülni, ami ugyebár nem csak Panel vezérlő lehet, hanem bármi más is, akár még egy UserControl is!
A másik dolog, amit még létre kell hoznunk: az lbl_sample. Ebben akarjuk megjeleníteni a kiválasztott menüelem nagyságú minta szöveget. Ehhez egy UpdatePanel-t is igénybe veszünk, hogy ne frissüljön a teljes oldal, hanemcsak a címkénk. Fontos, hogy a mind a 4 aszinkron trigger-t beállítsuk. Íme a kódunk:
<asp:UpdatePanel ID="UP_1" runat="server">
<ContentTemplate>
<asp:Label ID="lbl_sample" runat="server" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Option1" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="Option2" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="Option3" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="Option4" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
És készen is vagyunk!
Néhány érdekesség
Ez az extender is azon vezérlők közé tartozik, melyekhez lehet animációt rendelni. Értelemszerűen a legördülő objektumra vonatkozóan (OnShow – OnHide). Az érdekessége a dolognak az, hogy az SDK-ban is ajánlott, HideAction animációs tag-et, egyedül nem lehet használni, kell mellé egy másik animáció is. Azt gondolnánk, hogy ilyenkor a HideAction-t, illetve valamilyen egyéb animációt Parallel (párhuzamos lejátszás) tagek közé téve működni is fog. Mily meglepő, nem a várt hatás fogad majd minket. Ennek oka az, hogy a <HideAction Visible= true (|false)> animáció nem képes párhuzamosan futni más animációkkal, ezért utánuk fog csak lefutni. Így például, ha fade-eléssel szeretnénk egy kicsit javítani az megjelenítésen, akkor azt az alábbi módon tehetjük meg:
<Animations>
<OnShow>
<Sequence>
<HideAction Visible="true" />
<FadeIn duration="1" Fps="25" />
</Sequence>
</OnShow>
<OnHide>
<Sequence>
<HideAction Visible="false" />
<FadeOut duration="1" Fps="25" />
</Sequence>
</OnHide>
</Animations>
A másik érdekes dolog számomra ennél a vezérlőnél az volt, hogy egy bizonyos tulajdonságcsoportról, sehol-semmilyen leírást nem lehet találni. Ez a tulajdonságcsoport a dynamic, vagyis a dinamikus szövegkörnyezet generálás. Ez az ACT-nél megszokott módon történik, vagyis webszolgáltatás segítségével (erre a tulajdonságok nevéből rá lehet jönni). Az igazi probléma itt az volt, hogy a webmetódusok paraméterlistája szigorúan kötött. Ezt a listát eléggé nehezen, de végül is sikerült megtalálnom (reflector-nak köszönhetően).
A paraméterlistát úgy sikerült megtudom, hogy a DropDownDesign osztályban nézelődtem, aminek egyetlen egy Delegate-je van összesen:
private delegate string GetDynamicContent(string contextKey)
Ebből pedig már egyértelművé vált, hogy egy string-et visszaadó függvényről van szó, ahol a contextKey paraméter elhagyható. A contextKey arra való különben, hogy ha több DDE vezérlőnk van, és ezek legördülő elemeit egyetlen egy webmetódussal szeretnénk dinamikusan generáltatni, akkor a contextKey-ben kapott szöveg alapján (ezt mi állítjuk be a DynamicContextKey-en keresztül) tudjuk azonosítani a hívó objektumot.
További érdekessége a dolognak, hogy html tageket is tartalmazhat a visszaadott string, amiket képes utána értelmezni a DDE. Sőt nemcsak stringet adhatunk vissza, hanem akár string tömböt is, de ilyenkor az elemeket egymástól vesszővel választja el a rendszer.
Íme egy nagyon egyszerű példa:
<asp:Calendar ID="calendar_with_menu" runat="server"></asp:Calendar>
<asp:Panel ID="pnl_dynamic_menu" runat="server" CssClass="ContextMenuPanel" Style="display :none; visibility: hidden;">
</asp:Panel>
<ajaxToolkit:DropDownExtender ID="DDE_2" runat="server"
TargetControlID=" calendar_with_menu"
DropDownControlID="pnl_dynamic_menu"
DynamicServicePath="WebService.asmx"
DynamicServiceMethod="GetContextMenu"
DynamicContextKey="bármi"
CacheDynamicResults="true" >
</ajaxToolkit:DropDownExtender>
[WebMethod]
public string[] GetContextMenu(string contextKey)
{
List<string> result = new List<string>();
result.Add("1. elem<hr width=’100′>");
result.Add("Bejövő param:" + contextKey);
result.Add("<br>Harmadik<br>");
result.Add("<a href=’Default.aspx’ class=’ContextMenuItem’>(4) – Egy Link</a>");
return result.ToArray();
}
Egy fontos dolog még, ha nem állítjuk be a DynamicControlID tulajdonságot (ami azt szabja meg mely, vezérlőt töltsön fel adattal a webservice), akkor a DropDownControlID-ben megadott vezérlőt állítja be DynamicControlID-nak! (OnPreRender metóduson belül)
Természetesen akár az alap Hello World-öt is megadhatjuk webmetódusként, hiszen annak a szintakszisa is megfelelő!