Monthly Archives: February 2007

Action XML-Scriptben

Korábban már írtam az ASP.NET AJAX-ban található actionökről, mégpedig az újraküldés figyelése kapcsán. Az ott bemutatott megoldás az ASP.NET AJAX Control Toolkiten alapult, így szerver oldali kontrollokat és logikát tételezett fel.

Jó hír, hogy van lehetőség actionök használatára a kliens oldalon, ehhez azonban az ASP.NET AJAX Futures CTP-re lesz szükségünk. Telepítsük fel, majd hozzunk létre Visual Studioban egy ASP.NET AJAX CTP-Enabled Web Site-ot. Váltsunk át markup nézetbe a Default.aspx-en, majd adjunk az oldalhoz egy kliens oldali gombot és egy SPAN elemet, valahogy így:

    <span id="lblResult">Egy egy SPAN, itt jelenik majd meg az eredmény.</span>
    <input type="button" id="btnChange" value="Változtatás" />

A továbbiakhoz szükség lesz a PreviewScript.js fájlra, ezért módosítsuk a ScriptManagert:

    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Scripts>
            <asp:ScriptReference Assembly="Microsoft.Web.Preview" Name="PreviewScript.js" />
        </Scripts>
    </asp:ScriptManager>

A formon belül hozzunk létre egy XML-Script blokkot, azon belül pedig egy-egy referenciát a fenti két elemre. A SPAN elérhető a Sys.Preview.UI.Label, az INPUT type="button" pedig a Sys.Preview.UI.Button osztályon keresztül, például így:

  <script type="text/xml-script">
        <page xmlns="http://schemas.microsoft.com/xml-script/2005">
            <components>
                <label id="lblResult" />
                <button id="btnChange">
                </button>
            </components>
        </page>
  </script>        

A button elemet szándékosan üresen hagytam, ide fogjuk ugyanis hozzáadni az eseménykezelőket. A gomb click eseményére szeretnénk reagálni, mégpedig úgy, hogy megváltoztatjuk a cimke szövegét, ami a Label osztály text tulajdonságának köszönhetően gyerekjáték. Ehhez használhatjuk a setPropertyAction akciót:

    <button id="btnChange">
        <click>
            <setPropertyAction target="lblResult" property="text" value="Új szöveg a SPAN-be" />
        </click>
    </button>

Ki lehet próbálni, ennek így működnie kell! Újonnan megszerzett tudásunkkal próbáljuk meg átírni a gomb szövegét is! A fenti módon ez sajnos nem fog sikerülni, mert a Button osztálynak nincs text tulajdonsága, vége a gyereknapnak. Ha valaki tudja, hogy miért nincs, írja meg, én hiányolom!

A jó hír, hogy a setPropertyActionnek – és néhány más akcióknak is – van egy propertyKey tulajdonsága is, amivel nem csak a target osztály property tulajdonságát lehet beállítani value értékre target.property=value formában, hanem a target.property.propertyKey értékét is. Ennyi segítséggel felvértezve már ki is lehet találni a megoldást:

    <setPropertyAction target="btnChange" property="element" 
propertyKey="value" value="Új szöveg a gombra" />

Ez persze így már nem volt nehéz, hiszen a HTML kódból nyilvánvaló, hogy a gomb szövegét az INPUT elemen belül a value tulajdonság határozza meg. De mi van akkor, ha az oldalon egy DIV tartalmát szeretnénk átírni. A kérdés tehát, hogy az alábbi elem megjelenő szövege hogyan módosítható a setPropertyAction segítségével:

    <div id="pnlResult">Ez itt egy DIV, aminek nincs kliens oldali kontroll megfelelője.</div>

A DIV elemhez nem tartozik közvetlenül típusos kliens oldali kontroll a Sys.Preview.UI névtérben, tehát látszólag meg vagyunk lőve. Sebaj, használjuk minden kontrollok ősét, a Sys.UI.Control osztályt és azzal definiáljunk egy referenciát a label és a button tag környékére:

    <control id="pnlResult" />

Érdekesség, hogy a Control osztály nem a Sys.Preview.UI névtérben van. Mivel minden kontroll osztály innen örökli a funkcionalitásának egy részét, érdemes megnézni, hogy az ős mi mindent tud a C:Program FilesMicrosoft ASP.NETASP.NET 2.0 AJAX Extensionsv1.0.61025MicrosoftAjaxLibrarySystem.Web.Extensions1.0.61025.0MicrosoftAjax.debug.js fájlban.

Folytatva a fenti példát hátra van még az, hogy a gombra kattintáskor át kellene írnunk a DIV szövegét. A Control osztálynak sincs text tulajdonsága, de legalább el lehet kérni a burkolt HTML elemet az element tulajdonságon keresztül, és annak már meg lehet változtatni a tartalmát a jól ismert innerHTML tulajdonság átírásával:

    <setPropertyAction target="pnlResult" property="element" 
propertyKey="innerHTML" value="Új szöveg a DIV-re" />

A setPropertyAction csak egy a sokféle akció közül, érdemes megismerkedni a többivel is!

A fenti példa teljes forráskódja letölthető a devPORTALról.

 

Technorati tags: ,
Advertisements

Kattints, de csak egyszer! Action!

Aki készített már adatkezelő weblapot átlagfelhasználók számára, biztosan találkozott már azzal a feladattal, hogy biztosítani kellett, hogy a felhasználó csak egyszer küldhesse el a kitöltött űrlapot feldolgozásra. Az újraküldés figyelésére általánosan fogalmazva két lehetőség van:

  • Újraküldés figyelése szerver oldalon. Ez nagyon kényelmes, szerver oldali programozást biztosít, de nem egyszerű feladat és könnyen előfordulhat, hogy űrlap típusonként más megoldást kell alkalmaznunk. Az újraküldést ellenőrző logika ráadásul látványosan elcsúnyítja az adatok feldolgozását végző kódot.
  • Újraküldés tiltása kliens oldalon. Ez a megoldás lényegesen jobban kezelhető felhasználói felületet eredményez, nehézsége, hogy JavaScriptet kell írni hozzá és persze nem bolondálló a megoldás (nem árt, ha ettől függetlenül ellenőrzünk még egyszer szerver oldalon is).

A jobb felhasználói élmény, a kód újrafelhasználhatósága és a szerver tehermentesítése érdekében sokan választják a második megoldást. A feladat többféleképpen megoldható, nézzünk most egy újkeletű megoldást, használjuk az ASP.NET AJAX Control Toolkitet!

Az egyszerű példa kedvéért korlátuzzuk a feladatot arra, hogy egy gombot kell letiltanunk abban az esetben, ha a felhasználó rákattint. Hozzunk létre egy új AJAX Control Toolkit Web Site típusú projektet Visual Studioban, majd dobjunk a generált Default.aspx oldalra egy TextBox (ID=txtName), egy Label (ID=lblResult) és egy Button (ID=btnGo) kontrollt.

    <asp:TextBox ID="txtName" runat="server">Gipsz Jakab</asp:TextBox>
    <asp:Button ID="btnGo" runat="server" Text="Elküldés" OnClick="btnGo_Click" />
    <asp:Label ID="lblResult" runat="server" />

Írjunk a gombhoz egy rövid eseménykezelőt, amelyben kissé belassítjuk az oldal végrehajtását:

    protected void btnGo_Click( object sender, EventArgs e )
    {
        System.Threading.Thread.Sleep( 5000 );
        this.lblResult.Text += String.Format( "Köszönjük, {0}!", this.txtName.Text );
    }

Az újraküldés elkerülésére használjuk a Control Toolkitben lévő AnimationExtender kontrollt! Dobjunk belőle egy példányt az oldalra és állítsuk be úgy, hogy a gombunk funkcionalitását terjessze ki (TargetControlID="btnGo").

Sajnos a kód többi részét kézzel kell megírnunk, ezért váltsunk át markup forráskód nézetre. Az AnimationExtender tag-en belül hozzünk létre egy Animations elemet, ez fogja tartalmazni az animációkat, majd azon belül egy OnClick elemet – itt lesznek a kattintáskor lefutó animációk:

    <ajaxToolkit:AnimationExtender ID="ae" runat="server" TargetControlID="btnGo">
        <Animations>
            <OnClick>
            </OnClick>
        </Animations>
    </ajaxToolkit:AnimationExtender>

A lehetséges effektusoknak két fajtája létezik a Control Toolkitben:

  • Az animációk valaminek az értékét változtatják egy kezdőállapottól egy végállapotig a megadott időtartam alatt. Ilyen például a mozgatás (Move), az átméretezés (Resize) vagy a halványítás (FadeIn, FadeOut), melyek az Animation ősosztályból származnak.
  • Lényegében az animációk speciális esetének tekinthetők az akciók, melyek az Animationből származó Action osztály gyermekei. Az akciók olyan animációk, amelyek valójában nem is animálnak, hanem egyszerűen csak megtörténnek egy pillanat alatt. Ilyen például egy kontroll elrejtése vagy megjelenítése (Hide), átlátszóságának állítása (Opacity), valamilyen kód futtatása (Script) vagy éppen egy kontroll engedélyezése vagy tiltása (Enable).

A mi célunknak remekül megfelel az utolsóként említett EnableAction, amivel lehet engedélyezni vagy tiltani egy kontrollt. Adjuk hozzá az OnClick elemhez ezt az "animációt":

    <EnableAction Enabled="false" />

A StyleAction segítségével megváltoztathatjuk az adott kontroll stílusát, például elküldés esetén a homokóra egérkurzort rendelhetjük hozzá. Ehhez az alábbi sort kell csak beírnunk az EnableAction elem helyett:

    <StyleAction Attribute="cursor" Value="wait"/>

Hogy még feltűnőbb legyen a felhasználó számára, hogy történik valamit, kattintás esetén még a gomb szövegét is átírhatjuk. Erre elméletben remek lenne a PropertyAnimation, nekem viszont nem sikerült működésre bírnom a januári CTP változattal. Sebaj, legalább megnézhetjük, hogyan használható a ScriptAction! Ebben az esetben nekünk kell megírnunk azt a minimális kódot, ami a feladatot elvégzi, szerencsére használhatjuk a Microsoft AJAX Library metódusait, például a $get segítségével elkérhetünk egy a gombra mutató referenciát:

    <ScriptAction Script="$get('btnGo').value='Türelem...';"/>

Szerencsére alkalmazhatjuk egyszerre mindhárom animációt is, ekkor azonban be kell ágyaznunk őket egy Sequence vagy Parallel elembe, valahogy így:

    <ajaxToolkit:AnimationExtender ID="ae" runat="server" TargetControlID="btnGo">
        <Animations>
            <OnClick>
                <Sequence>
                    <EnableAction Enabled="false" />
                    <StyleAction Attribute="cursor" Value="wait"/>
                    <ScriptAction Script="$get('btnGo').value='Türelem...';"/>
                </Sequence>
            </OnClick>
        </Animations>
    </ajaxToolkit:AnimationExtender>

Hát nem nagyszerű?! Megint nem írtunk egyetlen sornyi JavaScript kódot sem és van egy remélhetőleg cross-browser megoldásunk – annyira az, amennyire az AnimationExtender, tehát éppen eléggé smile_wink!

Mindez nagyon szép, de mi van akkor, ha egy UpdatePanelt szeretnénk frissíteni? Gond egy szál se, akkor használjuk az UpdatePanelAnimationExtender kontrollt, amely szintén az AJAX Control Toolkit része. Ez annyiban más, hogy OnClick helyett OnUpdating és OnUpdated eseményei és elemei vannak, melyek a frissítés előtt és után futnak le. Itt már gondoskodnunk kell arról, hogy az elküldés előtt módosított értékeket a válasz megérkezése után visszaállítsuk, azaz újra engedélyezzük a kontrollt. Ez az EnableAction és a StyleAction esetén nem annyira bonyolult:

    <ajaxToolkit:UpdatePanelAnimationExtender ID="ae" runat="server" TargetControlID="up">
        <Animations>
            <OnUpdating>
                <Sequence>
                    <EnableAction Enabled="false" />
                    <StyleAction Attribute="cursor" Value="wait"/>
                </Sequence>
            </OnUpdating>
            <OnUpdated>
                <Sequence>
                    <EnableAction Enabled="true" />
                    <StyleAction Attribute="cursor" Value="hand"/>
                </Sequence>
            </OnUpdated>
        </Animations>
    </ajaxToolkit:UpdatePanelAnimationExtender>

A gond a gomb kezelésénél van. Először is az UpdatePanelAnimationExtender az UpdatePanel vezérlőt terjeszti ki (lásd fent TargetControlID="up"), nem a gombot. Tehát ha a gomb szövegét akarjuk megváltoztatni, akkor vagy az AnimationTarget tulajdonságot kell használnunk, vagy ésszel kell megírnunk a ScriptActiont. Az utóbbi esetben az jelenti a nehézséget, hogy elküldés előtt el kell tárolnunk a gomb eredeti szövegét, amit majd vissza kell állítanunk a válasz megérkezése után. Ehhez használjuk az extender BehaviorID tulajdonságát, amiről a dokumentáció mindössze ennyit ír:

BehaviorID: In cases where you would like to access the client-side behavior for your extender from script code in the client, you can set this BehaviorID to simplify the process.

Ezt felhasználva a teljes kontroll felparaméterezve így fest:

    <ajaxToolkit:UpdatePanelAnimationExtender ID="ae" BehaviorID="animation" 
runat="server" TargetControlID="up"> <Animations> <OnUpdating> <Sequence> <EnableAction Enabled="false" /> <StyleAction Attribute="cursor" Value="wait"/> <ScriptAction Script="var a = $find('animation');
var b = $get('btnGo');
a._originalText=b.value;
b.value='Türelem...';" />
</Sequence> </OnUpdating> <OnUpdated> <Sequence> <EnableAction Enabled="true" /> <StyleAction Attribute="cursor" Value="hand"/> <ScriptAction Script="$get('btnGo').value=$find('animation')._originalText;"/> </Sequence> </OnUpdated> </Animations> </ajaxToolkit:UpdatePanelAnimationExtender>

Nos, az eredmény talán bonyolultabb, mint azt előtte sejtettük, sőt, talán nem ez a létező legegyszerűbb megoldás, de az biztos, hgoy nem kellett egyetlen sort sem kódolnunk a kliens oldalra és a kód egészen áttekinthető! Az arany középút valószínűleg az EnableAction és az UpdateProgress kontroll használata.

A teljes forráskód letölthető a devPORTAL információtárából, jó kísérletezést!

Technorati tags: ,

ASP.NET AJAX: “Honnan fogom én ezt megtanulni?”

Igen gyakran keresnek meg olyan kérdéssel, hogy ajánljak egy könyvet, ahonnan ezt vagy azt (az éppen szóban forgó) technológiát meg lehet tanulni. Fontos, hogy lehetőleg egynél többet ne említsek, mert senkinek nincs ideje sokszáz oldalas szakkönyvekből többet is elolvasni. Így volt ez a mai MSDN Kompetenciák Egyetemének szünetében SQL Server kapcsán, és így volt a tegnapi előadásom után az ASP.NET AJAX-szal kapcsolatban is.

A helyzet az, hogy még soha nem fordult elő, hogy röviden tudtam volna azt válaszolni, hogy itt ez a remekmű, tessék, benne van minden. Annak idején, amikor a .NET 1.1-ről nekiláttunk megírni az azóta gyakran csak "Albert István féle fekete .NET biblia"-ként emlegetett könyvet, még volt ilyen ambíciónk, személy szerint bennem ez azóta teljesen szertefoszlott: a technológiák önmagukban is összetettek, sokrétűek, ráadásul összefüggenek egymással. Ma már szinte nincs alkalmazás adatbázis nélkül, tehát nem elég ismerni teszem azt a C#-ot, bizony konyítani kell az SQL-hez is. Ha webalkalmazásról van szó, akkor pedig nem elég az ASP.NET, tudni kell, hogy alul a csupasz HTTP van a maga kérés-válasz modelljével, a kliens oldalon pedig nem tud más futni, mint JavaScript. Ráadásul a kívánt eredmény eléréséhez ezek általában önmagukban nem elegek, együtt kell alkalmazni őket.

Az ASP.NET AJAX kapcsán például a következő három könyv került a kezembe:

Mindhárom könyvről elmondhatom, hogy nagyon jó kiindulópont lehet az AJAX megismeréséhez, ugyanis onnan indulnak, hogy mi kell egy aszinkron weboldalhoz, mi az az XmlHttpRequest, hogyan használható az XML böngészőben és persze ismertetik a JavaScriptet is, majd rátérnek az Atlasra. Kétségkívül van átfedés a három könyv között, és persze van különbség a téma feldolgozásában is. Mégis mindháromról elmondható, hogy nem adnak életképes tudást, ugyanis a termék béta verziójához készültek. Azóta átneveztek szinte mindent, és megszületett az ASP.NET AJAX Futures CTP is. Hogy csak egy példát mondjak, a Microsoft AJAX Library-ről szóló fejezetekből inkább ihletet tudtam meríteni, mintsem a példákat használni.

A hasonló helyzetek elkerülése érdekében a leggyakoribb, visszatérő problémák:

1. A Futures CTP megjelenése miatt született egy Sys.Preview névtér, és a legtöbb kliens oldali kontroll egyelőre ebben található meg. Honnan lehet megtudni, hogy melyik hol van? Ne féljünk belenézni a PreviewScript fájl debug változatába, onnan sok minden kiderül. (A teljes útvonal, kéretik fejből tudni: C:Program FilesMicrosoft ASP.NETASP.NET 2.0 AJAX Futures January CTPv1.0.61025ScriptLibraryMicrosoft.Web.Preview1.0.61025.0Microsoft.Web.Resources.ScriptLibrary.PreviewScript.debug.js) Például, ha a Button osztályt keressük, a fájl megnyitása után keressünk rá a ".Button" kifejezésre, és azonnal kiderül, hogy a Sys.Preview.UI névtérben található. Ezzel szemben az ős Control osztály a Sys.UI névtérben van – egyelőre.

2. Sok tulajdonság megszűnt (legalábbis átmenetileg). Több cikk ír például a checkbox enabled tulajdonságáról. Nyissuk meg a fenti fájlt, keressünk rá arra, hogy ".CheckBox", majd görgessünk le addig a sorig, amely úgy kezdődik, hogy "Sys.Preview.UI.CheckBox.prototype", itt található ugyanis az osztály legtömörebb leírása. Enablednek semmi nyoma. Nosza nézzük meg az ősosztályt! Ha lejjebb tekerünk 25 sorral, ezt találjuk:

    Sys.Preview.UI.CheckBox.registerClass('Sys.Preview.UI.CheckBox', Sys.UI.Control);

Ebből látszik, hogy a Control az ős, de annak is csak visible tulajdonsága van, noha az enabled szerintem sokkal hasznosabb lenne. Reméljük egyszer azért visszakapjuk. Másik gyakori eset, hogy a Select osztályt ma például Selectornak hívják, aki nem hiszi, járjon utána!

3. Máshogy kell hivatkozni a szkriptekre a ScriptManagerben. Már nem kell kiírni a teljes névteret, elég a script nevét megadni, valahogy így:

    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Scripts>
            <asp:ScriptReference Assembly="Microsoft.Web.Preview" Name="PreviewScript.js" />
        </Scripts>
    </asp:ScriptManager>

Ha nincs $get függvényünk sem, vagy az alábbi függvényhívás nem dob fel egy alert ablakot automatikusan az oldal betöltése után, gyanakodhatunk erre a hibára:

    function pageLoad()
    {
        Sys.Preview.UI.Window.messageBox( "Az oldal inicializálása befejeződött." );
    }

4. Szerver oldalon is megjelent egy preview névtér, a Microsoft.Web.Preview, ami a hasonló nevű DLL-ben található. De a korábbi Microsoft.Web ma már System.Web, hogy jobban illeszkedjen az ASP.NET-hez, így például az UpdatePanel a System.Web.UI névtérben van, mint a Control és a Page osztály, csak éppen a System.Web.Extensions.dll-ben, ami azonban nem a C:WINDOWSMicrosoft.NETFrameworkv2.0.50727, hanem a C:Program FilesMicrosoft ASP.NETASP.NET 2.0 AJAX Extensionsv1.0.61025 mappában lelhető meg (és persze a GAC-ban).

Mindez csak ízelítő, hiszen sok helyen nem csak, hogy a szintakszis más, de egy adott probléma megoldásához elindulni is máshonnan kell, mint ahogyan az a könyvben szerepel. Sajnos ez az egyetlen lehetőség van arra, hogy a termék megjelenéséhez időben minél közelebb a polcokra kerülhessen egy könyv. Nem lehet hónapokat várni, hiszen addigra jön egy újabb verzió, vagy ha nem, a konkurencia biztosan.

Röviden: ebben a szakmában a hagyományos szakirodalom napjai meg vannak számlálva. Van, aki ezt már akkor megérezte, amikor nyilvánvalóvá vált, hogy a Pascalhoz még elég volt egy könyv, de ma már MSDN nélkül nem lehet fejleszteni.

De akkor hogyan, honnan? Úgy tűnik, hogy a legdinamikusabb és legbőségesebb (és persze legkevésbé ellenőrzött) forrás kétségkívül az internet: cikkek, blogok, folyóiratok. Na de kinek van ideje mindezt végigolvasni? Vegyük a mostani konferencia esetét: Dávid Zoltán, Gincsai Gábor, Kereskényi Róbert és Virág András kollégáimmal együtt hosszú heteket áldoztunk arra, hogy az a tartalom, amit a résztvevők láttak (láttatok) így összeálljon. A fent említett könyveken kívül – kis túlzással – szinte mindent elolvastunk, ami az adott témában az interneten rendelkezésre áll, azokat kipróbáltuk, hogy bennünk olyan szinten álljanak össze az ismeretek, hogy azt már megemésztve, rendszerezve tovább tudjuk adni. Nem csak teszt alkalmazásokat készítettünk, hanem bizony éles projektekben is bevetettük az AJAX-ot. A bökkenő csak az, hogy mindez összesítve komoly emberhónapokat jelent, amit nem mindenki engedhet meg magának.

Visszatérve a kezdeti problémához: hogyan lehet a leghatékonyabban elsajátítani egy technológiát, mikor mindenki benne van a napi robotban és sürget a határidő? Csak úgy, hogy előemésztett forrásokkal dolgozik az ember. Aki az önálló tanulást preferálja, ilyen előemésztett forrásként használhatja például a novemberi MSDN konferencia alapján készült .NET 3.0 anyagot a devPORTALon, vagy az ASP.NET 2.0 Induló Készletet, amely remekül megalapozhatja az ASP.NET AJAXos ismereteinket. Aki pedig inkább a csoportos, interaktív tanulást preferálja, annak nem tudok jobbat mondani, mint hogy keressen magának tanfolyamot az adott témában. Sajnos a hivatalos Microsoft tanfolyamok legalább fél évvel a technológia végleges változatának megjelenése után lesznek csak elérhetőek, de lehet olyan céget vagy oktatóközpontot választani, ahol megvan a kompetencia az egyéni, testreszabott tanfolyamhoz, amely a résztvevőkhöz alkalmazkodó szintről indul és olyan tempóban halad, hogy a rendelkezésre álló időt a lehető legjobban kihasználja.

És hogy mi legyen az ASP.NET AJAX-szal? Már töltődnek fel a konferencia előadásai a devPORTALra, lehet csemegézni smile_wink

 

Technorati tags: ,

Új kedvenc: ?? operátor

A .NET Framework 2.0 megjelenésével elérhetővé váltak az ún. nullable típusok, azaz olyan érték típusok, amelyek null értékűek is lehetnek. Ilyen például a Nullable<Int32> vagy Nullable<bool> típus, mely utóbbi három értéket is felvehet, lehet true, false vagy null. Ennek megfelelően nem szerepelhet logikai kifejezésekben, azaz például nem állhat if, for vagy while feltételében. Természetesen lehet bool típusra kasztolni, de előtte nem szabad megfeledkezni a HasValue metódus hívásáról, hiszen null-t nem lehet logikai értékre kasztolni.

A legszebb az egészben, hogy a C#-ban megjelentek nyelvi elemek a nullable típusokhoz kapcsolódóan, így Nullable<bool> helyett elég ennyit írnunk: bool?, a többit a fordító elintézi.

Ez a lehetőség sok helyen egyszerűsítheti az alkalmazásunk logikáját, de bizony itt-ott bonyolíthatja is a kódot, hiszen nem szabad elfelejtkeznünk a null érték ellenőrzéséről. Itt jön a képbe a ?? operátor, amiről az MSDN a következőt írja:

The ?? operator returns the left-hand operand if it is not null, or else it returns the right operand.

Hohó, de hisz erre nagyon gyakran van szükség! Gondoljuk csak végig, egy webalkalmazásban hányszor írunk olyan kódot, amelyben ellenőrizzük, hogy a Session, a Cache, a ViewState, a QueryString vagy valamelyik más szótár típusú gyűjtemény egyik eleme tartalmaz-e értéket vagy sem! Biztosan írtunk már valami hasonlót (akár az as operátor használatával):

    object name = this.Session[ "nev" ];

    if( name != null )
    {
        this.lblResult.Text = name.ToString();
    }
    else
    {
        this.lblResult.Text = "Nincs adat!";
    }

A ?? operátor segítségével mindez ennyire rövidül le:

    this.lblResult.Text = (string) ( this.Session[ "nev" ] ?? "Nincs adat" );

Vagy akinek így jobban tetszik:

    this.lblResult.Text = ( this.Session[ "nev" ] ?? "Nincs adat" ).ToString();

Egy másik példa integerrel:

    int age = (int) ( this.Session[ "kor" ] ?? 0 );

Hát nem csodálatos?! Szerintem sokkal tisztábban látszik, hogy csak a null érték kezelését akarjuk megoldani. Persze először nehéz megszokni, hogy hogy is kell mindezt olvasni, de ahogy túltettük magunkat a ?: operátoron, úgy egyszer majd ezen sem fogunk fennakadni…

 

Technorati tags: , ,

Offtopic: Ragtime, dixieland, jazz, blues, swing

Bár sokan a bloggolást a személyes naplóírás modern verziójának tekintik, én ezt a blogot szándékozom szinte kizárólag szakmai tartalommal megtölteni. Feltűnt azonban, hogy a szakmai kapcsolatokon keresztül megismert kollégák közül is többeket érdekelnek a címben megfogalmazott zenei stílusok, így talán ez a téma is szélesebb körű közérdeklődésre tarthat számot. (A hasonló jellegű bejegyzéseknek létrehoztam egy Nem szakmai kategóriát.)

Bohém Ragtime és Jazz Fesztivál 2007. Fóti Marcell jóvoltából múlt szombaton volt szerencsém a Zeneakadémián meghallgatni a Jazztörténeti kalandozások: Ragtime-tól a swing-ig című koncertet. Az est két fő fellépője az Ittzés Tamás vezette kecskeméti Bohém Ragtime Jazz Band és a szegedi Molnár Gyula vezette Molnár Dixieland Band volt. Bevallom, nem ismertem őket korábban, – talán mivel nem fővárosi zenekarok, – noha a kecskeméti "Bohém" Ragtime és Jazz Fesztivál neve ismerősen csengett a fülemben. Sajnos nem értek annyira a zenéhez, hogy meg tudjam ítélni, mennyire jól vagy pontosan játszottak, de a koncert és az este mindenképpen nagyon szórakoztató és élvezetes volt! Külön tetszett, hogy nem csak zene szólt, hanem a műfaj kialakulásának történetéről is megtudhattunk sok mindent. Mindkét zenekart csak ajánlani tudom és a magam részéről biztosan utána fogok nézni, hogy a kecskeméti fesztivál március 23. és 25. között milyen programokat kínál!

Meg kell említenem a meghívott vendégzenekart, a szegedi jambay dobosokat (aki tudja az oldaluk címét, írja meg, kérem). Aki már hallott dob zenekart játszani, legyen az afrikai jambay dob, taiKo vagy éppen a Stomp, biztosan tudja, hogy az extázis kifejezés egyáltalán nem túlzás, akár a hallgatóságról, akár a dobosokról beszélünk. Korábban volt már alkalmam jambay dobon játszani és nyugodtan mondhatom, felejthetetlen élmény még annak is, aki nem ért a zenéhez. (Hogy legyen valami szakmai is: ez egy bináris hangszer, két hang van rajta, egy magas és egy mély és mindössze a tenyered kell hozzá, hogy megszólaltasd clap) Nem véletlen, hogy létezik olyan cég-zenekar a világon, akik a team building eszközeként használják ezt az egyszerű hangszert.

Ha pedig swingről van szó és jó muzsikáról, akkor az este nem zenei szereplője ki más lehetett volna, mint a Jumpers táncegyesület vezetője, Janicsek Gábor és partnere. Jazzt és bluest talán lehet hallgatni egy fotelból, de az igazi swing megmozgatja az ember lábát, arra táncolni kell – mindenkinek a maga módján. Egyre szaporodnak azok a táncegyesületek, ahol már ezt a stílust is el lehet sajátítani, ezek sorában az egyik, vagy AZ első tudomásom szerint Gábor egyesülete volt. A lindy hop semmivel sem egyszerűbb, mint bármely más tánc, de szerintem aránylag hamar el lehet jutni odáig, hogy az alaplépések, a turn, a circle, a charleston, a swing-out és a többiek már örömet okoznak és az ember kimerészkedik a parkettre. Ezt ki kell próbálni!

Összefoglal, az este igazán volt, reméljük a Szervusz Budapest! felütés tényleg több fővárosi koncertet tartogat ezektől a zenekaroktól a jövőben. Aki szintén ott volt a koncerten vagy tud hasonló eseményről, ossza meg gondolatait itt comment formájában! Köszönöm!

 

Technorati tags: , , , ,

XML alapú adatkötés JavaScriptben

Amikor először meghallottam, hogy az ASP.NET AJAX többek között a címben megnevezett szolgáltatást is nyújta, bizony kis híján elment tőle a kedvem: nem vagyok oda sem az XML-ért, sem pedig a JavaScriptért – noha mindkettőnek látom a maga előnyeit bizonyos esetekben. Jobban megismerkedve ezzel a lehetőséggel, egészen barátságos kis jószággá szelídült az a fránya JavaScript.

Kezdjük az elején: az ASP.NET AJAX több részből áll, ezek közül az egyik a Microsoft AJAX Library, amely egy böngésző és szerver független JavaScript osztálykönyvtár. Lényegében azokat a szolgáltatásokat adja, amikre eddig is szükségünk volt, ha a weblapjaink kliens oldali szolgáltatásait akartuk felturbózni: HTML tag-ek elérése és adatok manipulálása. (Ennél persze lényegesen többről van szó.) A funkciók közül sajnos még nincs minden készen, tehát ha valaki meg akar ismerkedni vele, telepítse fel az ASP.NET AJAX Futures CTP-t, majd indítsa el a Visual Studiot és hozzon létre egy új webhelyet, amely támogatja ezt a komponenst. (File – New – Web Site… – ASP.NET AJAX CTP-Enabled Web Site).

Az a kedvencem ebben az osztálykönyvtárban, hogy teljesen elfedi a JavaScript böngészőfüggéseit, ráadásul olyan névtereket és osztályokat tartalmaz, amelyek kísértetiesen hasonlítanak a .NET-es osztályokhoz.

A szükséges kliens oldali JavaScripteket a ScriptManager komponens fogja az oldalba ágyazni, ha megnyitjuk a Default.aspx fájlt Markup nézetben, láthatjuk is benne. Egészítsük ki ezt úgy, hogy a Microsoft.Web.Preview.dll-ben lévő PreviewScript.js is elérhető legyen:

<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Scripts>
        <asp:ScriptReference Assembly="Microsoft.Web.Preview" Name="PreviewScript.js" />
    </Scripts>
</
asp:ScriptManager>

Hello World!

Kezdjük rögtön a Hello World! megírásával. A <HEAD> és </HEAD> közé tegyünk egy üzenetablakot, majd csapjunk a Ctrl-F5-re:

<head runat="server">
    <title>ASP.NET AJAX kliens szkript demó</title>
    <script language="javascript" type="text/javascript">
        function pageLoad()
        {
            Sys.Preview.UI.Window.messageBox( "Az oldal inicializálása befejeződött." );
        }
    </script>
</head>

Aki már írt JavaScriptet, annak két dolog biztosan feltűnt:

1. Nem az alert függvényt használtuk. Ennek az osztálykönyvtárnak a segítségével nem kell a window.alert(), a window.confirm() és a window.prompt() metódusokat használnunk, hanem hívhatjuk a szerver oldalon már megszokott messageBox() és inputBox() függvényeket. Persze a camelCase-re oda kell figyelni, meg a paraméterezés is eltér egy kicsit, sőt, azt a hosszú névteret is ki kell írni, de azért valljuk be, mégis csak barátságosabb smile_sarcastic

2. A második figyelemreméltó dolog, hogy nem kellett feliratkoznunk a BODY onload eseményére. A pageLoad metódus meghívódik automatikusan, ráadásul azután, hogy az ASP.NET AJAX runtime inicializálta magát.

(Megjegyzés: a kódrészletek az ASP.NET AJAX 1.0 2007. januári Futures CTP alapján készültek, a névterek és a metódusok nevei változhatnak a jövőben!)

HTML elemek elérése

A JavaScript és a DOM eltérő implementációjának "köszönhetően", nem azonos módon tudjuk elérni a HTML oldal egyes elemeit kliens oldalon. Magyarul ha hivatkozni szeretnénk egy gombra vagy egy képre, akkor már pusztán ahhoz töb sor kódot kell írnunk, hogy egy referenciát szerezzünk az adott elemre. Na ezt is szépen elfedi előlünk az ASP.NET AJAX. Íme egy példa:

Tegyünk egy szövegdobozt, egy gombot és egy cimkét az oldalra:

    Az Ön neve:
    <input id="txtName" type="text" />
    <input id="btnWelcome" type="button" value="Mondd szia!" onclick="greetMe()" />
    <span id="lblMessage"></span>

A feladat természetesen a szövegdöbözba írt szöveg megjelenítése a cimkében. A megoldást nyújtó greetMe() metódust írhatjuk a HEAD-ben korábban megnyitott SCRIPT elembe:

    function greetMe()
    {
        var txtName = new Sys.Preview.UI.TextBox( $get( "txtName" ) );
        var message = String.format( "Szia, {0}!", txtName.get_text() );
        var lblMessage = new Sys.Preview.UI.Label( $get( "lblMessage" ) );
        lblMessage.set_text( message );
    }

A $get() megkímél minket a document.all és a document.getElementById szörnyektől és lényegesen olvashatóbb kódot eredményez.

A legdurvább az egészben az, hogy mindezt lehet automatizálni, erre szolgál az:

Adatkötés

Ugyanúgy, ahogy szerver oldalon már megszoktuk, adatkötés segítségével összekapcsolhatunk adatforrásokat és kontrollokat. Ezt megtehetjük akár kódból, akár XML-ből, és itt jön a képbe az XML-script. Sok szövegelés helyett próbáljuk ki:

Hozzunk létre egy images nevű mappát és tegyünk bele néhány képet, mondjuk ezeket:

 

Nevezzük el a fájlokat rendre: flag_at.gif, flag_es.gif, flag_fi.gif, flag_gb.gif, flag_hu.gif

Hogy ne keveredjen a művünk az előzővel, hozzunk létre egy új ASPX oldalt és a ScriptManagert a fentiek szerint egészítsük ki. Ezek után adjunk az oldalhoz egy lenyitható listát és egy képet:

    <select id="selCountries" size="6">
        <option value="HU" selected="selected">Magyarország</option>
        <option value="GB">Nagy Britannia</option>
        <option value="FI">Finnország</option>
        <option value="ES">Spanyolország</option>
        <option value="AT">Ausztria</option>
    </select>
    <img src="" id="imgFlag" alt="Zászló" />

A feladat az, hogy a kiválasztott ország zászlóját azonnal jelenítsük meg. Ehhez írhatnánk eseménykezelő kódot, vagy megfogalmazhatnánk az adatkötést a pageLoad() metódusban a Binding osztály segítségével. Ehelyett inkább tegyük meg mindezt deklaratívan XML-scriptben:

<head id="Head1" runat="server">
    <title>ASP.NET AJAX adatkötés</title>
    <script type="text/xml-script">
        <page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
            <components>
                <selector id="selCountries" />
                <image id="imgFlag" >
                    <bindings>
                        <binding dataContext="selCountries" dataPath="selectedValue" 
property="imageURL" transform="ToString"
transformerArgument="images/flag_{0}.gif" /> </bindings> </image> </components> </page> </script> </head>

A fontosabb pontok:

  • A selector jelenti a hivatkozást a lenyitható listára, az image pedig a képre.
  • Az adatkötés megfogalmazása WPF stílusban történik, a cél kontrollnál adunk meg mindent, azért van bindings az image tag elett:
    • dataContext: a forrás kontroll
    • dataPath: a forrás kontroll forrás tulajdonsága
    • property: a cél kontroll cél tulajdonsága
    • transform: egy kis adatgyúrás. A ToString gyakorlatilag egy String.Format hívást fog jelenteni, amihez a formátumot bemenő paraméterként adjuk a transformerArgument attribútumban.

És kész, ennyi, működik, ki lehet próbálni!

Természetesen egy elemhez több bindingot is rendelhetünk. Tehetünk például az oldalra egy jelölőnégyzetet és megadhatjuk, hogy a kép csak akkor jelenjen meg, ha a checkboxot a felhasználó bepipálta. Így tegyük az oldalra a kontrollt:

    <input id="chkShow" type="checkbox" checked="CHECKED" /> 
A kiválasztott ország zászlajának megjelenítése:

Az adatkötést pedig így írjuk át:

    <page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
        <components>
            <selector id="selCountries" />
            <checkBox id="chkShow" />
            <image id="imgFlag" >
                <bindings>
                    <binding dataContext="chkShow" dataPath="checked" property="visible" />
                    <binding dataContext="selCountries" dataPath="selectedValue" 
property="imageURL" transform="ToString"
transformerArgument="images/flag_{0}.gif" /> </bindings> </image> </components> </page>

Mit tegyünk akkor, ha pont ez ellenkező irányban szeretnénk használni a checkbox-ot? Mi sem egyszerűbb: használjuk az Invert transformert, ami meginvertálja a boolean értékeket:

<binding dataContext="chkShow" dataPath="checked" property="visible" transform="Invert" />

Ugye, hogy ütős? (Hát még ha majd lesz hozzá designer az Orcas-ban!) És mindez csak ízelítő, aki szeretne jobban megismerkedni a Microsoft AJAX Library lehetőségeivel, annak jó hír, hogy a csütörtök-pénteki MSDN Kompetenciák Egyetemén lesz róla szó részletesen, lehet még regisztrálni!

A cikkhez tartozó teljes forráskód letölthető a devPORTALról.

Technorati tags: ,

Eltűnt Jim Gray

Aki csak egyszer is hallotta a 63 éves Jim Gray valamelyik előadását, kiváltképp, ha személyesen, biztosan nem felejti el egy életre. Olyantehetségű ember, akit nem lehet egyszerűen besorolni a szokásos szervezeti hierarchiába, a Microsoftnál is korábban a distinguished engineer címmel illették, majd később átkerült a még elitebbnek számító technical fellow kategóriába, ahol olyan már-már legendás nevek szerepelnek, mint Mark Russinovich vagy a C#-ot megalkotó Anders Hejlsberg vagy az NT kernel atyjának tartott David Cutler.

Jim Gray adatbázisokkal foglalkozik, elsősorban olyan szolgáltatások mögötti adattárházak létrehozásán fáradozik, amelyek a tudományos életet mozdíthatják előre azáltal, hogy segítenek világszerte megosztani a végtelen mennyiségű kutatói információt. Az ő nevéhez fűződik például a műholdképeket tároló TerraService megalkotása, amely évekkel előzte meg mind a Google, mind pedig a Microsoft hasonló szolgáltatását, de dolgozott még más csillagászati, földrajzi, óceanográfiai, biológiai és orvostudományi területeken is. Csöppet sem túlzás a ráragasztott "data wizard" elnevezés, amit az is jól mutat, hogy munkájáért 1998-ban Turing díjat kapott, amivel megint csak nem sokan büszkélkedhetnek.

Ezen rövid cikk szomorú apropóját az adja, hogy múlt vasárnap vitorlásával együtt nyomtalanul eltűnt San Francisco közelében a tengeren. Tíz évnyi vitorlás tapasztalattal és jól felszerelt hajójával indult útnak és azóta sem érkezett vissza, nem adott le vészjelzést és katasztrófának sem találták semmi nyomát a kutató csoportok, melyek azóta is keresik.

Szorítsunk egy kicsit érte, miközben elolvassuk valamelyik vele készült interjút, vagy megnézzük valamelyik vele készült beszélgetést a Channel9-on.