Windows Phone fejlesztés lépésről lépésre

Készült a Microsoft Magyarország megbízásából

Árvai Zoltán – Fár Attila Gergő – Farkas Bálint – Fülöp Dávid – Komjáthy Szabolcs – Turóczy Attila – Velvárt András

Windows Phone fejlesztés lépésről lépésre

Jedlik Oktatási Stúdió Budapest, 2012

A szerzők a könyv írása során törekedtek arra, hogy a leírt tartalom a lehető legpontosabb és naprakész legyen. Ennek ellenére előfordulhatnak hibák, vagy bizonyos információk elavulttá válhattak. A könyvben leírt programkódokat mindenki saját felelősségére alkalmazhatja. Javasoljuk, hogy ezeket ne éles környezetben próbálják ki. A felhasználásból eredő esetleges károkért sem a szerzők, sem a kiadó nem vonható felelősségre. A forráskódok elérhetők a https://devportal.hu/wp7/konyv oldalon keresztül. Az oldalakon előforduló márka- valamint kereskedelmi védjegyek bejegyzőjük tulajdonában állnak.

A könyv vagy annak bármely része, valamint a benne szereplő példák a szerzőkkel kötött megállapodás nélkül nem használhatók fel üzleti célú oktatási tevékenység során! A könyv tudásanyaga államilag finanszírozott közép- és felsőoktatásban, illetve szakmai közösségek oktatásában bármely célra felhasználható.
© 2011 Microsoft. Minden jog fenntartva. A könyv papír alapon megvásárolható a Jedlik Oktatási Stúdió honlapján keresztül: http://joskiado.hu/termek/windows_phone_fejlesztes_lepesrol_lepesre.html

Szerkesztette: Novák István Szakmai lektor: Novák István Anyanyelvi lektor: Dr. Bonhardtné Hoffmann Ildikó Borító: Varga Tamás

Kiadó: Jedlik Oktatási Stúdió Kft. 1215 Budapest, Ív u. 8-12. Internet: http://www.jos.hu E-mail: jos@jos.hu Felelős kiadó: a Jedlik Oktatási Stúdió Kft. ügyvezetője

Nyomta: LAGrade Kft. Felelős vezető: Szutter Lénárd ISBN: 978-615-5012-13-6 Raktári szám: JO-0338

6

Tartalomjegyzék

Tartalomjegyzék
Előszó ............................................................................................................... 13 1. Bevezetés a „Windows Phone” platform-ba .................................................. 15
A Windows Phone Platform ............................................................................................... 15 Windows Phone hardver követelmények........................................................................... 16 A Windows Phone platform képességei ............................................................................ 16 Alkalmazás fejlesztés Silverlight alapokon ....................................................................... 19 Ismerkedés a XAML-lel ..................................................................................................... 19 XAML alapú felhasználói felületek..................................................................................... 21 Hello Windows Phone......................................................................................................... 22 Összefoglalás...................................................................................................................... 26

2. Felhasználói élmény tervezése Windows Phone-on ...................................... 27
A Windows Phone jelenség ............................................................................................... 27 Ikonografikus és infografikus felületek ............................................................................. 28 A METRO Dizájn Nyelv ....................................................................................................... 29 Ismerős megjelenés .......................................................................................................... 29 Tiszta és pehelykönnyű..................................................................................................... 29 Digitális eredetiség ............................................................................................................ 30 Gyönyörű tipográfia ........................................................................................................... 30 Állandóan mozgásban....................................................................................................... 30 A tartalom az elsődleges ................................................................................................... 30 Design vezérelt fejlesztés................................................................................................... 31 Tartalom és információs architektúra ................................................................................ 32 Használhatóság és ergonómia .......................................................................................... 32 Esztétika és vizuális élmény.............................................................................................. 32 Csináld magad! ................................................................................................................... 33 A dizájn szórakoztató! ....................................................................................................... 33 Innováció tervezés közben ................................................................................................ 33 A probléma megértése ...................................................................................................... 33 Magasabb termékminőség ................................................................................................ 33 Tervezés Sketchflow-val ................................................................................................... 34 Élmény vagy alkalmazás .................................................................................................... 35 Ismerjük meg a felhasználóinkat! ...................................................................................... 35 Releváns tartalom ............................................................................................................. 36 Személyes alkalmazások .................................................................................................. 36 Hasznos, jól használható, kívánatos ................................................................................. 36 Gyakorlati Dizájn ................................................................................................................. 36

7

................................................................................................................................... 68 Adatkötés UI-elemek között .............. 106 Példaprogram ................................................ Az alkalmazás életciklusa ................................Mozgás és animáció ... 74 Az alkalmazás állapotainak létrehozása VisualState-ek segítségével .............. 85 A Bing Maps vezérlő használata ... 111 5....................................................................................................................................... 105 Fontosabb vezérlők ..................................................................... 103 Különbségek................................. 39 Érintőképernyős alkalmazások tervezése ... 55 Szövegbeviteli vezérlők ...................................................................................................................................................................................... 85 Feliratkozás a szolgáltatásra ............................................ 104 Silverlight Toolkit for Windows Phone7 ................................................................................................. 44 Parancsvezérlők ................................. 78 Animációk hozzáadása .................. 86 Pushpinek.......................................................................................................................................................................................................... 109 Összefoglalás .................................................................................................................................................................................................................................................................... 105 Telepítés .................................................................................... 97 Oldalak ............................................................................................................................................................................................................................................................................................................................................................................................ 36 Windows Phone 7 specifikus komponensek tervezése ........................................................................................................................................................................ 70 Az adatok megjelenésének testreszabása adatsablonokkal ................................. 58 Listavezérlők .......... 83 Összefoglalás ................................. 41 Összefoglalás ................................ 84 4....... Alkalmazásfejlesztés Windows Phone-on .................................................................................................................................................................................................................................................................................................... 97 Adatátvitel az oldalak között .......................................................................................................................................... 93 Navigáció .............................................................................................................................. 99 BackStack ......................................................................................... 49 Szövegmegjelenítési vezérlők .................................................................................................... 65 Több vezérlő kötése egyazon forráshoz .................................................................................... 113 8 .................................. 62 Adatkötés ............................................................................................................................. 42 3............................................................................................... 72 A vezérlők kinézetének testreszabása vezérlősablonokkal ......................................................... 90 Egyéb szolgáltatások .............. 65 Erőforrások .............................................. Haladó alkalmazásfejlesztés Windows Phone-on ....................................................... 81 Témák használata ................................................................................................................................................ 101 Pivot és Panorama ...................... 89 Rétegek alkalmazása .................................. 100 Az alkalmazás kiegészítése navigációs vezérlőkkel ......... 37 Vezérlők használata ......................................................................................................................................................................................................................................................... 85 Térképek kezelése ................................................. 99 Navigációs metódusok................................................................................................................ 43 Alapvető WP7 vezérlők ..........................................

.................................. 166 A nyers érintési adatok kezelése ........................... 138 Launcherek... 149 Adatok megosztása alkalmazások között .................................................................................................................................... 117 Életciklus-események kezelése ........................................ 137 A példaalkalmazás létrehozása..................... Alapvető telefonos funkciók használata .................................................... 135 6........... 126 Figyelmeztetések és riasztások kezelése.......................................... 145 SearchTask ....................................................................................... 125 Elméleti áttekintés .......................................................................................................................... 179 Az iránytű használata ........................................................................................................Tartalomjegyzék Multitasking ................................................................................. 180 Az érzékelők együttes használata a Motion API segítségével ....................................... 169 Helymeghatározás ..................................... 173 Helyzetmeghatározás .................. 151 Appointments .......................... 132 Adatok letöltése a háttérben....................... 142 PhoneCallTask....................................................................... 114 A multitasking megvalósítása WP 7...................... 146 Chooserek ....... 150 Contacts.................................................................. 142 SmsComposeTask .... 152 Kamera használata taszk nélkül ............................................................................................................................................................................. 144 MediaPlayerLauncher ............................................................................................................................................................ 176 A gyorsulásmérő használata ................................................... 176 A giroszkóp használata .................................. 119 Folyamatok a háttérben ............................................................................................ 133 Összefoglalás................................. 163 Alapvető érintési események .......................................................................................................................... 149 PhotoChooserTask ........................ További telefonos funkciók használata............................................................................ 161 7...................................................................................................................... 163 Multitouch manipulációk .... 183 9 ................................... 163 Az érintőképernyő kezelése .............................................................................................. 148 CameraCaptureTask ................................................................................................................................................................................................................................................................................................................................................................................................................................. 117 Az alkalmazás állapotának mentése és helyreállítása .................................................................................................................................................................................................................................................................................................................................................................................................... 147 PhoneNumberChooserTask ....................................................................................................................................................................................................................................................................................................................................................5 platformon....................................................................... 147 SavePhoneNumberTask .................................................................................................. 113 A feladatütemezés elméletben ...................................... 125 Zenelejátszás integrálása saját alkalmazásokba ........................ 144 WebBrowserTask................................. 153 Összefoglalás............................................................. 115 Állapotok kezelése .......................................................................... 143 EmailComposeTask ........................................................................................................................................................................................................................................................................................................................................................

..................................... 215 9.................................................................................... 246 Méret ..................... 217 Webszolgáltatások használata ........................................................................................ 240 Összefoglalás ............................................................................................................................................................................................................................................................................................ 218 A webszolgáltatások működése................................................................................................................................... 210 Adatok lekérdezése − SELECT ..................................................................................................................................... 210 Adatok módosítása − UPDATE ............................................ 234 Táblák (table-k) ...................................................................... Lapkák és értesítések ..................................................................................................................................................................................................................................................... 202 DataContext ......................................... 245 Néhány példa a lapkák és értesítések használatára ................................................. 226 Adattárolás Windows Azure-ban ............................................... 187 Isolated Storage ..................................................................... 243 10............................... 188 IsolatedStorageFileStream ............................. 200 Lokális adatbázisok használata Windows Phone 7-en ........................................................ 202 Linq To SQL ......................... 231 Várakozási sorok (queue-k) ............ Adatkezelés ...................... 247 A lapkák felépítése ............................................................................................................................................................................................................................................................................. 196 Önálló feladatok .................................................................................. 218 Webszolgáltatás egy mintaalkalmazásban ........................................................................................................ 211 Az adatbázis biztonsága ................................................................................................................................................... 200 IsolatedStorage – Tool ................................................... 194 Isolated Storage gyakorlat ....................... 212 Adatbázis kezelés gyakorlat ..................................................................... 187 Application Settings .................................................................................................................................. 203 Mapping ....... 217 A kommunikáció módjai ................................................................................................................................................................................................................................................................................................................... 212 Összefoglalás ...................................... Kommunikáció szerverrel............................................. 219 Webes tartalom letöltése ................................ 236 Árazás ................................. 246 Kiszögezés és elrendezés ...... 185 8......... 224 Adatelérés az OData protokollon keresztül ......... 203 Adatbázis létrehozása .......................................................................................................................................................................... 211 Adatok törlése − DELETE ............. 239 Felhasználó-hitelesítés szerveroldalról ............................................................................................................................................................................................................................................................................................................................. 247 Statikus és dinamikus lapkák ..................................................................................................... 247 10 ....................................Összefoglalás ..................................... 204 Adatbázis létrehozása II... 230 Fájlok (blob-ok) ................................................................................................................... 246 A lapkák tulajdonságai ........................................................................................................................ 206 Adatok felvitele − INSERT .............................. .....................................................................................................................................................................................................................

................................ 260 A felugró értesítések ........................................... 254 Lapkák frissítése Background Agent-ek segítségével .......................... 272 A kép kialakítása ................................................... 277 Egy XNA program felépítése ......................... 299 12.................................................................... 301 APPHUB ........................................................................................... 254 Lapkák frissítése ShellTileSchedule segítségével ..................................................... 253 Másodlagos lapka törlése ...................... 249 A ShellTile API ........... 249 Lapkák létrehozása és frissítése alkalmazásunkból .............................................................................. 283 Ütközések detektálása ............................................................................................................................................................................................................................................................. 260 A Push Notification szolgáltatás....... 313 11 ......... 258 Időzítés beállítása az elsődleges lapkára ........................... 268 Push Notification-önök és a Windows Azure ................................................................................................................................................................................. 272 A játékciklus .............................................................................. 301 Alkalmazások telepítése ........................... 269 Összefoglalás...................................................................................................................... Játékok a Mango világában ........................... 303 ChevronWP7 ............................................................................................................................................... 277 Sprite-ok ................................................................... 260 Időzítés törlése......................................................................................................................................... 281 Bemenetek kezelése ...................... 270 11........................... 285 Animációk ................................................................................... Marketplace .......................................................................................................... 262 Lapkák frissítése Push Notification-ök segítségével ..................................................... 311 Ikonok ... 267 Raw üzenetek fogadása a Push Notification szolgáltatáson keresztül.................................................................................... 286 XNA és Silverlight integráció ................................ 304 Publikálás .......................................................................................................... 263 Értesítések megjelenítése Push Notification-ök segítségével ...........Tartalomjegyzék Másodlagos lapkák .............................................................. 271 Grafikus programozási és XNA alapok ..................................................................................................................................................................................................................................................................................................................................... 301 Készüléken történő hibakeresés és regisztráció ..................................................................................................................................................................................................................... 248 Deep Linking ......... 310 Windows Phone Marketplace Test Kit .................................................................................................................................................................. 271 Windows Phone – a motorháztető alatt .......................................................................................................................................................................................................................................................................................................................................................... 291 Silverlight és XNA együtt a gyakorlatban.............................................................................................................................................................................................................................. 291 Összefoglalás ...................... 258 Időzítés beállítása egy másodlagos lapkára ...................................... 261 A Push Notification szolgáltatás működése .................................................... 249 Másodlagos lapka létrehozása ..................................................... 249 Lapka frissítése .............................. 305 Screenshot készítés ...........................................................................................................................................................

...... 319 A tipikus teljesítmény-problémákról .................................................................................................................................................................................... 317 13............................................................................................................................................................... 325 Kis összefoglalás ................. 330 Cache vizualizáció .................................................Marketplace Task ...................................................................................................... 329 Használjuk a GPU-t! .................................................. 338 A memória foglalás kijelzése ......................................... 316 Összefoglalás .................................................... 337 Köztes animációk .... 334 Listák ........ 326 Frame Rate Counters . 334 Szubjektív teljesítmény .............................................................................................. 336 A folyamat jelzése .................................................................................................. 314 Trial Mode ................................. 320 Csillagok............................................ 324 Háttérszálak alkalmazása ......................................................... megoldása.. 335 Tilt effektus ................ 337 Amikor a lassabb gyorsabb(-nak tűnik) ............................................... Teljesítmény ................................................................................................................................................................... 339 Optimalizálás .......................... csillagok…................ Compositor és Input szálak ........................................................................................................................................................................................................ 337 Memória-optimalizálás ......................................................... 343 12 .................................................. 328 Redraw Regions ....................................................................................................................................................................................................................................................................... 319 A CPU és a GPU feladata ...................................................................................................................................................................... 339 Összefoglalás ........................................................................................................................................................................................................................................................................................................................................................................................ 323 Az elrendezés (layout) költségeinek csökkentése ................................................................................................. 326 Akadozó animációk okai............................................................ 323 Splash Screen ............................................................................... 339 Windows Phone Performance Analysis ....................................................................................................................................................................................................................................................................................................................................................................................... 332 Hosszú válaszidő kezelése ........................... 324 Előre elvégzett munka ................................................... 324 Inicializációs teendők elhalasztása .............. 331 Beépített animációk és a GPU ............................................................................................................... 333 Általános tippek.................................................................................................................... 320 Lassú betöltődés kezelése .................................................. 332 UI....................

.

amelyeken internetet is elérő alkalmazásokat tudunk futtatni. akik maguk is gépeket építenek. december 13 . és 10. fejezetek). Ez a könyv az alkalmazásfejlesztőknek készült.hu oldalon. Ugyanígy az okostelefonok felhasználói között is többen akadnak. fejezetek). akik szeretik gépjárművüket maguk bütykölni. Olyan szakemberek írták. és 6. és 12. fejezetek). Szinte hihetetlen mértékű változáson estek azóta át a mobil készülékek! Ma leginkább az „okostelefon” megjelölést használjuk azoknak a tenyérben elférő − szinte kizárólag érintőképernyős − mini csodáknak a megnevezésére. és 7. nekem kellett előkeresni a számokat a noteszomból és bepötyögni azokat egy-egy telefonhívás során. Turóczy Attila (8. 2011. Fülöp Dávid (3. fejezet) mindannyian rengeteg energiát fordítottak arra.Előszó Amikor első hordozható telefonomat 18 évvel ezelőtt megkaptam. Árvai Zoltán (1. az még egy kisebb diplomatatáska méretével egyezett meg. amelyben személyes tapasztalataikon. akik korábban már megmutatták. amelyek számítógépek. A könyv és a hozzátartozó programozási példák a weben is elérhetők a Devportal. Olyan eszközök. Novák István Budapest. és a telefonálás lehetősége csupán egyike tucatnyi képességeiknek. Olyan magyar nyelvű könyvet hoztak létre. több korábbi kezdeményezéshez hasonlóan a magyarországi Windows Phone szakmai közösség aktív munkájával jött létre. Komjáthy Szabolcs (4. és 11. fejezetek). valamint Velvárt András (13. Egyetlen dolgot lehetett vele csinálni: telefonálni. akik saját alkalmazásokat szeretnének készíteni. hogy értenek a platform használatához és programozásához. A repülőgépmodellek megszállottjai között vannak olyanok. és 2. és egyúttal betekintést is adnak annak működésébe és használatába. Fár Attila Gergő (5. fejezetek). amelyek segítenek a Windows Phone fejlesztésbe frissen bekapcsolódó érdeklődőknek megismerni a platform legfontosabb alapelemeit. fejezetek). és ezek piaci sikeréből akár meg is élni. hogy ismereteiket megosszák a fejlesztőközösséggel. Farkas Bálint (9. Ebben a könyvben azokat az ismereteiket is átadják. Az autók szerelmesei között vannak olyanok. Még csak telefonkönyve sem volt. a platformhoz kapcsolódó élményeiken keresztül mutatják be a Windows Phone alkalmazásfejlesztés alapvető eszközeit és fogásait.

.

hanem a fejlesztőcégek számára is. Az elmúlt években számos mesébe illő sikertörténetet hallhattunk olyan cégekről. a Flickr és még számtalan online és folyamatos jelenlétet igénylő szolgáltatás világában ezek az eszközök robbanásszerű fejlődésen mentek át és hatalmas kereslet mutatkozik irántuk. új igényekhez igazítva tervezték. Nem csoda hát. a Facebook.ezt a tényt felismerve szemmel láthatólag nem erőltette tovább ezt a vonalat. ezzel lehetőséget biztosítva a készülék gyártói számára saját termékpaletták kialakítására. életünk. illetve az okoskészülékek piacán. Habár saját eszközt nem dobott a piacra. A telefonok tudják. kik a barátaink. bármikor elérhetővé válik. A gyakorlott fejlesztők ezeket a sorokat olvasva biztosan felhördülnek és elgondolkodnak. A Windows Mobile termékcsalád hosszú utat járt be – még ha ez az út igencsak rögös is volt. és újabb lehetőségeket kínál. hogy a Twitter. hogy újabb sikertörténetek születhessenek. Így nem csoda. A Google platformján (Android) a fejlesztők számára komoly kihívást jelent az alkalmazások felkészítése a fragmentációra. mikor hol kellene lennünk. hogy a Microsoft készüléket nem. a Windows Phone és saját alkalmazásboltja (Marketplace) megjelenésével új piacot nyit a vállalkozó szellemű fejlesztők számára. hogy az okostelefonok megjelenésével egyfajta fejlesztői „aranyláz” tört ki. az eddigi mobil operációs rendszerektől eltérő dizájnnal és szellemiséggel rendelkezik. csupán mobil operációs rendszert fejleszt. kik vagyunk. A Microsoft egyike volt az elsőknek az okostelefonok piacán. A Windows Phone Platform A Windows Phone megjelenésében merőben újszerű. Sajnos az idő előrehaladtával egyre nehezebb sikertörténeteket írni. bármi. hogy az asztali Windows-t vihetjük a zsebünkben.1. azzal a gondolattal. hogy ez vajon mekkora fragmentációt jelenthet a készülékek piacán. A Microsoft . az alkalmazást hány különböző eszközre és hardver konfigurációra kell elkészíteni. és alapjaiban új operációs rendszerrel. gyakorlatilag a nulláról indulva. Évente okostelefonok milliói találnak gazdára! Ezek az eszközök napról napra egyre inkább hétköznapjaink részévé válnak. de a Windows Phone újabb ilyen lehetőséget jelent! A Microsoft. a fogyasztói piacnak azonban ezek az elvek és ez a termék nem tudott megfelelni. a Windows Phone-nal jelent meg a piacon. Az Apple a fragmentáció kiküszöbölésére rendkívül egyszerű stratégiát alkalmaz: a készülékeket ő maga gyártja. sokszor kényszerülnek olyan döntéseket hozni. amely az előírt hardver követelményeket maradéktalanul kielégíti. hogy bizonyos kategória alatt nem támogatnak telefonokat. digitális identitásunk egyfajta kiterjesztéseként gondolunk rájuk. 15 . Az okostelefonok új piaca nemcsak a felhasználók számára jelentenek izgalmas. de nagyon pontos specifikációt írt elő a telefon hardveres képességeit illetően. hol vagyunk. a konkurrens termékekkel nem volt képes felvenni a versenyt. A Windows Phone különlegessége. akik a semmiből. Az a telefon lehet Windows Phone. Bevezetés a „Windows Phone” platform-ba Az utóbbi évek egyik legjelentősebb technológiai robbanásának lehettünk tanúi az okostelefonok. mit szeretünk csinálni és kivel. új lehetőségeket. A Google ezzel a kérdéssel nem nagyon foglalkozik. és maximálisan igyekeznek minket kiszolgálni. A Microsoft valahol a kettő közötti utat választotta. A világot helyezik kezünkbe. amely évről évre csak nő. 1-2 év alatt meghatározó szereplőkké nőtték ki magukat. Sokszor társként. Az új igényeknek. Ez a mobil operációs rendszer azonban elsősorban üzleti használatra készült. Ezt a terméket a megváltozott. illetve a könyv írásának pillanatáig nem sokat foglalkozott.

A készüléknek hálózati kommunikáció tekintetében mobil adathálózatok kezelését. Futtatókörnyezet 2. illetve XNA. illetve futó taszkok közötti váltást szolgálja.1. amelyek szorosan kapcsolódnak az operációs rendszer és a navigációs mechanizmus működéséhez.) Adatok tárolásra minimum 8GB-os flash tárolóegységgel kell rendelkeznie a készüléknek. Hálózati jellemzők:   Memória:     Navigáció:  Mozgásérzékelés: A telefon mozgásának. Iránytű Giroszkóp (jóval pontosabb pozíció/állapot meghatározásra képes. (A gyártók döntő többsége 512MB-ot tesz a készülékeibe. mint a gyorsulásmérő) Hátsó kamera Előlapi kamera A Windows Phone által támogatott egyéb opcionális hardverek listája:     A Windows Phone platform képességei A Windows Phone platform alapvetően négy részből tevődik össze: 1. Az alkalmazások ennek köszönhetően nem férhetnek hozzá kontrollálatlanul tetszőleges erőforráshoz. 7. Operatív memória tekintetében legalább 256 MB memóriával kell rendelkeznie a készüléknek. Integráció a felhővel 3. A kijelzőnek támogatnia kell a kapacitív technológiát és minimum 4 pontos érintést meg kell tudnia különböztetni.1-ben ez a viselkedés nem módosítható. Vissza gomb (Back): Az alkalmazáson belüli navigációt. Műholdas navigáció tekintetében Assisted-GPS támogatás szükséges. bármely alkalmazásból. Fejlesztőeszközök Futtatókörnyezet A Windows Phone alkalmazások izoláltan. döntésének és egyéb pozícióinak követésére gyorsulásmérőt kell beépíteni. 16 . ezt a futtatókörnyezet szigorúan ellenőrzi. Kereső gomb: Minden esetben a beépített Bing keresőt hozza fel. elsősorban biztonsági okok miatt. Saját termékek fejlesztése során két platform közül választhatunk: Silverlight. valamint Wi-Fi-t kell támogatnia. ún. Marketplace portál szolgáltatások 4. sandboxban („homokozó”) futnak. Kezdő oldal gomb (Home): A Start képenyőre navigál bárhonnan.     Kijelző:    A kijelzőnek legalább 800 x 480-as felbontással kell rendelkeznie. Bevezetés a „Windows Phone” platform-ba Windows Phone hardver követelmények A Windows Phone készülékeknek számos hardveres előírásnak kell megfelelniük:  Fizikai gombok: A Windows Phone készülékeken kötelezően jelentkező hardveres gombok.

XNA segítségével menedzselt kódú kétdimenziós sprite alapú. A 7. Ennek oka az ún. Windows Phone-nal ismerkedő fejlesztők számára a fejlesztési élmény olyan. hogy a két technológia között az átjárhatóság biztosított. Ezek a felhőben futó szolgáltatások üzeneteket küldenek a telefonok felé.  Értesítések: A mai mobil eszközök kapacitása. illetve GPS adatok segítségével biztosítják a pontos helymeghatározást. limitált erőforrással. mintha a . Térképszolgáltatások: A felhőben pozícionálási és térképszolgáltatások is elérhetők. A Silverlightnak köszönhetően csupán a kreativitásunk szabhat határt a felhasználói élménynek. illetve az XNA ismerős koncepciókat hozott át az asztali Windows-os PC-k világából. mint például szálkezelés. cellainformációk. amely a . fény és árnyékhatások. Base Class Library (BCL). melyek komponensei jól integrálódnak a Windows Phone Metro stílusú látványvilágával. Az XNA API számos játékfejlesztésben felmerülő gyakori problémára (textúra és modell betöltés. Windows-ra és Windows Phonera is játékot. email küldés. Ennek megfelelően menedzselt API-k biztosítják a telefon különböző szenzoraihoz. Míg a BCL. az akkumulátor üzemideje és egyéb erőforrásai nem engedik meg. csupán kisebb módosításokat kell végrehajtanunk. ha valamilyen új információ áll rendelkezésre az alkalmazás és a felhasználó számára. médiaközpontú alkalmazásokat fejleszthetünk. hiszen egy új platformról. Ágyazhatunk XNA tartalmat Silverlightos felületekbe és viszont. hogy azok a telefon tudását és képességeit kiterjeszthessék. életciklus menedzsment) a hozzáférést. Ennek köszönhetően a már korábban elsajátított értékes tudás hordozható a két platform között. 1-1 ábra: A futtatókörnyezet felépítése Integráció a felhővel A Windows Phone alapvetően egy kliens oldali eszköz. XNA felhasználásával fejleszthetünk Xbox-ra. transzformációk. a Silverlight. 17  . felhasználói felületeknek.A Windows Phone Platform Silverlight felhasználásával látványos. operációs rendszerszintű képességeihez (kapcsolatok. így a fejlesztők valóban a játék logikájára koncentrálhatnak. egy mobil eszközről beszélünk. stb. számítási kapacitással és tudáshalmazzal rendelkezik.1-es Mango operációs rendszer különlegessége. A felhőben azonban folyamatosan futó szolgáltatások érhetők el. hogy párhuzamosan alkalmazások tucatjai kommunikáljanak különböző szolgáltatásokkal és egyéb komponensekkel. XNA-val a fejlesztés gyors és produktív. illetve komoly háromdimenziós modellekre épülő játékokat is írhatunk.NET keretrendszeren dolgoznának. gyűjtemények vagy éppen a Linq.NET platformon a jól ismert és leggyakrabban használt alapkönyvtárak jelentős részét tartalmazza. addig számos új elem is megjelent.) kínál kompakt megoldást. és mint ilyen. vagy éppen külön értesítésként is. Ezek WiFi. A Windows Phone-ok támogatják az ún. Ezek az értesítések megjelenhetnek az alkalmazás saját lapkáin. Az 1-1 ábrán a futtatókörnyezet felépítését láthatjuk. értesítéseket (push notifications).

amellyel üzleti célra is fejleszthetünk alkalmazásokat.com címen található portálon végezhető el. amely a telefon legtöbb képességét képes emulálni. amely szolgáltatások ezreihez képes csatlakozni. Alkalmazások közzététele Az alkalmazások. Microsoft Expression Blend for Windows Phone: A Windows Phone felhasználói felületek fejlesztésével és építésével foglalkozó dizájnerek és fejlesztők első számú eszköze. a http://create. Xbox Live szolgáltatások: A Windows Phone képes a felhőben futó Xbox Live szolgáltatásokhoz is kapcsolódni. A Microsoft Expression Blend 4. Regisztráció fejlesztők számára A telefonra történő fejlesztést megelőzi a fejlesztői programba történő jelentkezés.microsoft. ennek segítségével feltölthetjük a Windows Phone alkalmazás boltba.1. összehasonlíthatjuk elért eredményeiket a miénkkel. az alábbi címről: http://www. App Hub-on. ahol a különböző tartalmak és alkalmazások közül válogathatnak. és amelyen keresztül értékesíthetik azokat. üzeneteket küldhetünk nekik. Ezek a szabályok az Application Certification Requirements for Windows Phone című dokumentumban kerültek rögzítésre. Az induláshoz csupán a Windows Phone SDK 7. feltöltésüket követően. egy tanúsítványt kap. Bevezetés a „Windows Phone” platform-ba  Közösségi hálózatok: A Windows Phone nagyon fontos részét jelentik a közösségi hálózatok és az integrált élmény biztosítása az ún.  A Marketplace portálszolgáltatásai A Windows Phone Marketplace egy központi portál.com/enus/library/hh184843(v=VS. Miután az alkamazásunk sikeresen átment a teszteken. így nyomon követhetjük barátainkat. A fejlesztőeszközök is erről a portálról tölthetők le közvetlenül.92). amely során a Microsoft egy szigorú tesztsorozat futtatásának segítségével meggyőződik arról. hogy a telefon egy kliens. Fejlesztőeszközök A Windows Phone-ra fejleszteni készülők számára fontos kérdés az indulás költségvonzata. továbbá egy Windows Phone készülék sem árt.msnd. A regisztrációt és a hitelesítést követően a fejlesztői készülékek zárolását feloldhatjuk.microsoft. Az éves fejlesztői díj 99 dollár.1-es változatot kell letölteni. hogy az alkalmazásunk stabil. Természetesen egy Windowst futtató PC-re szükség lesz. csupán erősen ajánlott. Soha ne felejtsük el. A Marketplace-en keresztül történik a számlázás és a frissítések kezelése is. Cserébe a publikációs lehetőségen túl számos szolgáltatást kapunk a portálon. továbbá kielégíti az alkalmazások által követendő szabályokat. A felhasználók számára ez hatalmas piactér. bár ez utóbbi nem kötelező.   18 . Windows Phone Emulator: Fejlesztési időben használható Windows-on futó emulátor. A fejlesztőeszközök a Windows Phone fejlesztők számára ingyenesen elérhetők. ahol a fejlesztői vezérlőpulton értékes információkhoz. és segítségükkel rendkívül gazdag és értékes információhalmazt biztosítani.com/download/en/details. amely egy Live ID segítségével az ún. nem szolgál rossz célt.0 termék kizárólag Windows Phone projektek kezelésére alkalmas. és ennek eredményeképpen saját alkalmazásokat tudunk rá telepíteni a Visual Studio 2010 segítségével. de teljes értékű változata. ingyenes Visual Studio 2010 változat. hubokon keresztül. Szerencsére elmondhatjuk.aspx?displaylang=en&id=27570 Az SDK a következő fontosabb komponenseket tartalmazza:  Visual Studio 2010 Express for Windows Phone: Kizárólag Windows Phone projektek kezelésére alkalmas. A dokumentum a következő címen érhető el: http://msdn. statisztikákhoz juthatunk alkalmazásainkat illetően.aspx. hogy a fejlesztési infrastruktúra költsége gyakorlatilag nulla. vagy akár otthoni Xboxunkat is vezérelhetjük telefonunkról. ahova a fejlesztők elkészült alkalmazásaikat tölthetik fel. egy hitelesítési folyamaton mennek keresztül. ahol az ár és a régiók kiválasztása után az alkalmazás széles közönség számára válik elérhetővé.

komplexebb értékadásoknál az utóbbi mechanizmust alkalmazzuk. mint például a szélességét vagy magasságát. a webes és intranetes környezetekben is komoly szerepet kaptak. játékterét. Az XML egyfajta kiterjesztése egy különleges XAML Parser-rel. amelyeknek középpontjában a modern. ahol különböző folyamatokat és annak státuszait kell megjeleníteni.0 keretrendszer megjelenésekor.1-ben is a Silverlight. illetve terjeszti ki.NET keretrendszer egyik kulcstechnológiájának. A Button egyéb tulajdonságait. Ismerkedés a XAML-lel Az új modell mellé egy másik fontos koncepció is párosult. Az alkalmazás. Ezt a technológiát később Silverlightként ismerte meg a világ. Ultimate) a fejlesztőeszközök beépülnek a telepített változatba. hogy olyan alkalmazást fejlesztünk. így nem felhasználói felület specifikus. esetleg a tartalmát. mint egy cella lehetséges elemét. Sajánlatos módon további sorsát megpecsételte saját képességeinek erős korlátozottsága. A megvalósítás során hamar belefutunk abba a rendkívül kellemetlen ténybe. a vezérlők alapvetően tartalom jellegű vezérlők (ContentControl) és bármit tartalmazhatnak. Ez lett a WPF legjelentősebb újdonsága. hogy az évek elteltével a Silverlight egyre inkább próbált megszabadulni a böngészőtől és önálló életre kelni. melyet nem sokkal később Windows Presentation Foundation (WPF) néven ismert meg a világ a . A sors különleges fintora. hogy érezzük ezt a kötöttséget. attribútum. Ha XAML-ben leírunk egy elemet (pl <Button/>). 19 . a Windows Forms-nak a segítségével fejlesztették ki. Meghódították az asztali PC-k világát. kiforrott és rendkívül produktív volt. A Windows Phone fő alkalmazásfejlesztési platformja a 7. izgalmas és jól használható felhasználói felületek helyezkedtek el. melyet reprezenáljunk egy ProgressBarral. Ennek következtében nem tudott megfelelni az új igényeknek. melynek feladata a XAML értelmezése és a leírt objektumgráf felépítése. A XAML alapú rendszerek komoly sikertörténetet tudnak magukénak. Premium. hogy a Windows Forms ListView vezérlője nem támogatja a ProgressBart. hogy a XAML alapú felületek jelentik a jövőt. A XAML (eXtensible Application Markup Language) egy kiterjeszthető alkalmazásleíró nyelv. a státuszt pedig minden sorban jelölje egy százalékos érték. illetve tulajdonság szintaxissal lehet meghatározni. mint alkalmazás leíró nyelv. Az ilyen típusú kötöttségek nagyon szűk korlátok közé szorították a termék készítőinek kreativitását.Alkalmazás fejlesztés Silverlight alapokon Amennyiben korábban vásárolt teljes értékű Visual Studio 2010 változattal rendelkezünk (Professional. A technológia és a koncepció igazi bebetonozását a Windows 8 Metro stílusú alkalmazások XAML alapú fejlesztésének lehetősége jelenti. XAML szintaktika – értékadás A XAML alapvetően az XML szintaktikai előírásait követi. Annak érdekében. aminek természetesen túl sok értelme ugyan nincs. Míg az előbbi egyszerű értékek beállítása esetén elegendőnek bizonyulhat. A folyamatokat egy táblázat sorai reprezentálják. és a webre is célszerű lenne elkészíteni egy WPF-hez hasonló technológiát. Ennek köszönhetően egy Button vezérlőbe egy másik Buttont. majd abba egy DataGridet helyezhetünk el. A gondolat nagyon egyszerű volt. de nagyon jól példázza a modell rugalmasságát.0 változatban és a 7.és a vezérlőmodell. A WPF számos új koncepció mellett egy nagyon fontos újdonságot hordozott magában − az új vezérlőmodellt. A Windows Forms maradiságának okán a technológia leváltására a Microsoft elindította az Avalon projektet. XAML nyelvet választotta. melynek segítségével egészen különleges webes felületek építhetők! A Microsoft az új felhasználói felület leírására az ún. akkor abból futásidőben egy Button példány fog elkészülni. Legújabban pedig különböző mobil. A WPF megjelenését követően a Microsoft hamarosan úgy ítélte. A felhasználói felületek leírásának egyik és egyben talán legtermészetesebb módja a leíró nyelvek (Markup Language) használata. amely a Windows Forms-ot jellemezte rendkívül rugalmatlan és merev volt.NET 3. Gondoljunk csak a HTML-re. képzeljük el. ez pedig a felhasználói felület deklaratív leírása. Alkalmazás fejlesztés Silverlight alapokon Nem is olyan régen a Windows platformra készülő alkalmazások jelentős részét a . illetve hordozható eszközökön fejleszthetünk alkalmazásokat XAML alapokon. A technológia hatékony.

ezért elegendő attribútum szintaxist alkalmaznunk. azaz tulajdonság szintaxissal kell beállítani a tartalmat. vagy éppenséggel túl körülményes lenne. Prefix definiálása saját komponens használatához: xmlns:myControls="clr-namespace:MyControlsLibrary. Prefixszel együtt. valamint a „Hello World” felirat kerül. A belső panelbe pedig egy piros 10 x 10-es kör.Content> </Button> A fenti példában a Button belső tartalmát egy némileg összetettebb vezérlőfa határozza meg. amelyet vagy nem tudunk az XML szintaktikai eszközeivel leírni. Tartalom meghatározása tulajdonság szintaxissal: <Button> <Button. Ha a Windows Phone-ra egy saját Button vezérlőt fejlesztünk. Ezek sajátos szintaktikája a következő: PropertyNév="{kiterjesztésneve [hivatkozás paraméterek]}" 20 . Az ilyen esetekben (például adatkötés. hogy amikor leírjuk az objektumok nevét. az ún. azaz leírónyelvi kiterjesztéseket használhatunk.1. hivatkozás statikus erőforrásokra) ún. XAML szintaktika – Prefixek használata A C#-ban vagy éppen a Visual Basic-ben megszokhattuk. akkor a megfelelő névtérre kell hivatkoznunk. De honnan tudhatja a XAML Parser. Markup Extension-öket. Saját komponens meghivatkozása prefixen keresztül <myControls:MyButton> </myControls:MyButton> A fenti példában a myControls prefix által reprezentált névtérben található MyButton komponenst hivatkozzuk meg.dll állomány MyControlsLibrary névterét rendeljük a myControls prefixhez. hogy a XAML Parser számára valami különleges dolgot kell jeleznünk. Figyeljük meg. vagy a saját Buttont szeretnénk felhasználni? Erre a problémára a prefixek használata jelenti a megoldást. A Button belsejébe egy panel kerül. Bevezetés a „Windows Phone” platform-ba Tartalom meghatározása attribútum szintaxissal: <Button Content="Hello World"/> A fenti példában a gomb tartalma egy egyszerű string. XAML szintaktika – Leírónyelvi kiterjesztések Gyakran előfordul.assembly=MyControlsLibrary" A fenti példában a MyControlsLibrary. amely egymás alá rendezi el az elemeket. A megfelelő XAML elemeken definiálnunk kell a névtereket egy hivatkozással. Ezt követően a prefix felhasználásával könnyedén hivatkozhatjuk meg a saját komponenseinket. hogy a kör (Ellipse) és a felirat (TextBlock) saját tulajdonságait attribútum szintaxissal határoztuk meg. akkor azt szeretnénk helyezni a felhasználói felületen használni. Ezt a belső tartalmat attribútum szintaxissal nem lehet meghatározni. ezért a Content tulajdonságot „ki kell nyitni”.Content> <StackPanel> <Ellipse Fill="Red" Width="10" Height="10"/> <TextBlock Text="Hello World"/> </StackPanel> </Button. hogy mi most melyik gombra gondolunk? A beépített Button érdekel minket.

Az x prefix a XAML nyelv saját névterét reprezentálja. hogy melyik saját osztály származik a PhoneApplicationPage osztályból. Az mc:Ignorable paraméter azt határozza meg. amelyik a kapcsolódó mögöttes kódban megtalálható. mint a betűkészlet típusa. Ez lesz az alapértelmezett névtér. De mi az az x prefix? Az x:Class-nál is feltűnt már korábban. akkor azt ebben a névtérben fogja keresni a XAML Parser.Phone" xmlns:d="http://schemas.Shell. azaz melyik az az osztály. akkor azt a XAML névtérben találhatjuk meg.microsoft. Ezek rendszerszintű beállításokra (ún.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas. továbbá a panel neve „LayoutRoot” lett.microsoft.microsoft. óra.openxmlformats. ha valami XAML-specifikus dologra van szükségünk. A prefix definíciók után néhány PhoneApplicationPage tulajdonság kerül beállításra.) látszik-e az alkalmazásban.assembly=Microsoft. Az x:Class tulajdonság segítségével azt határozzuk meg. Végül a PhoneApplicationPage elem kerül definiálásra. A következő két tulajdonság azt határozza meg. hogy a felső rendszerinformációs sáv (akkumulátor töltöttség. ezt kizárólag a tervezőeszköz tartja számon.com/expression/blend/2008" xmlns:mc="http://schemas. vagy elrejtjük. Mode=TwoWay}"/> Ne aggódjunk amiatt. A „d” prefixszel ellátott beállítások egytől egyig a tervezőfelület számára meghatározott értékek. Azaz. stb. A fenti SystemTray. hogy az alkalmazás milyen orientációkat támogat (SupportedOrientations) és mi az alapértelmezett orientáció (Orientation).assembly=Microsoft. ahol nem szerepel prefix. erőforrásokra) hivatkoznak.Phone. már csak a benne levő tartalom – azaz az oldal tartalma –a kérdéses.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray. A következő sorokban számos prefix definíciót látunk. illetve az előtér színe.Phone" xmlns:shell="clr-namespace:Microsoft. csupán az xmlns definíció. Jelen esetben egyetlen Grid panel található benne.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft. azaz ha prefix nélkül írunk le xaml-ben egy elemet.Phone. amelyen transzparens hátteret határoztunk meg. mérete. 21 .IsVisible tulajdonság határozza meg azt. futásidőben nem játszanak szerepet. kiegészíthető.Controls. hogy a „d” prefixet nem kell figyelembe venni futásidőben. ha a fenti sorok egyelőre semmit nem jelentenek számunkra! A későbbi fejezetek során ezek jelentésére fény derül.Alkalmazás fejlesztés Silverlight alapokon Néhány példa markup extension-ökre: <Button Style="{StaticResource buttonStyle}"/> <TextBox Text="{Binding FirstName. XAML alapú felhasználói felületek Egy egyszerű Windows Phone felhasználói felületet leíró XAML részlet anatómiája: <phone:PhoneApplicationPage x:Class="PhoneApp2. ebből egy kiemelkedik. amelyhez az x prefix került hozzárendelésre.IsVisible="True"> <Grid x:Name="LayoutRoot" Background="Transparent"> </Grid> </phone:PhoneApplicationPage> A PhoneApplicationPage objektum egy Windows Phone képernyőt reprezentál.SecondPage" xmlns="http://schemas.

1-2 ábra: Új projekt létrehozása 2. hogy el ne készítse rá a dedikált Hello World alkalmazását. A következő lépésben a Visual Studio megkérdezi tőlünk. a többi beállítás alapértelmezett értékét hagyjuk meg (1-2 ábra)! Kattintsunk az OK gombra! A dialógus ablakban láthatjuk. hogy számos különböző projektsablon áll rendelkezésünkre. majd kattintsunk az OK gombra! 3. Egyelőre gondoljunk ezekre úgy. Készítsük hát el első Windows Phone alkalmazásunkat! 1. Ezekkel a későbbi fejezetek során részletesebben is megismerkedünk majd. 1-3 ábra: A projekt felépítése 22 .1 van kiválasztva. Vegyük szemügyre a Visual Studio által létrehozott elemeket! A Solutions Explorer ablak tartalma az 1-3 ábrán látható.1. hogy a Windows Phone OS 7. Bevezetés a „Windows Phone” platform-ba Hello Windows Phone Egyetlen valamirevaló fejlesztő sem vághat bele egy új technológiával való ismerkedésbe anélkül. illetve különböző felépítéssel rendelkező alkalmazások speciális változatai. mint különböző alkalmazás típusok. hogy melyik operációs rendszer változatra szeretnénk fejleszteni. válasszuk ki a New Project parancsot! Az elérhető alkalmazás típusok listájából válasszuk a Windows Phone Application sablont! A projektet nevezzük el HelloWindowsPhone-nak. Győződjünk meg róla. Hozzunk létre egy új Windows Phone alkalmazást! Kattintsunk a File menüre.

png Induláskor megjelenő. A legérdekesebb szekció azonban a Capabilities elem és gyerekei. Ezeknek a gyerekelemeknek a felvételével határozhatjuk meg.com/windowsphone/2009/deployment" AppPlatformVersio n="7.png</IconPath> <Capabilities> <Capability Name="ID_CAP_GAMERSERVICES"/> <Capability Name="ID_CAP_IDENTITY_DEVICE"/> <Capability Name="ID_CAP_IDENTITY_USER"/> <Capability Name="ID_CAP_LOCATION"/> <Capability Name="ID_CAP_MEDIALIB"/> <Capability Name="ID_CAP_MICROPHONE"/> <Capability Name="ID_CAP_NETWORKING"/> <Capability Name="ID_CAP_PHONEDIALER"/> <Capability Name="ID_CAP_PUSH_NOTIFICATION"/> <Capability Name="ID_CAP_SENSORS"/> <Capability Name="ID_CAP_WEBBROWSERCOMPONENT"/> <Capability Name="ID_CAP_ISV_CAMERA"/> <Capability Name="ID_CAP_CONTACTS"/> <Capability Name="ID_CAP_APPOINTMENTS"/> </Capabilities> <Tasks> <DefaultTask Name ="_default" NavigationPage="MainPage.xaml"/> </Tasks> <Tokens> <PrimaryToken TokenID="HelloWindowsPhoneToken" TaskName="_default"> <TemplateType5> <BackgroundImageURI IsRelative="true" IsResource="false">Background. töltési idő alatt látható kép A Properties alatt található WMAppManifest.xaml (MainPage.png</BackgroundImageURI> <Count>0</Count> <Title>HelloWindowsPhone</Title> </TemplateType5> </PrimaryToken> </Tokens> </App> </Deployment> A fenti XML kódrészletben jól látható.Hello Windows Phone A HelloWindowsPhone projekt elemeinek tartalmát az alábbi táblázat mutatja be: Elem neve Properties References App.normal" Author="HelloWindowsPhone author" Description="Sample description" Publisher="HelloWindowsPhone"> <IconPath IsRelative="true" IsResource="false">ApplicationIcon.xaml.0" Genre="apps.png Background. stb.xaml (App.0. hogy az alkalmazás alapbeállításai itt kerülnek meghatározásra: a háttérkép.xaml. hogy az alkalmazásunk a telefon 23 .cs) ApplicationIcon.0. az alkalmazás felirata.microsoft.xml fájl megér külön egy kis magyarázatot: <Deployment xmlns="http://schemas.1"> <App xmlns="" ProductID= "{9bb8c371-293f-4726-a4ba-5b2e2efb152d}" Title="HelloWindowsPhone" RuntimeType="Silverlight" Version="1. az ikon.png MainPage.cs Elem jelentése Az alkalmazás tulajdonságait és beállításait tartalmazó állományok Hivatkozott egyéb könyvtárak Az alkalmazást reprezentáló objektum és a mögöttes kódja A lapkához tartozó kép Az alkalmazás háttérképe Az alkalmazás főoldala és a kapcsolódó mögöttes kód SplashScreenImage.

Row="1" Margin="12.Shell.openxmlformats.0"></Grid> </Grid> <!--Sample code showing usage of ApplicationBar--> <!--<phone:PhoneApplicationPage.microsoft. Bevezetés a „Windows Phone” platform-ba mely képességeihez fér hozzá.28"> <TextBlock x:Name="ApplicationTitle" Text="MY FIRST APPLICATION" 24 .IsVisible="True"> <!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.0.MainPage" xmlns="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.0.Phone" xmlns:shell="clr-namespace:Microsoft.microsoft. a későbbi fejezetekben azokat részletesen bemutatják! Az érdekes rész az ApplicationTitle és PageTitle névvel rendelkező TextBlock vezérlők Text tulajdonságai.12. majd vegyük szemügyre annak tartalmát: <phone:PhoneApplicationPage x:Class="HelloWindowsPhone.1.Controls.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.17. mit képes kihasználni.png" Text="Button 2"/> <shell:ApplicationBar.Phone. Módosítsuk az értékeket a következő módon: <StackPanel x:Name="TitlePanel" Grid. amelyeket ténylegesen is használunk.Phone. A Text tulajdonság határozza meg a felirat tartalmát.28"> <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="page name" Margin="9.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.assembly=Microsoft. hogy itt csak azok az elemek maradjanak meg.Row="0" Margin="12.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.17.MenuItems> <shell:ApplicationBarMenuItem Text="MenuItem 1"/> <shell:ApplicationBarMenuItem Text="MenuItem 2"/> </shell:ApplicationBar.Phone" xmlns:d="http://schemas.-7.Row="0" Margin="12.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray. ne aggódjunk.0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel . Kattintsunk duplán a MainPage.ApplicationBar>--> </phone:PhoneApplicationPage> A PhoneApplicationPage beállítások már korábban tisztázásra kerültek.0.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft. 4.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.assembly=Microsoft. ezért koncentráljunk most a LayoutRoot elnevezésű Grid panel tartalmára! Ha sok benne az ismeretlen elem.png" Text="Button 1"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.0.place additional content here--> <Grid x:Name="ContentPanel" Grid. Biztonsági szempontból érdemes ügyelni arra.xaml állományra.

és válasszuk a Navigate To Event Handler parancsot! Ennek hatására a Visual Studio megnyitja a MainPage. ha végeztünk a futtatással. majd futtatja rajta az alkalmazást.cs kódállományt.12. Ez azt jelenti.0.0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> 5. telepíti rá. az alábbi módon: private void Button_Click(object sender. majd válasszuk ki a Start Debugging menüpontot! 9. Helyezzük el benne az alábbi kódrészletet: <Grid x:Name="ContentPanel" Grid. és a megfelelő eseménykezelő metódusra navigál. 6. RoutedEventArgs e) { MessageBox. Ha az emulátor még nem fut.Row="1" Margin="12.0"> <Button Content="Greet Me" Click="Button_Click" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> Ezzel egy középre igazított gombot helyeztünk el. Kattintsunk az egér jobb gombjával a Button_Click szövegre. Az emulátor elsőre lassabban indul el. Futtassuk az alkalmazást! A Visual Studio felső sávjában. Az éles eszközön való tesztelés esetén a következő feltételeknek rendelkezésre kell állniuk:    Zune Desktop alkalmazás fut a háttérben A telefon össze van kötve USB adatkábelen a számítógéppel A telefonon a lockscreen fel van oldva 8.xaml. 25 . közvetlenül a menü alatt láthatjuk a Windows Phone Emulator beállítást. Figyelem: Az emulátort csak egyszer kell elindítani.Hello Windows Phone Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="hello page" Margin="9. Egészítsük ki a kódot. hogy a Visual Studió alapértelmezett módon az emulátoron futtatja majd az alkalmazást. melyen a „Greet Me” felirat található.0. akkor indít egy újat. ha szeretnénk közvetlenül egy valódi eszközön futtatni az alkalmazást. Teszteljük az alkalmazást! Kattintsunk a Greet Me gombra! Az eredmény az 1-4 ábrán látható. Keressük meg a ContentPanel elnevezésű Grid panelt! Ennek a belseje fogja reprezentálni az oldal tartalmát. Ezen felül a Click eseményre is feliratkoztunk egy Button_Click eseménykezelő metódussal.Show("Windows Phone says hello!"). A futtatás megkezdéséhez kattintsunk a Debug menüre. nem érdemes leállítani azt.-7. de egyetlen futó példányon bármennyi tesztfuttatást indíthatunk! A lenyíló menüben a Windows Phone Device-t is kiválaszthatjuk. } 7. hanem a Visual Studióban érdemes a futást megszakítani.

beállításai. A következő fejezetekben ezt a tudást mélyítjük el. hogyan is épül fel egy Windows Phone projekt. valamint megírtuk életünk első Windows Phone alkalmazását.1. 26 . a Silverlight és a XAML nyelv alapjaiba. Betekintést nyerhettünk a platform legfontosabb építőelemeibe. hogy végül professzionális alkalmazásokat tervezhessünk és fejleszthessünk. Bevezetés a „Windows Phone” platform-ba 1-4 ábra: A „Hello Windows Phone” alkalmazás futás közben Összefoglalás Ebben a fejezetben megismerkedhettünk a Windows Phone alkalmazásplatformmal. melyek a legfontosabb elemei. amelynek során részletesen megvizsgáltuk. Bemutatásra került a fejlesztőeszköz.

Ennek az „újraindításnak” eredményeképpen született meg a Windows Phone 7. és egy új szellemiséget tükröz. Az újdonság alkotásának képessége felbecsülhetetlen értékű kincsnek számít az informatika világában is. A Windows Phone tökéletes példája ennek a történetnek. hogy az okostelefonok szerepét és jelenségét alapjaiban újra kell gondolni és tervezni! Ez a piac más. más rendszert alkotott. hogyan lépnek interakcióba a felhasználók telefonjaikkal. Néhányan azonban sikeresen felismerték. Az évszázadok során a piacok talán legfontosabb mozgatórugójának az innováció bizonyult. melynek során a telefonok egyre okosabbak lettek. mint a hagyományos értelemben vett IT szektor. de számos kulcsfontosságú hozzávalót sikerült azonosítani a sikerhez vezető úton. sokkal inkább az Apple és a Google. ezért a legfontosabb területen. A Microsoft terméke valóban jól megkülönböztethető. a fogyasztói termékek piacán a felhasználó diktál! Az ő igényei az elsődlegesek. valós igényeitől. A Windows Phone jelenség Ebben a történetben nem a Microsoft a felfedező. Az elmúlt években mamutokat láthattunk visszasüllyedni a középszerűségbe. ismeretlen. különösen nem ilyen versenytársak mellett. amely az elmúlt években egy új területre gyűrűzött be. a felhasználói élmény tekintetében a versenytársakétól merőben eltérő. Ennek az innovációs hullámvasútnak a legmarkánsabb területe éppen a mobilpiac. A Microsoft korábbi okostelefon rendszerét. amely jól elkülönül a többi konkurens terméktől. A megszokott funkcionális innováció mellett újabb irányt vett.2. ahol számos esetben a felhasználók rákényszerülnek a lehetséges és elérhető megoldásokra. aki felismeri ezt az új helyzetet. és egy ilyen belépés sohasem egyszerű. Ilyet senki nem hozott nyilvánosságra. Felhasználói élmény tervezése Windows Phone-on A történelem során vállalkozások ezrei keresték a siker zálogát jelentő receptet. 27 . A Microsoft jól tudta. a Windows Mobile-t hátrahagyva. vagy éppen csőd közeli cégeket mamutokká válni. illetve Android alapú mobil rendszereiket. hogyan és mire használják azt. Legtöbben talán emlékszünk még a fél tégla méretű. a felhasználók. egyedi megjelenéssel rendelkezik. Egyre komplexebb szoftverek és operációs rendszerek jelentek meg. az emberek felé. A sikerhez azonban nem elég egy jó másolat elkészítése. Ennek az izgalmas és érdekes hullámvasútnak az egyik legfőbb oka az innováció (vagy éppen annak hiánya volt). A 2-1 ábrán látható a Windows Phone. majd az ezt követő funkcionális innovációra. egyéb okostelefonok társaságában. akik komoly sikerre vitték saját iOS. melyeknek köszönhetően ezek a szinte már számítógépnek nevezhető készülékek egyre inkább eltávolodtak a felhasználók gondolkodásától. Olyan készülékkel akart piacra lépni. A Microsoftnak ilyen értelemben egy markáns piacra kellett belépnie. hogy ezúttal az innovátor szerepét kell magára vállalnia. telefonálásra éppen csak alkalmas készülékek megjelenésére. alapjaiban gondolta újra. és az a piaci szereplő lehet a nyerő. az írhatja a következő sikertörténetet. Ezen a piacon.

ahol a felhasználók kiszolgálása.) A 2-2 ábrán egy infografikus. hogy azok a versenytársak. akik az ikonografikus felületet részesítik előnyben. infografikus felület. hogy nem az alkalmazás és a vezérlők kerete vagy a „csicsa” az. A weben. izgalmas és szép felületeket készíthetünk. Ikonografikus környezetben és koncepcióval is rendkívül jól használható. a reklám és a média világában ez az irányzat már jó ideje elsőbbséget élvez. egyre nagyobb teret kapnak az infografikus felületek. Azokon a területeken. Ez az új gondolkodásmód egy igen izgalmas és markáns design nyelv létrejöttét eredményezte.2. Míg a versenytársak termékei rendre a megszokott és egyébként nagyon jól bevált ikonografikus megjelenést részesítik előnyben. Ez persze nem jelenti azt. ami meghatározza egy alkalmazás jellegét. Az infografika az információközlés igazi művészete. az ún. addig a Microsoft új utat választott. a jól használhatóság különös jelentőséggel bír. a tartalom. az információ átadás. Felhasználói élmény tervezése Windows Phone-on 2-1 ábra: Windows Phone 7 a versenytársak mellett Ikonografikus és infografikus felületek Az egyediség kulcsa egy új koncepció. rossz úton járnának. (A csicsa jelen esetben semmiképp sem pejoratív értelemben értendő. hanem a benne levő tartalom. a 2-3 ábrán pedig egy ikonografikus felület látható. 2-2 ábra: Infografikus megjelenés 2-3 ábra: Ikonografikus megjelenés 28 . A Microsoft által választott út kimondja.

ezen keresztül adható tudtukra. ismerősek és könnyen érhetőek: jelzések és apró infografikák a reptereken. képek. az egyértelmű vizuális kommunikáció és az érthetőség. melyeket jól megszoktunk. valamint célorientált. mint például az Xbox360 Dashboard vagy éppen az új Windows 8 UI. a metró aluljárókban. A Metro is ebből az eszköztárból merít ikonok. néhány alapvetést fektet le.A METRO Dizájn Nyelv A METRO Dizájn Nyelv Az infografikus megközelítés szellemében a Microsoft kialakította saját ún. a nehézkes megjelenés csupán a komplexitáshoz és a zsúfoltság érzéséhez járulhatnak hozzá. bátran alkalmazza a szabad és üres területeket. ahogyan ezt a 2-5 ábra is tükrözi. a pályaudvarokon. Az életünk és a környezetünk tele van olyan elemekkel. Azóta ez a megjelenés gyakorlatilag a Microsoft összes termékében visszaköszönt. a bankokban. A 2-4 ábrán láthatjuk a Metro dizájn forráselemeit. szabad területben gazdag megjelenés 29 . az utcán. dizájn nyelvét. de ugyanakkor pehelykönnyed működést és érzést kell biztosítania. ami új és idegen számukra. A Metro felület könnyed. 2-4 ábra: Metro dizájn források Tiszta és pehelykönnyű A felhasználói felületnek gyorsnak és válaszképesnek kell lennie. A felhasználók nehezebben azonosulnak mindennel. A dizájn nyelv csupán az alapvető szellemiséget határozza meg. 2-5 ábra: Letisztult. mint a kommunikációs csatorna a felhasználókkal. amely a Windows Phone 7-es készülékeken jelent meg először. hogyan is működik az alkalmazás. amikor az elsődleges szempont a tájékozódás. Nézzük meg ezeket közelebbről! Ismerős megjelenés A felhasználói felület nem más. feliratok alkalmazásakor. rohamtempóban vette át a stafétát a régebbi felhasználói felületektől. jelzések. olyan termékekben. A bonyolult felületek. letisztult és nyílt.

letisztultak és modernek. Felhasználói élmény tervezése Windows Phone-on Digitális eredetiség Nincs szükség arra. öncélú vizuális elem gátolja a felhasználó szabad mozgásterét. Ilyenkor a felületen a keret. képekkel. Az érintőkijelzőnek köszönhetően természetes mozdulatokkal vezérelhetjük az alkalmazásainkat. koncentráljunk a lényegre! 2-6 ábra: Digitális megjelenés Gyönyörű tipográfia Fölösleges grafikai elemek nélkül is készíthetünk rendkívül ízléses és gyönyörü felhasználói felületeket. hagyjuk el a fölösleges keretet. a hangsúlyozásra. hogy jelezzük. letisztult. Állandóan mozgásban A mozgás. szavakkal. A jól kidolgozott animációk meghatározzák az alkalmazás ritmusát és dinamikáját is. Az animációk nem öncélúak. informatív jellegűek. figyeljünk oda a méretekre. legyünk egyszerűek. a gomb kattintható! Nincs szükség fölösleges grafikai elemekre. és építsünk minimál-dizájnnal rendelkező. tevékenységük milyen hatással bír a felületre nézve. a jó vizuális hierarchiára! Legyen a tartalom maga gyönyörű! Megfelelő betűtípusok és egyensúly alkalmazása mellett egyetlen fehér papírlap is lehet rendkívül esztétikus és vonzó. hanem tanító. az egyensúlyra. megértését az alkalmazás működésére vonatkozóan. Gyors. azaz a „tartalom mindenekfelett” elv. hogy műveleteik. Koncentráljunk a szép betűtípusokra. Koncentráljunk a tartalomra. könnyed animációkkal pillanatok alatt megtaníthatunk bárkit. A felhasználók számára azonnal jeleznünk kell. hogyan használja az alkalmazásunkat. Legyünk őszinték. A felhasználók ezeket az alkalmazásokat érintéssel („tapogatással”) fedezik fel. hogy egy gombot 3D-snek tüntessünk fel ahhoz. ez egy digitális termék! Ma már nincs szükség arra. a túl sok fölösleges. a felfedezést. Az egyik legfontosabb irányelv a Metro dizájnban a tartalom elsődlegessége a kerettel szemben. A vizuális visszajelzés elsődleges eleme az animáció. hogy másnak mutassuk az eszközt. mint ami valójában.2. A tartalom az elsődleges A felhasználói élményt tervező szakértők körében jó ideje elfogadott és hangsúlyozott elv a „Content is King”. Különösen fontos szerepet játszik ez a gondolat érintőképernyős alkalmazások tervezésekor. videókkal próbálnak interakcióba lépni. tágas felhasználói felületeket! 30 . az animációk jelentik a felhasználók és az eszközök közötti kétirányú interakció gerincét.

Annak az esélye azonban. a szociális hálókat összefogó People Hub-on át. A User Experience Design (UXD).Design vezérelt fejlesztés 2-7 ábra: Tartalom a középpontban A Metro dizájn nyelv. melynek elveit szem előtt tartva professzionális. mára a Microsoft saját termékeinek elsődleges dizájnjává nőtte ki magát. Ennyi különböző ember igényeinek kielégítése igen komoly és nehéz feladat. hanem azt a megfelelő szakembereknek kell kezükbe venniük. Ebben az esetben ugyanis a fogyasztói piacra fejlesztünk.és szórakozáscentrikus Xbox Live Hub-bal. Nem véletlen. Elkeserednünk azonban nem érdemes. remélhetőleg tízezrei fogják használatba venni és „nyúzni” alkalmazásainkat. amely alkalmazza ezeket az elveket minden szoftverében. 2-8 ábra: Metro-s megjelenés alkalmazás típustól függetlenül Design vezérelt fejlesztés A Windows Phone 7 alkalmazásfejlesztés eszenciája némileg eltér az eddig megszokottól. El kell fogadnunk. innovatív. hogy egy teljes UXD csapatot alkalmazhatunk mobil alkalmazásaink fejlesztésénél. mint például a Office termékcsalád (2-8 ábra). elég csekély. A Windows Phone 7 az első olyan termék. de ugyanakkor konzisztens. vagyis a felhasználói élmény tervezése mint tevékenység számos területet foglal magába. hogy az esetek többségében nem bízhatjuk a fejlesztőre a felhasználói élmény kialakítását. kellő 31 . új generációs felületeket alakíthatunk ki. Ők a User Experience Designerek. egészen a professzionális alkalmazásokig. kezdve a játék . hogy komoly szakmák létrejöttét eredményezték ezek a körülmények. Komolyabb rendszerek építésekor ezekre a területekre külön specializálódott szakembereket alkalmaznak. ahol felhasználók ezrei.

hogy miként reprezentálhatjuk ezt látványosan. Ne essünk tévedésbe! Az a gyakorlat. Használjuk bátran a vizuális eszközöket. amit csinál. a vizuális dizájnra nem. és folyamatosan finomítsuk a felhasználói felületünket! Esztétika és vizuális élmény A dizájnerek fontossága soha sem volt kétséges. esztétikus alkalmazás. 32 . Rendkívül sokat segíthetnek az ún. Ha elég sokat foglalkozunk a saját termékünkkel. hogy a tartalom megfelelően tálalva. Felhasználói élmény tervezése Windows Phone-on odafigyeléssel mi magunk is kellemes élményt alakíthatunk ki. az információból! Döntsük el. ezért létfontosságú. Teszteljünk minél többet. egészen az apró részletekig. a kiemelkedő vizuális élmény. hogy hajtson végre valamit az alkalmazásunkkal. Ehhez azonban tisztában kell lennünk a kulcsfontosságú területekkel! Tartalom és információs architektúra A Metro egész szellemisége a tartalom köré épül. folyosó tesztek: kapjunk el valakit a folyosón és kérjük meg. a használhatóság biztosítása. Ez igen tág témakör.2. nem elegendő. hanem az értékből. előbb-utóbb nem vesszük észre benne a finomságokat. A legfontosabb dolog. mi a legértékesebb információ! Miután ez a tudás már a birtokunkban van. hogy a felhasználó fejével gondolkodjunk. A weben tömegével megtalálható infografikai példák komoly segítséget nyújthatnak. nekiállhatunk megtervezni. melyek a legfontosabb elemek. A középszerűségből csak úgy emelkedhetünk ki. Szintén sok ötletet meríthetünk egyéb sikeres alkalmazásokból. és egy fekete-fehér alkalmazást készítünk. amelyben a vizuális hierarchiától kezdve a navigáción át. grafikonokat. hogy gondosan elemezzük. és ennek megfelelően alakítsuk ki a felhasználói felületet! Sajnálatos módon az objektivitásukat még a gyakorlottabb szakemberek is igencsak nehezen tudják megőrizni. kérjük ki mások véleményét. sok mindent gondosan meg kell terveznünk. A fogyasztói termékek piacán azonban elengedhetetlen a szép. prioritás és érték szerint kerüljön megjelenítésre (2-9 ábra)! 2-9 ábra: Tartalom meghatározása Metro elvek szerint Használhatóság és ergonómia A felhasználói élmény tervezésének másik fontos területe az ergonómiai kérdések tisztázása. hogy tesztelje le. hogy a Metro dizájn elveit betartjuk. infografikákat! Végig tartsuk szem előtt. a tartalom az. ha maradandó élményt nyújtunk! Sok mindenre sajnálhatjuk az erőforrásainkat. rosszabb esetben a nagyobb bajokat sem. amelynek ki kell emelkednie. Az alkalmazás középpontjában a tartalom van. Ezért a legfontosabb a kezdő ergonómus számára. figyeljük a felhasználóink „ügyetlenkedését”. hogy mit és hogyan mutatunk meg a felhasználónak! Ne a vizualitásból induljunk ki. annak kell ragyognia. melyeket láttatni kell a felhasználóval.

és ennek eredményeképpen jóval kevesebbet fogunk hibázni a fejlesztés alatt. azt hogy a felhasználóknak . az ötletelésről szól. hogyan alakulnak majd a felületek. a használati esetek alapján történő fejlesztés nem visz közelebb a jó felhasználói élményhez. amit építünk. A probléma megértése Miközben a tervezés zajlik. ceruzára és arra. A szöveges specifikáció. amelyek meghatározzák. Írjuk le az ötleteket. hogy egyre jobb és minőségibb termék szülessen. amit csinálunk. születnek azok a gondolatok. amikor az alkalmazás körvonalazódni látszik. illetve az interakciós folyamat végiggondolása közben azonnal megmutatkoznak a rossz koncepciók.Csináld magad! 2-10 ábra: Dizájn alkalmazása a tartalom fölött Csináld magad! A dizájn-vezérelt tervezés legfontosabb eleme maga a tervezési folyamat. A dizájn szórakoztató. amelytől a termék igazán innovatív lehet. mind a felhasználói felület tekintetében – hol helyezkednek el a prioritások és a súlypontok. A dizájn szórakoztató! Tervezzünk magunk! Csupán három dologra van szükségünk a munkához! Papírra. Az ötletelés.mind a funkciók. Időközben nem árt újra és újra végigszaladni a terveken és újraértékelni. 33 . Sokkal jobban átlátjuk a feladatot. a felhasználói felületek épülnek. amikor a funkciók. hogy ne munkának fogjuk fel. Azok a termékek. semmit se zárjunk ki! A csoportos ötletelés fantasztikus eredményekre vezethet. helyenként még a szoftver és a felület instabilitásához is hozzájárulhat. Gondolataink rendszerezéséhez nagy segítséget nyújthatnak a különböző mindmapping szoftverek. egyre jobban megértjük a problémakört. Ezek azok az órák. Magasabb termékminőség A pontos UI tervezés komoly előnye. sokkal jobb minőségűek. mint az ad-hoc. és hogyan szolgálhatja a legjobban a felhasználó igényeit. napok. Az egyik legizgalmasabb pillanat és folyamat. Ez nagyon fontos „mellékhatása” a tervezési folyamatnak. a brainstorming hozzájárul ahhoz. „evolúciós” felhasználói felülettel rendelkező társaik. hogy a fejlesztés során sokkal egyértelműbb. Számtalan szoftver szenved a dizájn és a UI tervek hiánya következtében előálló káosztól. hogy az elkövetkező hónapok kemény munkájának eredménye gyümölcsöző lesz vagy éppen csúfos bukás. és az innovatív gondolatok születnek. mi is az. melyeknek a felhasználói felületét előre megtervezték. az újratervezés minimális lesz. a hibás gondolatok. az ötletek záporoznak. Innováció tervezés közben Amikor az alkalmazás megjelenik a szemünk előtt. Rajzolás.

Tervezés Sketchflow-val A Microsoft Expression Blend for Windows Phone termék rendkívül hatékony eszköz. (2-11 és 2-12 ábrák) 2-11 ábra: Sketchflow-val tervezett dinamikus prototípus 2-12 ábra: Sketchflow navigációs térkép 34 . mint például az Expression Blend Sketchflow.codeplex. Sketchflow projektek létrehozására is. A felhasználói felület végleges kialakításában.2. Ez a fejlesztőeszköz Windows Phone fejlesztéshez ingyenesen elérhető. vázlatok. Felhasználói élmény tervezése Windows Phone-on Amennyiben a felhasználói felület tervezését formális eszközökkel támogatni kívánjuk. a hatékony és gyors munkában elengedhetetlen szerepe van. Ezek a projektek kizárólag sketchek. Windows Phone fejlesztéshez elérhető a Codeplex-en. dinamikus prototípusok készítésére alkalmasak. használhatunk erre specializálódott eszközöket is.com/). Az Expression Blend egyéb változataiban lehetőségünk van ún. melynek segítségével Windows Phone alkalmazások prototípusát készíthetjük el. Sketchflow-s Projekt sablon a Blend-hez (http://wp7sketchflow.

Ők Anna és Miles (2-13 ábra). Miles pedig építész saját vállalkozásában. pontos definiálásában. Ahhoz. a funkciók. csupán az egyszeri letöltés. A konkurens okostelefon gyártók az alkalmazásokra szó szerint alkalmazásként. hogy az alkalmazások mindössze 10%-a éri meg a használatbavételt követő 100-ik napot.com/products/windows-phone-sticky-pad). A Windows Phone 7 tervezésekor az UX csapat ezt a két fiktív személyt használta a felhasználói igények meghatározásában. Azaz ebben a fázisban ergonómiai szempontokat veszünk figyelembe. Például: a Windows Phone 7 Sketch Padet (http://www.uistencils. Könnyebb és precízebb a tervezés minden fázisa.uistencils. Az alkalmazások nagy részét a letöltést követő pár napban a felhasználók elhagyják. a logikus és helyes működés az elsődleges. perszóna definiálásával. hogy kiemelkedő élményt nyújtsunk. hogy az alkalmazások életciklusa hogyan alakul. amennyiben 35 . de már megjelentek olyan tanulmányok. 2-13 ábra: A Windows Phone 7 átlagos felhasználói Anna sikeres PR szakértő és elfoglalt fiatal anyuka. Élmény vagy alkalmazás Mobilalkalmazás boltok nem olyan régóta léteznek. akár ügyfeleink számára egyértelműen kommunikálhatjuk. Ennek részben a temérdek „egy funkciós” alkalmazás az oka. néhány dolgot szem előtt kell tartanunk! Ismerjük meg a felhasználóinkat! Az alkalmazás fejlesztésekor a célközönség megválasztása és azonosÍtása kulcsfontosságú. melyekben azt elemzik. Saját alkalmazásunk tervezésekor is kiemelkedő szerepe van a célközönség pontos meghatározásának. A legsikeresebb alkalmazások – amelyek folyamatosan a top 50-ben szerepelnek – sok energiát fektetnek felhasználói bázisuk megtartásába és kielégítésébe. A Sketch projektek tervezése elsősorban a felhasználói élmény tervezésről szól. „app”-ként gondolnak. miként fog működni az alkalmazásunk. A Metro Design kialakításakor a Microsoft is meghatározta saját célközönségét két ún. Általános mintaként azonosították. Hogyan érdemes hát nekiállnunk az alkalmazás megtervezésének? Windows Phone alapú rendszerek esetén egy különleges koncepcióval gazdgabbak lehetünk.Élmény vagy alkalmazás Sketchflow-t használva akár saját magunk számára. sokkal inkább integrált élményről. Papíralapú tervezésnél érdemes lehet külső sablonokat felhasználni.com/products/windows-phone-sketch-pad) vagy a Windows Phone 7 Sticky Padet (http://www. Windows Phone alatt azonban nem csupán egyszerű alkalmazásokról van szó. amelyeknek nem céljuk a felhasználói bázis kialakítása.

A korosztály. mint objektumok folyamatos átpozicionálásáról. amelyek vele foglalkoznak. könnyen használható és egyszerűen tanulható. és kívánatos. Releváns tartalom Az alkalmazások élettartamát és életciklusát vizsgáló tanulmányokban a legtovább élő alkalmazások jellemzően a sport. melyek segítségével jó eséllyel népszerű és közkedvelt alkalmazást készíthetünk felhasználóink körében. Windows Phone esetén a mozgás és az animáció a legfontosabb visszajelzése annak. amelyek róla szólnak. naprakész tartalom és ajánlatok. A felhasználói kör számára értékes és érdekes tartalmat próbáljuk szolgáltatni a lehető leggyakoribb rendszerességgel! Személyes alkalmazások Az ember számára a legérdekesebb saját maga. illetve weboldala: releváns. újdonság szolgáltatása nélkül szinte lehetetlen a felhasználóinkat visszavonzani. sokkal sikeresebbek. a felhasználó számára értékes funkcionalitással bír. a közös jellemzők meghatározása jelentősen leegyszerűsítik a tervezés folyamatát. Azok az alkalmazások. hogy a felhasználó mennyire érzi folyamatosan válaszra késznek az alkalmazást. hogy a felhasználói interakciónak virtuális értelemben vett fizikai hatása van. kívánatos A tökéletes alkalmazás hasznos. a nem. A gyors. Gyakorlati Dizájn Mozgás és animáció A Mozgás jelentősége A mozgás és az animáció többről szól. navigáció). személyes. személyre szabott. Jól integrálódik az operációs rendszer megszokott jellemzőivel (pl.és hírközpontú alkalmazások. jó érzés használni. jól használható. A mozgás és az animáció minősége és jellege határozza meg elsősorban. annál nagyobb sikerre számíthatunk! 2-14 ábra: Személyes alkalmazás (Facebook) Hasznos. az ő igényeiről.2. amelyek úgy tesznek. Minél inkább a felhasználó képére tudjuk formálni az alkalmazást. míg a lassú. Friss és értékes tartalom. netán akadozó animációk nagyban rontják a felhasználói élményt. Felhasználói élmény tervezése Windows Phone-on megszemélyesítjük a jellemző felhasználóinkat. Ezek a tényezők együttesen fektetik le azokat a jellemzőket és alapvetéseket. A Windows Phone alkalmazások felhasználói felületén alkalmazott mozgásokat két részre érdemes bontani: 36 . nehézkes. mintha szinte csak neki íródtak volna. Nagyon jó példa erre az Amazon alkalmazása. sima és könnyed animációk ezt az érzetet keltik.

fontos információk közlése (pl. A mozgás karaktert kölcsönöz az alkalmazásnak. ikonok.    Érintés nélkül. magabiztosabban fogja az alkalmazást használni.    Windows Phone 7 specifikus komponensek tervezése A szépség és a konzisztents kinézet a mobil alkalmazások integráns része. informatívabb egy alkalmazás lapkája. majd bezáráskor oda kerül/zsugorodik vissza) A mozgás mint élmény A mozgás a felhasználói élmény kialakításában kulcsfontosságú szerepet játszik. hogy egyedi. míg anélkül – azonnali nézetváltás esetén – esetleg üres képernyő fogadhatja a felhasználót. játszunk vele. az első vizuális elem. stb. Az adatok betöltése. a megjelenés egyik legfontosabb eleme. Ennek megfelelően saját élő lapkákra. A mozgás eleganciát kölcsönöz az alkalmazásnak. gombnyomás. A mozgás konzisztens működéshez vezethet.   A mozgás kellemes a szemnek. Nem titok. de bizony jóval használhatóbbá is teszi az alkalmazást! A lapka az alkalmazás belépési pontja. melyeket szép és megkapó módon célszerű tálalnunk. hogy mely alkalmazásokat jeleníti meg a Start képernyőn. ami számít: koncentráljunk a jelenre. hasznos és különleges legyen (2-15 ábra)! 37 . de szívesen nézzük. annál nagyobb a valószínűsége. a jól megtervezett szép animációk esztétikai élményt biztosítanak az alkalmazás felhasználói számára. vezérlők. Start Menü és a lapkák Windows Phone 7 esetén a hagyományos Asztal és az ikonok koncepcióját felváltotta a Start képernyő és a rajta elhelyezett ún. Átmenetek bevezetésével elrejthetjük ezt az átmeneti időszakot. melynek forrása nem feltétlenül felhasználói tevékenység (például értesítések). mindig valamilyen fontos célt szolgáljanak. értesítések. Így minél dekoratívabb. megértést segítő animációk (pl. hogy „az adott pillanat és az adott hely az. Ha az átmeneteinket ügyesen és egységesen alakítjuk. hogy a telefon használatbavételekor a felhasználót milyen élmény és látvány fogadja. és alapinformációkat közölnek – például öt új olvasatlan levél van a postaládában. melyek az időben változnak. Animáció: Vizuális visszajelzés. melyek az operációs rendszerben található vezérlőkkel azonos működést. akkor az alkalmazást a felhasználó konzisztensnek fogja találni. hogy a Start képernyőre kerülhet. egy kép a helyéről kerül kinagyításra érintés hatására. animálódnak. Ezek gyakorlatilag az ikonokat helyettesítik. releváns információkra. hogy azok ne öncélúak legyenek. koncentráljunk az élményre”. A lapka kinézete jelentősen befolyásolja. Ezek együttesen hívják fel a figyelmet az adott feladatokra. élő lapkák) Felhasználói tevekénységhez kapcsolódó vizuális visszajelzések (pl. A teljes összképet számos komponens együtt határozza meg. a felhasználó dönti el. az információ megjelenítése okozhat némi késleltetést. navigáció) Tanító jellegű. animált ikonokra. A lapkák lehetnek élő lapkák is. 30 fok lesz Budapesten. szép és kellemes Splash képernyőkre van szükség. A Start képernyő átrendezhető. és nagyobb biztonsággal fog a képernyők között navigálni. hogy egyik nézetről másik nézetre váltunk. Ennek megfelelően fontos.Gyakorlati Dizájn   Átmenet (transition): Vizuális visszajelzés arról. Az érintőképernyős felület a legtöbb ember számára szórakoztató és érdekes. élményt nyújtanak. lapkák (tile). Nemcsak tanító hatása van. A Start lapka. Az átmeneteket a felhasználó idézi elő. A mozgások tervezésénél fontos figyelembe venni. A gyors és sima animációk azt az érzést keltik a felhasználóban. a Splash képernyő. amely lehetőleg segítse a felhasználó megértését az alkalmazás működését illetően. A mozgás segíthet a teljesítmény-problémák palástolásában. prioritásokra. Nemcsak vizuális előnyt jelent az élő lapka.

vágáshoz vezethet. színes belső képekkel 2-16 ábra: Helytelen háttérszínek használata lapkáknál 38 . Felhasználói élmény tervezése Windows Phone-on 2-15 ábra: Helyes és helytelen lapka dizájnok A dizájn fontos A lapkák esetén a dizájn a legfontosabb! Az elégtelen minőségű. JPEG vagy PNG formátumban. ellenkező esetben az alapértelmezett lapka kerül átméretezésre. Fontos. ami torzításhoz.2. Az ennél nagyobb vagy kisebb képek átméretezésre kerülnek. melyek a megfelelő Windows Phone témák esetén „transzparens” háttérként funkcionálnak (2-16 ábra) Transzparens háttereket. árnyékok alkalmazását Lekerekített lapkákat Fekete vagy fehér háttereket. felfelé vagy lefelé. gyengén megtervezett és megrajzolt lapkával rendelkező alkalmazás azt is kockáztatja. Különböző képek használata esetén azonban maradjunk minden esetben konzisztensek! A lapkák tervezése során kerüljük el az alábbiakat:      3D-s lapkák használatát A gradiensek használatát. Ezenfelül az alkalmazás listába érdemes külön 63x63 pixeles képet biztosítani. hogy megragadja a szemet! A lapka képeknek 173x173 pixel méretűeknek kell lenniük. hogy a Marketplace-ből kisebb eséllyel kerül letöltésre.

Minden vezérlőhöz saját tervezési és használati útmutató tartozik. 39 . mint az alkalmazás reklámjára. A betöltési idő lehet egy rövid pillanat is. A betöltés során alkalmazunk Splash képernyőket! A Splash képernyő ennek megfelelően a második szint. Ezek a vezérlők a fejlesztők számára is elérhetők az SDK-ban vagy a Toolkiten keresztül. görgethető teljes képernyős konténer. Ez a két vezérlő a Panorama és a Pivot. mint egy magazin főoldalára. hogy a felhasználók használatba vegyék az alkalmazást. Hosszabb szövegek. 2-17 ábra: Splash képernyők alkalmazása Vezérlők használata Windows Phone 7-ben a hagyományos vezérlők mellett számos specializált. A Windows Phone-ra jellemző vezérlők közül kettő kiemelkedik. Fontos tehát a jó betöltő képernyő megtervezése. ahol a legfontosabb. jelentősen meghatározza a felhasználó hozzáállását az alkalmazás többi részéhez. az operációs rendszerre jellemző vezérlő is helyet kapott. így az itt töltött idő és az élmény. A betöltő képernyőn a felhasználó könnyedén eltölthet néhány (max. közvetlenül a lapkák után. Leginkább úgy gondolhatunk rá. ami itt fogadja.Gyakorlati Dizájn Splash képernyő Az alkalmazások indításakor számos inicializációs feladat elvégzésére lehet szükség. mielőtt szembetalálná magát a felhasználó a tényleges alkalmazással (2-17 ábra). legérdekesebb és legizgalmasabb dolgok szerepelnek (2-18 ábra). így nem érdemes komolyabb információt megjeleníteni ezen a képernyőn. A Panorama vezérlő A Panorama vezérlő egy széles jobbra-balra csúsztatható. és alapvetően navigációs modell is egyben. amellyel a felhasználó találkozik. Ilyenkor a felhasználói felület még nem áll készen arra. 10) másodpercet. hangulatfokozóra. melyekkel érdemes mélyebben is megismerkedni. Erre a képernyőre célszerű úgy gondolni. instrukciók elhelyezése teljesen fölösleges.

2. illetve horizontális mozgatással lehetséges. Felhasználói élmény tervezése Windows Phone-on 2-18 ábra: A Panorama vezérlő A Panorama vezérlő messze túlnyúlik a látható területen. A navigáció a menüelemek fejlécét érintve. ezáltal rendkívül látványos. Ez biztosítja a jó teljesítményt és a gyors betöltést. amelyek magukban is görgethetők horizontális irányban! Teljesítmény megfontolások miatt szorítkozzunk maximum négy különböző nézetre egyetlen Panorama vezérlőben! A Panorama címe célszerűen sima szöveg legyen! A Pivot vezérlő A Pivot vezérlő a Windows Phone saját Tab vezérlője. Toggle. Map vezérlők). dinamikus parallaxszerű effektust eredményezve. a felhasználók könnyen elveszhetnek bennük! A Pivot alapértelmezett navigációs mechanizmusát ne írjuk felül! Bizonyos vezérlőket nem célszerű használni a Pivot belsejében (például Slider. illetve 1024x800-as felbontásban. Az animáció során a tartalom és a feliratok különböző sebességgel. időben eltolódva hajtódnak végre. 40 . és biztosítja a navigációt közöttük. Háttér meghatározásakor gondoskodjunk a megfelelő kontrasztról a fontok és a háttér között! Ne menjen a design az olvashatóság kárára! Ne használjunk olyan egyéb vezérlőket a Panorama egyes nézeteiben. Háttérképként jellemzően JPEG ajánlott 480x800-as. elkülönített nézeteket helyez el egymás mellett. A vezérlő önálló. A vezérlő használatakor néhány dolgot célszerű szem előtt tartani:       A hátteret célszerű egyetlen színnel vagy egy óvatosan választott háttérképpel kitölteni. a görgetés során pedig egészen egyedi animációval és tulajdonságokkal rendelkezik. A Panorama vezérlővel ellentétben nem egyetlen nagy téren helyezkednek el az egyes szekciók. valamint az átméretezés elkerülését. A vezérlő használatakor néhány dolgot célszerű szem előtt tartani:      Pivot vezérlőket ne ágyazzunk egymásba! Ne kombináljuk a Pivot és a Panorama vezérlőket! Ne használjunk túl sok Pivot elemet.

Ugyanakkor a kijelzők mérete – okostelefonokról lévén szó – erősen korlátozott. közvetlenül. vizuális visszajelzést kell biztosítanunk. így a ma kapható modern okostelefonok jelentős része ilyen típusú kijelzőket alkalmaz. Az új követelmények Érintőképernyős alkalmazások létrehozásának lehetősége teljesen új távolatokat nyit a szoftveripar szereplői előtt. Interakciós modellek Habár nem beszélhetünk szabványosított modellekről. képet vagy bármilyen objektumot elsőre eltalálni. ergonómus) segítségére is. eddig még nem ismert vagy nem használt interakciós modellek születését teszik lehetővé. Az ilyen típusú felületek új. érintés-kombinációk bevezetése kockázatos lehet.Gyakorlati Dizájn Érintőképernyős alkalmazások tervezése A hardver A kijelzők technológiája rengeteget fejlődött az elmúlt években. így az új típusú modellek kidolgozása során figyelembe kell venni az emberi tényező mellett a méretkorlátokat is. Hosszas használhatósági tesztelés során megállapították. Slide. mint például a Pinch. hogy az eszközöket kapacitív kijelzővel kell ellátni. ha nem tudja az adott gombot. Ellenben számos elfogadott multitouch mozdulat közül választhatunk (2-19 ábra). hogy az ideális célobjektum területe minimum 81mm2-es (9mm x 9mm). Az ilyen nagy lépésekhez a fantázián túl szükség lehet szakember (pszichológus. Ennek megfelelően bizonyos korlátokat célszerű szem előtt tartanunk. A technológia jellemzőinek köszönhetően rendkívül sima és folyamatos élményt lehet biztosítani. 2-19 ábra: Használható gesztusok Windows Phone-on A Windows Phone 7 jelen pillanatban 12 különböző mozdulatot képes megkülönböztetni API szinten. Az egyik. A Windows Phone 7 telefonok követelményei között szerepel. Méretkorlátok az érintőkijelzőn A felhasználó számára a célobjektumokkal történő érintkezést követően. linket. az objektumok közötti szabad területek és a vizuális elemek között. Minimum méretek érintéshez Az érintésre működő felületek kialakítása finom egyensúlyozás a méretek. TapAndHold. és így tovább. a felhasználó számára legfrusztrálóbb negatív élmény. 41 . Az egyik legfontosabb áttörés a kapacitív értintőképernyők megjelenése volt. Pontos és csupán könnyed érintést igényel. Tap. teljesen új mozdulatok.

örömteli perceket szerezhetnek. mind a felhasználóink számára élvezetes. és semmilyen interakcióval nem rendelkezik. Ez az érték csupán a kis vizuális elemekre értendő. A gyakorlati tippek fontos útmutatóként szolgálnak az ergonómiai követelmények kielégítésében. Holt területnek nevezzük azt a szabad területet. Ennél kisebb területet a felhasználók nem fognak interaktívnak tekinteni. a használhatóság vonatkozásában! Összefoglalás Ebben a fejezetben megismerkedtünk a Metro Design legfontosabb elveivel. melyek mind számunkra. azaz „félrenyom”. amely két célobjektum között helyezkedik el. Ilyenkor azonban célszerű a célobjektum szélességét magasabb értékben megállapítani! 2-21 ábra: Ajánlott sormagasság Minimum méretek vizuális elemek tekintetében A vizuális elemeket illetően minden olyan elemnek. amelyet szándékozott. Ezeket az elveket betartva olyan stabil termékek születhetnek. minimum 4. holt terület helyes meghatározása. tipikusan listák esetében. 42 . a 2mm-es minimum jó alsó határértéknek tekinthető. amelyen már a vizuális visszajelzés (lenyomás animáció) is érzékelhető 10-15mm2 között mozog.2mm2-esnek kell lennie. A fenti szempontok figyelembevételével ennek a kockázata jelentős mértékben csökkenthető.2. Az ideális méret. Bár a holt területet célszerű arányaiban megállapítani. A helyzeten tovább javít az ún. A helyes interkaciós modellek megválasztása és támogatása kulcsfontosságú szereppel bír a felhasználói élmény. valamint a dizájnvezérelt tervezés módszerével. itt a minimum korlát a 7mm-es magasság. Ezenfelül az érinthető. interaktív területet is célszerű nagyobbnak választani a vizuális elem területénél. amely érintésre reagál. Vizuális elrendezés A sikertelen találatnál csak egy frusztrálóbb dolog van: amikor a felhasználó nem azt az objektumot érinti meg. Felhasználói élmény tervezése Windows Phone-on 2-20 ábra: Érintéskor a célobjektum ajánlott területe Ennél kisebb objektumok is elképzelhetők.

a Windows Phone 7-re átszabott változatban is két nagyobb részben jelenik meg ennek megvalósítása: a vezérlőkönyvtárban. Aki a WP7-es Silverlight nagytestvérének használata során már találkozott az itt leírt típusokkal és koncepciókkal. A vezérlők kinézetét egy nagyszerű vezérlősablonrendszerrel. ezenfelül pedig könnyedén animálhatjuk azokat. Ennek a fejezetnek az első részében ezekkel az építőelemekkel ismerkedünk meg. összetett felhasználói felületek (a továbbiakban UI – User Interface) kialakításának támogatása. ezért. és megismerkedünk még néhány fontos koncepcióval – például az erőforrások és a témák használatával –. illetve stílusok segítségével változtathatjuk meg. akár őstípusokból való leszármaztatás és a vezérlő teljes funkcionalitásának megvalósítása segítségével. Azonban a felületek kialakítása egyes esetekben eléggé fájdalmas tud lenni a VS használatával. Mivel már rengeteg könyv megjelent Silverlight 4 témában. A Silverlight UI-építést és -működést támogató részének másik része azoknak a szolgáltatásoknak a halmaza.3. adatfüggő felületeket. A fejezet során végig az Expression Blend 4 segítségével hozzuk létre és szabjuk testre a felületeket. amelyek segítségével a legegyszerűbbtől a legbonyolultabb üzleti alkalmazásokig bármilyen felhasználói felületet átlátható. Előbbiben értelemszerűen a vezérlőket találjuk. Különböző vizuális állapotokat hozhatunk létre. könnyen használhatóvá teszik a vezérlőket. hogy kiterjesszük azokat – új tulajdonságokat. Ebben a fejezetben ezeket a témaköröket nézzük meg közelebbről. A Visual Studio 2010 elsősorban a fejlesztőknek készült. akár a teljes felület bizonyos helyzetekben felvett megjelenítését írhatjuk le központi. Az adatkötésirendszerrel és az adatsablonok használatával pedig rengeteg kódot megspórolva építhetünk dinamikus. akár több már meglévő elem együttes használatával. 43 . amelyekkel akár az egyes vezérlők. Ahogy a Silverlight „asztali” verziójában is. Szerencsére a Microsoft nagy hangsúlyt fektet a különböző technológiái közötti átjárhatóságra és a hordozható tudásra. egységes módon. amelyek testre szabhatóvá. Az Expression termékek elsősorban a dizájnereknek készültek – ahogy a Silverlight elődjét. és lehetőséget adnak arra. illetve saját vezérlőket hozzunk létre. ez a fejezet csak egy gyors. tökéletes választás a fejlesztés teljes életciklusának felügyeletéhez a kezdeti kódírástól a tesztelésig és a telepítésig. hogy segítsék a dizájnerek és a fejlesztők együttműködését. a Windows Presentation Foundationt is azzal a céllal hozták létre. izgalmassá. de korábban megszerzett tudása azonnal és közel száz százalékosan átvihető WP7-re. ahogy látni is fogjuk. Többek között a VS ezen gyenge pontját ellensúlyozandó hozta létre a Microsoft az Expression termékcsaládot. A Silverlight alapú fejlesztésre – mint azt a korábbi fejezetek már említették – két eszközt is biztosít számunkra a Microsoft. illetve a keretrendszer UIhoz kapcsolódó szolgáltatásaiban. Alkalmazásfejlesztés Windows Phone-on Az eredetileg RIA fejlesztésre kialakított Silverlight keretrendszer talán legfontosabb alapgondolata a gazdag tartalmú. hogy a korábbi UI-keretrendszerek által biztosított lehetőségeknél jóval több mindent tehessünk meg – sokkal kisebb erőfeszítéssel. az is találhat néhány új dolgot (például az InputScopeok). kézre álló módon felépíthetünk. áttekintő összefoglalást kíván adni. Az itt ismertetett vezérlők használatán felül a vezérlők osztályhierarchiájának kialakítása lehetővé teszi. sok minden megegyezik az „asztali” Silverlighttal. Ezek azok az alapvető építőelemek. és az ezekben leírtak komolyabb változtatások nélkül alkalmazhatók Windows Phone 7-fejlesztésben is. amelyek a felületek építéséhez elengedhetetlenek. viselkedést adjunk nekik –.

A bal oldali listából a Windows Phone pontot. majd áttérünk a szövegmegjelenítésre és a szövegbevitelre. 3-2 ábra: Sablon kiválasztása 44 . a jobb oldalon pedig a Windows Phone Application projektsablont kell választanunk. A ListBox osztályon keresztül áttekintjük a listavezérlők általános használatát. mind az Expression Blend 4 rendelkezik ingyenes.3. 3-1 ábra: Új projekt létrehozása Expression Blenddel A megjelenő ablakban választhatjuk ki. kiválaszthatjuk a projekt fizikai helyét a merevlemezen.1). illetve beállíthatjuk a Windows Phone verziót (7. hogy milyen projektet szeretnénk létrehozni. amelyek részét képezik a WP7 fejlesztői csomagnak. kifejezetten WP7-fejlesztésre kihegyezett verzióval. illetve segítséget kérhetünk a program használatával kapcsolatban (Help fül). A legtöbb programnál szokásos főmenü itt is elérhető. amint azt a 3-2 ábra mutatja. Alul nevet adhatunk az alkalmazásnak (BaseControlsSample). Alkalmazásfejlesztés Windows Phone-on Megjegyzés: mind a Visual Studio 2010. a Close gombbal (Alt+C) bezárhatjuk az alkalmazást. A Samples fülön mintaalkalmazásokat tekinthetünk meg. érjük be a C#-pal). A File menü New Project menüpontjára kattintva hozhatunk létre új projektet (3-1 ábra). Az egyszerűség kedvéért egyetlen alkalmazáson belül helyezzük el ezeket a vezérlőket. illetve megadhatunk egyéb beállításokat. amelyen létrehozhatunk új projektet vagy megnyithatunk egy már létezőt. nyelvet választhatunk (főtt marha nincs. Alapvető WP7 vezérlők Ebben a részben először az alapvető parancskiadási vezérlőkkel foglalkozunk. Hozzunk is létre egy alkalmazást a Blend 4 segítségével! Az Expression Blendet a Start Menü az All Programs menüpontban a Microsoft Expression mappában találjuk. Elindítása után egy nyitóképernyő fogad.

Alatta találhatók az elrendezés-vezérlők (Grid. szerkeszteni). A nagyító ikon segítségével nagyíthatunk a felület egy részére.7720. A toolbox legalsó eleme jelen pillanatban egy dupla. hogy nem egy eszközről van szó. Lejjebb. Ha közelebbről megnézzük. Erre kattintva érjük el az ún. Az OK gombra kattintva a Blend létrehozza a projektet. amelyeknél van ilyen nyíl. négy részre osztott négyzet ikon).5-ösként reklámozott OS belső verziószáma 7. mint a Visual Studio.68. Ha kiválasztunk valamit az Asset Library-ban. ahonnan egyéb. a toolboxon nem szereplő vezérlőket és egyéb felhasználható típusokat érhetünk el. illetve egyéb gyakran használt vezérlők (gomb ikon). hanem egy csoportról. hanem a C:\Users\<felhasználónév>\<dokumentumok>\Expression\Blend 4\Projects mappában! A választott 7. A tetején a kiválasztáshoz szükséges kurzorok foglalnak helyet (ezek használatával tudunk valamit közvetlenül a tervezőfelületre kattintással kiválasztani.Alapvető WP7 vezérlők Tartsuk észben.10. Lejjebb. hogy a Blend alapbeállításként nem ugyanabban a könyvtárban hozza létre a projekteket. hanem minden a felület kialakításával kapcsolatos eszközt tartalmaz. Ismerkedjünk meg a felülettel. a 45 . a harmadik csoportban találjuk a primitív vezérlőket szimbolizáló egyszerű négyszöget. a szövegvezérlők (keretes T betű). Azoknál az ikonoknál. Asset Library-t.1-es OS verzió ne tévesszen meg senkit! A Mangóként ismert. 7. amelynek elemeit a 3-3 ábra mutatja be! 3-3 ábra: Az Expression Blend felületének részei 0: A menüsor 1: A toolbox (szerszámosláda) Ez jelentősen eltér aVisual Studióban megszokottól: nem egyszerűen a vezérlők listája. jobbra mutató nyíl. a kéz ikonnal tudjuk egyszerűen görgetni a tervezőfelületet. annak ikonja a duplanyíl alatt jelenik meg. néhány ikon jobb alsó sarkában egy kis nyilat vehetünk észre – ez azt jelenti.

eltűnt. a Silverlight Toolkit használata nélkül háromféle elrendezés-vezérlő áll rendelkezésre a Windows Phone 7-ben: a táblázatos elrendezést lehetővé tévő Grid. akkor a gomb kitölti majd a teljes oldal felületét – leszámítva az ApplicationBar és az ún. ha a tervezőfelületen kijelöljük az új vezérlő helyét. A tervezőfelület jelentős részét az oldal interaktív megjelenítő felülete foglalja el. Ha úgy döntünk. A megjelenítőtől jobbra. hogy az animáció indulása utáni adott időpillanatban hogyan nézzen ki a felület. 3: Objects and Timeline Alapesetben itt láthatjuk az alkalmazásunk egy oldalának (PhoneApplicationPage) vizuális hierarchiáját. TextBox.3. illetve itt adhatjuk meg azt is. minimális helyigény alapján felsorakoztató StackPanel. PasswordBox. hogy az itt kiválasztott vezérlőt tudjuk létrehozni. amelyet használni szeretnénk. 5: Tulajdonságok és adatok A Properties fülön állíthatjuk be a kiválasztott vezérlő tulajdonságait. mely a TextBlockot hivatott jelképezni. Alkalmazásfejlesztés Windows Phone-on jobb egérgombbal kattintva előhívhatjuk a helyi menüt.microsoft. Kattintsunk a jobb gombbal például a keretes T betűre (szövegvezérlők)! Az ikon mellett megjelenő lista négy eleme: TextBlock. Ahhoz.aspx 46 . elrendezés-vezérlőre (layout control) lesz szükségünk. Az elrendezési rendszerről és vezérlőkről szóló további információkért érdemes az alábbi linkről elindulni: http://msdn. egy LayoutRoot nevű elem a legfelső vezérlő. alatta pedig az ún. „breadcrumb”. a XAML-nézet és az osztott nézet között. és itt iratkozhatunk fel az eseményekre. Alapesetben. Mivel az elrendezés futásidejű működése megegyezik az „asztali” Silverlightéval. felül három ikont találhatunk. itt nem térünk ki rá bővebben. pixel alapú pozicionálást lehetővé tevő Canvas. és látható. egy animáció vagy VisualState szerkesztésénél pedig itt jelenik meg az idővonalat (timeline) ábrázoló ablak.95). A Resources fülön találjuk az alkalmazás erőforrásainak listáját (ezekről később bővebben is szót ejtünk). hogy ez például egy gomb lesz. hogy ne csak egyetlen vezérlőt helyezhessünk el az oldalon.com/en-us/library/cc645025(v=vs. mellyel beállíthatjuk. Egy sablon szerkesztése esetén itt láthatjuk a sablon felépítését. Ezek a vezérlők azt teszik lehetővé. Ennek annyi a jelentősége. és azzal kiválaszthatjuk az eszközt. Ahogy a 3-3 ábrán is látható. és helyette a PasswordBox ikonja jelent meg. system tray által elfoglalt részeket. Ezen helyezhetjük el és méretezhetjük át a vezérlőket. A Data fül alatt a projekt adatforrásai találhatók. 4: A tervezőfelület Legfelül az éppen nyitva lévő fájlok listája látható (jelenleg csak a MainPage. Kattintsunk a PasswordBoxra (ezúttal a bal egérgombbal). A Device fül segítségével pedig az alkalmazásainkat futtató emulátor orientációját és témáját állíthatjuk be. azaz éppen semmi sincs kiválasztva). mely a Silverlight felülettel kapcsolatos típusokat gyűjti össze. ami a VS Solution Explorerének helyi verziója: ebben találjuk meg a projektet alkotó összes fájlt és könyvtárat. RichTextBox. 2: A fejlesztési ablak Legelső füle (a sorrend megváltoztatható) a Projects. hogy több gyermekvezérlőt is elrendezhessünk az elrendezés-vezérlő által lefoglalt területen. hogy a keretes T betű. ebben helyezhetjük el a tartalmat. A States fülön találhatjuk meg és szerkeszthetjük a kiválasztott vezérlő vizuális állapotait – erről később szó lesz még. ami azt mutatja. hogy éppen milyen elemet választottunk ki (a fenti képen Nothing Selected. és a vezérlőket egymás alá vagy egymás mellé. és rendszerezi. valamint referenciákat a külső szerelvényekre. Az oldal tartalmaként mindössze egyetlen vezérlőelemet adhatunk meg. ezek segítségével válthatunk a tervezési nézet. hogy a teszteléshez az emulátort vagy egy fizikai eszközt szeretnénk-e használni.xaml). Második füle az Assets. illetve itt hozhatunk létre teszteléshez használt adatforrást. a Windows Formsból (vagy korábbról) már ismerős.

azaz védeni a véletlen módosításoktól. hogy valaki ténylegesen egyetlen vezérlőt akarjon elhelyezni alkalmazása felületén. Ahogy az a 3-4 ábrán látható. Mivel több vezérlőt is szeretnénk elhelyezni az alkalmazáson – pontosabban a ContentPanelen – belül. a Silverlight Phone Application projektsablon rögtön egy teljes vizuális hierarchiát épít fel a felületen. hogy az alkalmazás illeszkedjen a sok másik által kialakított jól felismerhető sémába. hogy a „<No Name>” felirat szerepel ebben a szövegdobozban. hogy a vezérlőktől jobbra látható két piktogrammal tudunk eltüntetni egy-egy vezérlőt a tervezőfelületről. 47 . A név mellett találjuk a tulajdonságok és az események között váltó két gombot. amely az alkalmazás felső részét írja le: az alkalmazás nevét („MY APPLICATION”) tartalmazó TextBlockot. Ezt úgy tehetjük meg. a LayoutRoot két elemet tartalmaz. hogy kijelöljük azt. 3-4 ábra: Az Objects and Timeline panel A TitlePanel nevű gyermekelem egy StackPanel. Mindezek alatt pedig a keresődoboz helyezkedik el. illetve mert a Silverlight vezérlői tényleg nagyon sok tulajdonsággal rendelkeznek. Előfordulhat. Mielőtt azonban elvesznénk a millió tulajdonság között. majd a Properties panelen megkeressük annak RowDefinitions illetve ColumnDefinitions tulajdonságait. Ha az Objects and Timeline ablakra nézünk. érdemes madártávlatból is szemügyre venni a Properties panelt! Ahogyan azt a 3-5 ábra mutatja. Az Objects and Timeline ablakban kattintsunk jobbal a lecserélni kívánt vezérlőre. Ha nincs különleges igényünk. Észrevehetjük. A tervezőfelületre pillantva érezhető.Alapvető WP7 vezérlők Tipp: ha utólag rájövünk. nem kell XAML-t túrni a cseréhez. Bár a kezdeti időkben nem túl gyakran kerülnek elő. de a struktúrához nem kell hozzányúlnunk. ugyanis a Silverlightban nem feltétlenül kell egy vezérlőnek nevet adni. láthatjuk ennek gyökérelemét. esetleg szeretnénk. érdemes tudni. a jobb oldalon lévő Properties panel tartalma azonnal frissül. meg kell adnunk a ContentPanelnak. illetve az alatta lévő oldalnevet („page name”). akkor elég. hogy itt ennél bonyolultabb struktúrának kell lennie – a LayoutRoottól balra lévő apró nyílra kattintva megtekinthetjük a Grid belsejében lévő felületi elemeket is. ha megváltoztatjuk a két TextBlock tartalmát. amely történetesen egy Grid. Ez az egyetlen tartalma az oldalunknak. A ContentPanel nevű gyermekelem a leginkább érdekes rész: ebben a Gridben helyezhetjük el a tényleges tartalmat adó és funkciót szolgáló vezérlőket. hogy a vezérlőkre kattintgatva az Objects and Timeline panelen (vagy valamelyik nyíl alakú kurzorral magán a tervezőfelületen). legfelül a kijelölt objektum nevét láthatjuk – ezzel a névvel hivatkozhatunk a vezérlőre a mögöttes kódban. mivel a szűrés kellőképpen intelligens (nemcsak a tulajdonságok nevének kezdete alapján szűrhetünk). és válasszuk ki a Change Layout Type pont alatt a megfelelő típust! Mivel viszonylag ritka az a helyzet. illetve zárolni. Érdemes ezt használnunk. alatta pedig a kijelölt elem típusát. hogy hány oszlopból és sorból álljon. illetve egyéb helyeken a XAML-ben. hogy egy nem megfelelő típusú elrendezés-vezérlőt helyeztünk el a felületen. a LayoutRoot nevű vezérlőt.

A másik. amelyek nélkül nincs élet a Silverlightban! 48 . amelyeket elsőre könnyű nem észrevenni. hogy sok tulajdonságtól jobbra egy kis négyzet található. hogy a csoportok alján található egy lefelé mutató nyíl. akkor kézzel állították be valamilyen értékre. akkor a tulajdonság az alapértelmezett értékén áll. Itt két dologról is érdemes szót ejteni. hanem funkcióval is bír! Az Advanced options „gomb” segítségével hozhatunk létre adatkötést (esetleg erőforráshoz kötést) az adott tulajdonság kapcsán. ha fehér. ezzel érhetjük el a ritkábban használt tulajdonságokat.) A gomb színe is jelentőséggel bír: ha szürke. Ez nemcsak dizájnelem. hogy a tervezőfelületen is megjelennek a cellák határoló vonalai. 3-6 ábra: Hat egyforma cellára bontott ContentPanel Grid Ennyi áttekintés után vegyük sorra azt a néhány alapvető vezérlőt. ha sárga. és így tovább. Az egyik. ha hozzáadunk a RowDefinitions és a ColumnDefinitions tulajdonságokhoz két oszlopot és három sort. Visszatérve a ContentPanelre. ahogyan azt a 3-6 ábra mutatja. Alkalmazásfejlesztés Windows Phone-on 3-5 ábra – A Properties panel A keresődoboz alatt találjuk a tulajdonságokat – értékeikkel egyetemben — csoportokra osztva.3. illetve egyebek mellett alapértelmezett értékre is visszaállíthatjuk a tulajdonságot. valamilyen adatkötésből kapja az értékét. hat egyforma cellára bontják a felületet. látható. (Az adatkötésről és az erőforrásokról a későbbiekben lesz szó.

Alapvető WP7 vezérlők Parancsvezérlők A Button vezérlő használata A Toolboxon duplán a Button ikonjára kattintva (3-7 ábra). Az első. hogy pontosan melyik elrendezés vezérlőbe. A Properties panelen a Content tulajdonság melletti szövegdobozban írhatjuk át a gomb feliratát. hogy alapbeállításként a Blend a Margin tulajdonság segítségével méretezi a vezérlőt. hogy a felhasználó rákattinthat (illetve. a tervezőfelületen nem jelenik meg a teljes szöveg. hogy a tartalmazó vezérlő (a ContentPanel nevű Grid [0. ez a tulajdonság viszont System. Ennek a módszernek többek között az az előnye. hogy egy összetettebb vizuális hierarchiában a Blend néha eltéveszti. 49 . annak felirata. A ContentControlból származó vezérlők közös ismérve. hogy ha túl hosszú feliratot rendelünk a gombhoz. hogy egyetlen tartalmat tudnak fogadni – Content tulajdonságukon keresztül –. Hátránya viszont. rátapinthat). ahogyan azt a 3-8 ábra is mutatja: 3-8 ábra: A Button Content tulajdonságának átállítása a Properties panelen Észrevehetjük. tehát bármilyen objektumot felvehet értékéül. hogy egyszer kattintunk az ikonjára. Ennek oka. megjelenik egy gomb az alkalmazás felületén. Canvas használata esetén viszont ez a módszer nagyon hasznos. Alapértelmezés szerint abban a vezérlőben jelenik meg az új elem. egy Grid esetén melyik cellá(k)ba is akartuk helyezni az új vezérlőt. majd a pluszjel formájúra változott kurzorral megrajzoljuk a felületen. A Button a ContentControl ősosztályból származik.0] cellája) széleitől mekkora távolságot tartson a vezérlő (3-9 ábra). hogy rögtön meghatározhatjuk a vezérlő pontos pozícióját. amit szokás átállítani egy gombon.Object típusú. vagyis meghatározza. mivel érintőképernyős eszközről beszélünk: megérintheti. illetve méretét. A Button az elsődleges parancsvezérlő: funkciója általában mindössze annyi. és ennek hatására lefuttathatunk egy eseménykezelő metódust a mögöttes kódban. 3-7 ábra: A Buttont jelölő gomb a Toolboxon Vezérlőt úgy is létrehozhatunk. melyet az Objects and Timeline ablakban kijelöltünk.

és itt a Click felirat melletti szövegdobozba való dupla kattintással készíttethetjük el az eseménykezelőt a Blenddel (3-12 ábra). (Esetünkben ez btnOne lesz. a gomb szélesebb lesz. a Blend átvált az aktuális oldal mögöttes kódjára. széltében kitölti a cellát (3-11 ábra). 50 . amellyel megvalósíthatjuk az elvárt működést. hogy nevet kapjanak a vezérlők. Itt kapcsolhatjuk azt a kódot a felülethez. A Properties panel tetején válthatunk át eseménynézetbe.3. hogy gombunk még nem rendelkezik névvel. Alkalmazásfejlesztés Windows Phone-on 3-9 ábra: A túl kicsi gomb és a Margin esete Ha az Advanced options segítségével alaphelyzetbe állítjuk a Margint (3-10 ábra). a Button Click eseményéhez kell hozzárendelnünk egy eseménykezelő metódust. Alapértelmezés szerint nem kell. 3-12 ábra: A Properties panel átkapcsolása esemény-nézetbe Ahogy elkészül a metódus – melynek neve meg is jelent a Click mellett –. 3-10 ábra: A Margin alaphelyzetbe állítása az Advanced options Reset parancsának segítségével 3-11 ábra: Gomb.) Ahhoz. akkor érdemes nevet adni nekik. Marginok nélkül Azt is észrevehetjük. amikor a felhasználó megnyomja a gombot. hogy valamilyen kód lefusson. viszont ha hivatkozni szeretnénk rájuk a mögöttes kódban.

A Devices panel beállításai szerint a Blend vagy a WP7 emulátort indítja el. (Az Open source MVVM frameworks c. } private void btnOne_Click(object sender.Windows. majd az előbb elkészült eseménykezelőben megnövelem az értékét. Ehhez először létrehozok egy System. System. vagy a PC-hez csatlakoztatott telefonra telepíti az alkalmazást. rész alatti linkeket érdemes megnézni. Egy önállóan megírható alkalmazás elkészítésének leírása Silverlight MVVM-mel itt van részletesen leírva: http://www.net/learn/advanced-techniques/the-mvvm-pattern/using-the-mvvm-pattern-insilverlight-applications.Alapvető WP7 vezérlők A bonyolultabb programoknál érdemes szeparálni a felület mögötti logikát és a tényleges üzleti logikát. Ebben az MVVM (Model-View-ViewModel) alkalmazásfejlesztési minta lehet segítségünkre.Int32 típusú változót az oldal mögöttes kódjában. Josh Smith WPF-guru cikke az MVVM-ről WPF alatt itt található: http://msdn. és átadom a gombnak mint tartalmat. hogy amikor megnyomják. Ennek leírása túlmutat e könyv határain.wikipedia.org/wiki/Model_View_ViewModel linken található.microsoft.RoutedEventArgs e) { taps++. A teljes kód – leszámítva a using direktívákat – így néz ki: namespace BaseControlsSample { public partial class MainPage : PhoneApplicationPage { int taps = 0.) Itt annyit fog tenni a gomb.Content = taps.aspx. Az ismertebb MVVM-keretrendszerek leírása a http://en. Ahogy az alkalmazás elindult. 3-13 ábra: A program az emulátoron futtatva 51 . } } } Az alkalmazás futtatásához vagy megnyomjuk az F5 billentyűt. btnOne. növel egy számlálót. illetve több keretrendszer is létezik implementálására. a gombot nyomogatva növekszik az érték (3-13 ábra). public MainPage() { InitializeComponent().silverlight. aztán annak aktuális értékét megjeleníti a gombon. vagy kiválaszthatjuk a Project menüből a Run Project menüpontot.com/en-us/magazine/dd419663.

ahogyan azt a 3-14 ábra mutatja. ezután arra a Marketplace megkerülésével is telepíthető alkalmazás. tehát pl. Közvetlenül ezt nem tehetjük meg. Alapértelmezésként itt az alkalmazásban lévő PhoneApplicationPage-eket látjuk. 52 . a keresődoboz segítségével gyorsan megtalálható a HyperlinkButton vezérlő. Ezzel feloldjuk a zárolást.hu. 3-15 ábra: A HyperlinkButton elhelyezése a felületen Akárcsak a Button. ahová navigálni szeretnénk.com/) Windows Phone fejlesztőként. Szintén a Properties Panel Common Properties csoportjában található a NavigateUri tulajdonság. A HyperlinkButton alapértelmezésben nem található meg a Toolboxban.: http://devportal. de az Advanced options négyzetre kattintva kiválaszthatjuk a Custom Expression menüpontot. fejlesztői telefonná tesszük az eszközt.msdn. amely ezután egy kattintással helyezhető el a Toolboxon. (Protokollal együtt kell megadni.) Ahhoz. hogy a navigáció működjön. amellyel szabadon szerkeszthető az érték (3-16 ábra). és megadni telefonunk gyári azonosítóját. de beírhatunk egy webcímet is. A Toolbox alján lévő dupla nyílra kattintva megjelenik a fent nevezett ablak. és a HyperlinkButton megkeresése A Toolbox új elemére duplán kattintva megjelenik egy HyperlinkButton a felületen.3. be kell állítanunk a TargetName tulajdonságot is „_blank”-re. ez a vezérlő is a ContentControlból származik. Alkalmazásfejlesztés Windows Phone-on Nem telepíthetünk minden telefonra alkalmazásokat a Marketplace megkerülésével. Ennek segítségével állítható be az oldal. ami kattintás hatására végrehajtja a hozzárendelt kódot. ezért az Asset Library segítségével kell előkeríteni. Tulajdonképpen működése nem sokban különbözik a Buttonétól: valami. amelyet aztán a kurzor segítségével elhelyezhetünk (3-15 ábra). A HyperlinkButton vezérlő használata A HyperlinkButton vezérlő a webes hivatkozások megfelelőjének tekinthető. Be kell regisztrálnunk magunkat az App Hubon (http://create. 3-14 ábra: Az Assets panel megnyitása. tartalmát a Content tulajdonsággal szabályozhatjuk.

megnyílik az Internet Explorer. hogy a jelölőnégyzetet bejelölték-e. RoutedEventArgs e) { MessageBox. a legjobb választás a CheckBox. amikor a jelölőnégyzet állapota megváltozik. A Toolboxon ugyanabban a menüben található. köztes állapotba kerülés esetén) és Unchecked (bejelölés törlése esetén) eseményekre iratkozhatunk fel. és betöltődik a NavigateUri-ban megadott webcím. ha például nem akarjuk. A CheckBox használata Ha szeretnénk felkínálni a lehetőséget a felhasználónak. és a mögöttes kódban tetszőleges kódot végrehajthatunk. Ha az IsThreeState tulajdonság igaz (true) értékű. mert például azt dinamikusan szeretnénk előállítani. azaz jelölőnégyzet. Ez hasznos lehet. hogy így. határozatlan (indeterminate) állapotot is. deklaratívan megadjuk a navigáció címét. vagy felvehessen-e egy harmadik. de csak programozottan. ugyanakkor nem szeretnénk azt sem. hogy melyik állapotba kellene állítani alapértelmezetten a jelölőnégyzetet. akkor a Buttonnál látott módon feliratkozhatunk a Click eseményre. 3-17 ábra: A CheckBox beállítása private void cbGenderIsMale_Checked(object sender. a Content tulajdonságon keresztül változtatható meg. a jelölőnégyzet három állapotot vehet fel. Utóbbival azt szabályozhatjuk. Ha szeretnénk valamilyen kódot futtatni. akkor is felveheti a harmadik állapotot. Indeterminate (eldöntetlen. hogy szabályozza a program működését. hogy a felhasználó utólag visszaállíthassa köztes állapotba. hogy a jelölőnégyzet kétállapotú legyen. a Checked (bejelölés esetén).Alapvető WP7 vezérlők 3-16 ábra: A NavigateUri és a TargetName beállítása Ha ezek után elindítjuk a programot. vagy nem tudjuk előre megmondani. } 53 . és megérintjük a linket. A CheckBox felirata. ahogy a már bemutatott vezérlőknél is. Legfontosabb tulajdonságai az IsChecked és az IsThreeState. a felhasználó már nem állíthatja vissza köztes állapotba. Ha nem elég. ahol a Button.Show("Herbert Garrison"). Előbbi megmondja. engedélyezzen vagy letiltson valamilyen opciót. Ha hamis (false) értékű.

Show("Liane Cartman"). ha a felhasználó több lehetőségből egyet választhatna.Windows. btnOne. Unchecked. ha pedig nem. A RadioButton legfontosabb tulajdonságai és eseményei nevükben és működésükben is megegyeznek a CheckBoxnál látottakéval (Content.Show("Sheila Broflovski").Content = taps. } Mind a CheckBox. Indeterminate). úgy. IsThreeState. mind a RadioButton IsChecked tulajdonsága Nullable<Boolean> típusú. } A RadioButton használata A CheckBox vezérlőkkel egyes lehetőségek egymástól független ki.3. else taps--. Alkalmazásfejlesztés Windows Phone-on private void cbGenderIsMale_Unchecked(object sender.RoutedEventArgs e) { if ((bool)rbIncrement. Az alábbi példában a korábban elkészített Button eseménykezelőjét módosítjuk úgy. 3-18 ábra: A RadioButton tulajdonságainak beállítása Ha több csoportba szeretnénk rendezni a rádiógombokat. csökkenti azt (3-19 ábra). RoutedEventArgs e) { MessageBox. 54 .IsChecked) taps++. Ezért kell előbb Booleanné alakítani.vagy bekapcsolását adhatjuk a felhasználó kezébe. RoutedEventArgs e) { MessageBox. System. } private void cbGenderIsMale_Indeterminate(object sender. hogy true/false-ként vizsgálhassuk az értékét. A mögöttes kódban a RadioButtonök IsChecked tulajdonságát figyelembe véve írhatjuk meg a program logikáját. Checked. hogy minden csoportban kölcsönösen kizárják egymást a lehetőségek. Előfordul azonban. Ilyen esetekben használhatjuk a RadioButtont (rádiógomb). azaz a true és false értékén kívül null értéket is felvehet. hogy azt szeretnénk. private void btnOne_Click(object sender. IsChecked. növeli az értéket. GroupName tulajdonságuk segítségével csoportosíthatjuk őket. hogy ha az rbIncrement választógombot jelöli be a felhasználó. de a különböző csoportokban lévők között már ne legyen kapcsolat.

amelynek nem kell szöveget megjelenítenie. Vegyük szemre a PageTitle nevűt! A TextBlock által megjelenített szöveget a Text tulajdonság segítségével adhatjuk meg (3-20 ábra). aláhúzott) betűformázási lehetőségeket is megkapjuk (3-21 ábra). A Silverlightban erre elsősorban két vezérlőt használunk: egyszerű szövegmegjelenítésre a TextBlockot. a betűk méretét. Egyszerű szövegmegjelenítés a TextBlockkal Ahogy korábban láttuk. bonyolultabban formázott megjelenítésre pedig a RichTextBoxot. a Windows Phone Application sablon rögtön két TextBlockot is beépít alkalmazásunk felületébe. illetve a szokásos (félkövér.Alapvető WP7 vezérlők 3-19 ábra: Parancsvezérlők a felületen Szövegmegjelenítési vezérlők Nagyon kevés olyan program van. dőlt. Egyebek között átállíthatjuk a betűtípust. 55 . 3-20 ábra: A TextBlock szövegének beállítása A Text csoportban található tulajdonságok segítségével szabhatjuk testre a szöveg kinézetét.

Alkalmazásfejlesztés Windows Phone-on 3-21 ábra: A TextBlock szövegének tulajdonságai Előfordulhat. 3-23 ábra: Túl hosszú szöveg TextTrimminggel kezelve A másik lehetőség. amelyek már nem férnek ki. Általában érdemes elkerülni. Ennek eredményeképpen. de erre nem mindig van lehetőség. hogy a TextWrapping tulajdonságot Wrap értékre állítjuk. vagyis a vége nem jelenik meg (3-22 ábra). és nem fér ki a TextBlock rendelkezésére álló helyen. hogy a szöveg túl hosszú. levágja azokat a szavakat. 3-22 ábra: Túl hosszú szöveg Két dolgot tehetünk. a következő sorba kerül (3-24 ábra). Az első.3. hogy kiküszöböljük ezt a problémát. Ilyenkor alapértelmezésként egyszerűen „kicsúszik”. hogy a TextTrimming tulajdonságot None értékről WordEllipsis értékűre állítjuk. és három ponttal helyettesíti őket (3-23 ábra). 3-24 ábra: Túl hosszú szöveg TextWrappinggel kezelve 56 . hogy túl sok szöveg kerüljön egy TextBlockba. Amikor egy szó már nem fér ki. amikor a TextBlock túl sok szöveget tartalmaz. Ennek hatására a TextBlock több sorban próbálja meg elhelyezni a szöveget.

Amint elhelyezünk egyet a felületen. ha a Text csoportban lévő földgömb gombra kattintunk (3-27 ábra). – a vezérlőt. hogy egy szövegbeviteli vezérlőről lehet szó. Amellett. csupán arra ad lehetőséget. ahol egyszerre látjuk a tervezőfelületet. 3-25 ábra: Többféleképpen formázott szöveg egy RichTextBoxban A RichTextBoxot a szövegvezérlők csoportjában találjuk a Toolboxon. tartalma rögtön szerkeszthetővé is válik (3-26 ábra). hogy hivatkozássá alakítsuk 3-27 ábra – A Create Hyperlink gomb és ablak Ahogy korábban a HyperlinkButton esetén. és a XAML-t. Sőt. kézzel kell beleírni a XAML-be. képek stb. rögtön hivatkozást is befűzhetünk a szövegbe. hogy a TextBlockkal ellentétben nem csupán egyféle formázást adhatunk az egész szövegnek. hanem akár karakterenként mást és mást (3-25 ábra). hogy a hivatkozás tudja. és átállíthatóak jellemzői. itt is meg kell adnunk a TargetName tulajdonságot. hogy programozottan töltsük fel szöveggel. a RichTextBox igazi előnye. 57 . Sajnos erre a tervezőfelületen belül nincs lehetőség. milyen linket kell megnyitni. A tervezőfelület jobb felső sarkában találjuk a nézetváltó ikonokat (3-28 ábra). A RichTextBox WP7-es implementációja nem teszi lehetővé szöveg bevitelét vagy szerkesztését a felhasználó számára. hogy az egyszerű szövegeknél bonyolultabb elemeket is meg tud jeleníteni. A szöveg bármely része kijelölhető. 3-26 ábra: A szöveg egy részének kijelölése. a legalsóval válthatunk osztott nézetbe. illetve egyéb elemekkel – hivatkozások.Alapvető WP7 vezérlők Formázott szövegek megjelenítése a RichTextBoxszal A RichTextBox neve azt sugallja. a helyzet azonban — legalább is jelen pillanatban — nem ez.

de legáltalánosabb adatbeviteli vezérlő mindig is a TextBox marad. vagy éppen választhat lehetőségek közül. Ha ezek után fut az alkalmazás. és a felhasználó különböző parancsokat futtathat. a link már jól fog működni – ha megérintik. De gyorsan szembe kerülünk azzal az igénnyel. 3-29 ábra – Osztott nézetben egyszerre látjuk a tervezőfelületet és a hozzá tartozó XAML-t Szövegbeviteli vezérlők Szövegeket kiírni már tudunk. és TargetName tulajdonságának a „_blank” értéket kell adni. hanem ő maga adhasson meg valamilyen bemenetet. megnyílik az Internet Explorerben a megadott weblap. hogy megkönnyíthessék a felhasználói adatbevitelt. amit a program fel tud dolgozni.3. hogy ne csak a felkínált lehetőségek közül választhasson. Alkalmazásfejlesztés Windows Phone-on 3-28 ábra: A tervezőfelület jobb felső sarkában található nézetváltó gombok A XAML-ben meg kell keresni a Hyperlink elemet. 58 . A Silverlight számos speciálisabb vezérlőt kínál a fejlesztőknek.

3-30 ábra – A TextBox helye a szövegvezérlők között. illetve kódból itt állíthatjuk be a szövegdoboz szövegét. Az IsReadOnly tulajdonságával tehetjük csak olvashatóvá a szövegdobozt – ilyenkor a felhasználó nem állíthatja át a beleírt szöveget. avagy szövegdoboz segítségével a felhasználó a telefon virtuális vagy fizikai billentyűzete segítségével adatokat vihet be az alkalmazásba. Programozottan ennél többet is meg lehet adni. 3-31 ábra A TextBox tulajdonságainak beállítása a Properties panelen 59 . A TextBoxot.Alapvető WP7 vezérlők Szövegbevitel a TextBoxszal A TextBox. a Toolboxon Nem meglepő módon a TextBox vezérlő Text tulajdonságán keresztül érhetjük el. A MaxLength tulajdonsággal megszabhatjuk. hogy legfeljebb hány karaktert írhasson be a felhasználó a szövegdobozba. ahogy a két előző vezérlőnket is a szövegvezérlők csoportjában találjuk a Toolboxon (3-30 ábra). a MaxLength csak a felhasználói adatbevitelt szabályozza.

Ahogy gépel. Ha például tudjuk. Alkalmazásfejlesztés Windows Phone-on Amikor a TextBox szövege megváltozik.Text. hogy esetleg megakadályozzuk a felhasználót érvénytelen adatok bevitelében. Az alábbi kódrészlet segítségével a felhasználó írhatja be az oldal címét – a korábban meghatározott MaxLength miatt legfeljebb 10 karakterben. Ezt az InputScope tulajdonsággal tehetjük meg (3-33 ábra). 60 . hogy a felhasználó egy szövegdobozba csak számokat fog gépelni. miért nehezítsük meg a dolgát egy teljes billentyűzettel? Elég lenne a számbillentyűket megjeleníteni! Éppen ezért. private void tbTitle_TextChanged(object sender. } 3-32 ábra: Adatbevitel a TextBoxon keresztül A virtuális billentyűzet beállítása Egy néhány colos billentyűzeten gépelni sosem lesz annyira kényelmes és gyors. az oldal címe automatikusan frissül. TextChangedEventArgs e) { PageTitle.3. elkaphatjuk a TextChanged eseményt. illetve.Text = tbTitle. hogy néhány kattintással pontosan beállíthassuk a TextBox vezérlők virtuális billentyűzetét. mint egy teljes értékű és méretű fizikai billentyűzeten tenni ugyanezt. a Silverlight for Windows Phone 7 lehetővé teszi.

Add(insName). a felhasználó csak számokat tud majd beírni ebbe a szövegdobozba (3-34 ábra). ins.Number.Alapvető WP7 vezérlők 3-33 ábra: Az InputScope kiválasztása egy TextBoxnál Ha például a Number beállítást választjuk.NameValue= InputScopeNameValue. insName. így akár futás közben is változtatható egy TextBoxhoz rendelt billentyűzet: InputScope ins = new InputScope().InputScope = ins. 3-34 ábra: Number InputScope-úra beállított TextBox Ugyanezt természetesen kódból is beállíthatjuk. tbTitle. InputScopeName insName = new InputScopeName().Names. 61 .

95). A megjelenítés testreszabható. Listavezérlők A vezérlők. a Toolboxon az általános vezérlők között találjuk (3-36 ábra). Mi a helyzet. saját objektumot. hogy bárki. aztán egy pöttyre cseréli le a PasswordBox. A PasswordBox is a szövegvezérlők csoportban található (3-35 ábra). A ListBox használata A ListBox talán a legalapvetőbb elemvezérlő. az még egy másodpercig látszik. egyetlen tartalmat tudtak megjeleníteni. azonban ennek az a hátránya. (Azt most ne firtassuk. mely objektumok listája. ha nem egy elemet (szöveget. erre a későbbiekben még kitérünk. Miután a felhasználó beírt egy karaktert. lelesheti a jelszót a kijelzőről. ezzel megakadályozva. mely egy speciális TextBox. hogy ehhez olyan közel kell állnia. Ezekben közös. hogy elkerülhetetlenül a felhasználó fülébe szuszog!) Ilyen esetekre a megfelelő megoldás a PasswordBox használata.com/enus/library/system. 3-35 ábra: A PasswordBox kiválasztása a Toolboxról A Password tulajdonságon keresztül érhető el a beírt jelszó. Alkalmazásfejlesztés Windows Phone-on Az InputScope rengeteg lehetséges értéket felvehet. Ezen keresztül adhatunk hozzá elemeket a listavezérlőhöz. mely megpróbálja azokat legjobb tudása szerint megjeleníteni. hogy a jelszó utólag visszaolvasható legyen. hogy rendelkeznek egy Items nevű tulajdonsággal. aki éppen a felhasználó mögött áll. más vezérlőknél pedig a Text vagy Password tulajdonságban megadott egyszerű szöveg. a PasswordChar tulajdonsággal pedig az alapértelmezett pöttyöt cserélhetjük le egy nekünk tetsző helyettesítő karakterre. 62 . legalább egyszer a jelszót is be kell kérni a felhasználótól.microsoft.input. bármit) szeretnénk megjeleníteni.inputscopenamevalue(v=vs.windows. Az alábbi linken mindegyikről találhatunk egy rövid leírást: http://msdn. Ez történhet egy normál TextBoxon keresztül is. hanem több azonos típusú elemet? Erre a problémára szolgáltatnak megoldást a listavezérlők.aspx Jelszavak bevitele a PasswordBoxon keresztül Ha alkalmazásunk vagy egy hozzá kapcsolódó webes szolgáltatás jelszavas azonosítást igényel. amelyekkel eddig foglalkoztunk.3. Bizonyos vezérlőknél ez a Content tulajdonságon keresztül megadott objektum.

a -1 azt jelenti. hogy több elem is kijelölhető legyen-e. nincs kijelölt elem. a SelectionMode-dal pedig megadhatjuk.) 3-37 ábra: A Todo-lista program kinézete A ListBox kijelölése után a Properties panelen szétnézve ismét a Common Properties csoport rejti a leggyakrabban használt tulajdonságokat. végletekig egyszerűsített tennivaló-listát valósítjuk meg. Az Items listán keresztül adhatunk elemeket a ListBoxhoz.Alapvető WP7 vezérlők 3-36 ábra: A ListBox kiválasztása a Toolboxról A működés megértéséhez a 3-37 ábrán látható. (3-38 ábra) 63 . Mindössze annyit tud. (Az elemek törlése már feláras funkció. hogy a TextBoxba írt szövegeket a gomb megnyomásával a ListBoxhoz rendeli. A SelectedIndex segítségével állíthatjuk be. hogy hányadik elem legyen alapértelmezetten kijelölve. A számozás 0-tól indul.

3-39 ábra: Stringek hozzáadása a ListBox tartalmához A gomb Click eseményére felírt eseménykezelővel hozzáadhatjuk a felhasználó által megadott új elemet: 64 . illetve az „X” gombbal törölhetünk egy elemet (3-39 ábra). Alkalmazásfejlesztés Windows Phone-on 3-38 ábra: A ListBox tulajdonságainak beállítása a Properties panelen Ha az Items melletti „…” gombra kattintunk. Az „Add another item” gombra kattintva kiválaszthatjuk a ListBoxhoz hozzáadni kívánt elem típusát. Az egyes elemek sorrendjét az ablak alján lévő nyilakkal változtathatjuk meg. melyben szerkeszthetjük a ListBox tartalmát. amit átírhatunk. az Object Collection Editor ablak jelenik meg. Egy stringet hozzáadva (az mscorlib|Systemben találjuk) a szerkesztőablak jobb oldalán megjelenik a karakterlánc.3.

Show(lbxTodo.Text = string. A TextBoxba írt szöveg megváltozásakor lefutó TextChanged esemény minden karakter leütése után frissítette az oldal címét. hogy frissítsék a felületet. hogy ehhez bármilyen kódot kellene írnunk. amikor megváltozik a kijelölt elem. Erőforrások Vannak olyan értékek (számok. anélkül. } A ListBox SelectionChanged eseménye akkor következik be. a változás azonnal megjelenik a másik helyen is. RoutedEventArgs e) { if (!string. Adatkötés Az előző példákban szerepeltek olyan kódrészletek.Adatkötés private void btnAddItem_Click(object sender. holott. objektumok. ha később szerettük volna feldolgozni azokat. Az alábbi kód egy MessageBoxban jeleníti meg a felhasználó által kiválasztott elemet: private void lbxTodo_SelectionChanged(object sender. amelybe közvetlenül helyeztük bele az elemeket. Az adatkötés segítségével különböző objektumokat.Empty. a kijelölt elem a telefonon beállított „accent” színnel jelenik meg.Items. hanem utána explicit módon ki is írta a számot a gombra. típusos listába rakni őket. megjelenítsék rajta az új.ToString()). tbNewItem. SelectionChangedEventArgs e) { MessageBox. Ha valami megváltozik az egyik helyen.Add(tbNewItem. amelyek pusztán arra szolgáltak. Ezen kívül pedig ott volt még a ListBox. másrészt pedig szinkronban tartja az összes olyan objektumot. Érdemes lenne tehát egyszer létrehozni őket.IsNullOrWhiteSpace(tbNewItem. A gomb megnyomásának hatására lefutó eseménykezelő nemcsak megnövelt egy értéket. amelyeket nem csak egy helyen szeretnénk felhasználni egy programban.SelectedItem. vezérlőket tarthatunk automatikusan szinkronban. Könnyebb lesz 65 .Text). a SelectedItemsen keresztül kapjuk meg mindet).Text)) lbxTodo. és aztán az adott oldalon vagy az egész programban újra és újra felhasználni. mely felhasználja az erőforrást. Ez egyrészről a memóriafoglalást is csökkenti. szövegek). és ennek a listának a tartalmát megjeleníteni. A XAML-ben mélyen be van ágyazva az adatkötés technológiája. A SelectedItem tulajdonságon keresztül érjük el a kiválasztott elemet (ha több is van. megváltozott adatokat. } 3-40 ábra: Az alkalmazás működés közben Ahogy a 3-40 ábrán is látható. érdemesebb lett volna egy háttérben lévő.

hogy hol kerüljön definiálásra az erőforrás: az oldalon vagy az alkalmazás szintjén. illetve meghatározhatjuk. ha a változtatás igénye esetén csak egy helyen kell frissíteni egy adott objektumot.3. hogy egy erőforráskönyvtárban (resource dictionary) hozzuk létre. melynek egyik eleme a „Convert to New Resource…” névre hallgat (3-41 ábra). melyeket csak erőforrások tárolására szokás létrehozni. valószínűleg mindegyik ablakban szeretnénk majd felhasználni azt. Az erőforráskönyvtárak különálló XAML-fájlok. Így még jobban elválasztható a felület leírása a kódban megírt logikától. Alkalmazásfejlesztés Windows Phone-on megtartani a program konzisztenciáját. Ezeket a közös használatú objektumokat definiálhatjuk kódban. és ha több ablakból áll egy alkalmazás. hogy gyakran magához a felülethez köthetők (például egy-egy vezérlő háttérszínét meghatározó Brush). utóbbinál viszont ha vannak más oldalaink. Az ApplicationTitle TextBlockot a Properties panelen kiválasztva a Text tulajdonság mellett található Advanced options gombra kattintva megjelenik a menü. de tekintve. A megjelenő párbeszédablakban beállíthatjuk az erőforrás nevét (Name). Ez meghatározza azt is. XAML-ben is megadhatjuk őket. hogy hol lesz látható: előbbi esetben csak az aktuális oldalon belül. 3-42 ábra: Az erőforrás nevének és tárolási helyének beállítása 66 . 3-41 ábra: Erőforrás létrehozása egy meglévő értékből Erre kattintva alakíthatjuk egy újrafelhasználható erőforrássá azt a stringet. A harmadik lehetőség. azokban is elérhető lesz. Alkalmazásaink címe például nem változik. amit éppen a Text tulajdonság tartalmaz.

hogy a Blend nagyon szépen jelzi. 3-45 ábra: Már létező erőforrás kiválasztása egy tulajdonsághoz Ez egy nagyon hasznos lehetőség a XAML-ben. létrehozva ezzel az erőforráshoz kötést (3-44 ábra). ha átváltunk a Resources panelra. Mi a helyzet akkor. ha nem egy előre elkészíthető erőforráshoz akarunk kötni. hogy egy tulajdonság nem lokálisan kap értéket. drag-and-drop módszerrel áthúzható egy felületi elemre. hanem valami máshoz. vagy kötést szeretnénk létrehozni a UI különböző elemei között? Erre szolgál megoldással az adatkötési rendszer. hogy a tulajdonság egy erőforrásból kap értéket Továbbá. ha a kiválasztott tulajdonság melletti Advanced optionsre kattintva a Local Resource menüpont alatt kiválasztjuk a megfelelő erőforrást (3-45 ábra). 3-43 ábra: A zöld keret és pötty jelzi. ott is megtalálható az erőforrások között az újonnan létrehozott string. illetve a Silverlightban. hanem egy erőforráshoz kötöttük hozzá (3-43 ábra). A kész erőforrás innen azonnal.Adatkötés Az is észrevehető. 3-44 ábra: Az adatforrások a Resources panelon Ugyanezt elérhetjük. 67 . például egy CLR-objektumhoz.

) 68 . Hasznos a fejlesztésnek abban a fázisában. majd annak jobb felső sarkában a „Create data source” gomb alatt válasszuk a „Create Object Data Source…” pontot (3-47 ábra)! 3-47 ábra: Adatforrás létrehozása a Data panelen A Data panel tetején találunk egy másik gombot is.3. Ezzel véletlenszerű mintaadatokkal feltöltött adatforrásokat hozhatunk létre. ahol a tényleges adatok még nem állnak rendelkezésre. Alkalmazásfejlesztés Windows Phone-on Több vezérlő kötése egyazon forráshoz Tekintsük az alábbi osztályt: public class Character { public string Name {get. és megjelenik. vagy hiányzik a program szerelvénye a listából. a „Create sample data” nevűt.} public Character() { Name = "Hubert Farnsworth". set. } } Hozzunk létre egy példányt ebből az oldalon. set. fordítani vagy futtatni kell.} public string City {get. A megjelenő ablakban válasszuk ki a Character osztályt. illetve adjuk meg az adatforrás nevét! (Ha még nem jelenne meg az osztály. és jelenítsük meg mindkét tulajdonságát egy-egy TextBlockban (3-46 ábra)! 3-46 ábra: A program felülete Ehhez kattintsunk a Data panelre. City = "New New York".

Vezérlőink DataContext tulajdonsága szolgál 69 . szép. de ha sok tulajdonságot szeretnénk egyazon objektumról megjeleníteni. és létrejön az adatkötés (3-50 ábra).Adatkötés 3-48 ábra: Az adatforrás típusának kiválasztása A Data panelen megjelenik az új adatforrás (3-49 ábra). Drag-and-drop módszerrel az egész adatforrást vagy egyes részeit ráhúzhatjuk egy felületi elemre. 3-49 ábra: Az új adatforrás tulajdonságai a Data panelen 3-50 ábra: Az adatforrás részeinek adatkötése drag-and-drop módszerrel Szép. nem lehetne egy kicsit központosítani az adatkötést? Természetesen lehet.

melyben Character típusú elemeket helyezünk el. és drag-and-drop módszerrel a StackPanelre húzni. felbecsülhetetlen lehet. azaz az előbb létrehozott Character objektumra. az oldalon lévő vezérlő képes lesz adatot kötni hozzá. 3-51 ábra: Adatkötés létrehozása egy szülő DataContextjén keresztül Tekintve. Alkalmazásfejlesztés Windows Phone-on arra. és a ListBoxra kattintani (3-52 ábra). de ha kézzel szerkesztjük a XAML-t. Elég a StackPanel DataContextjénél az Advanced options alatti „Element Property Binding…” pontot választani. hanem az Objects and Timeline ablakon elengedni a vonszolt objektumot. Logikus tehát.3. (Érdemes nem a felületen. automatikusan mindegyik. egyenként létrehozott Bindinggal szemben. hogy egy objektumot megadva neki beállítsuk. A DataContext öröklődik lefelé a vizuális fán. majd jóval egyszerűbb szintaxissal a felület egyes részeihez kötni. a két TextBlock objektumot pedig ennek egyes tulajdonságaihoz kössük hozzá. hogy a StackPanel DataContextjét most ne egy háttérben lévő objektumhoz kössük. A megjelenő ablak automatikusan a DataContext fület nyitja meg. hanem a ListBox kiválasztott eleméhez. Szeretnénk. vagyis az adatkötést két UI-elem között hozzuk létre. ha a TextBlockokban a ListBox kiválasztott eleme jelenne meg. 70 . hanem elég egyszer létrehozni. Ehhez első lépésként magát az adatforrást kell megfogni.) Ezek után az egyik TextBlock Text tulajdonsága melletti Advanced optionsre kattintva a DataBinding menüpontot kell választani. Adatkötés UI-elemek között Az előző példát egészítjük ki! A TextBlockok alatt egy ListBox foglal helyet. hogy a vezérlő vagy a benne lévő vezérlők tulajdonságai alapértelmezetten milyen objektumra legyenek rákötve. Tehát arra van szükség. tehát ha például a PhoneApplicationPage-en állítjuk be. A fenti két TextBlock egy StackPanel gyermeke. hogy nem kell egy-egy bonyolultabb adatkötést újra és újra megírni. ahol kiválaszthatjuk. hogy a StackPanel DataContextjét állítsuk be a CharacterDataSource-ra. hogy Blendben az ember hajlamos mindent „csak összekattintgatni”. itt még nem olyan nagy a DataContext előnye a sok. A Blend ehhez is hathatós támogatást nyújt. hogy a StackPaneltől örökölt kontextus melyik tulajdonságára szeretnénk a Textet kötni (3-51 ábra).

vagyis az adatok első. a Create Data Binding ablakban nem kapunk segítséget. 3-53 ábra: Tulajdonság és irány kiválasztása adatkötésnél Ezután már csak a TextBlockok Text tulajdonságát kell a korábbiakban megismert módon kötni. ahol a változáskövetés kétirányú. Az ablak alsó részén található szövegdobozban adhatjuk meg manuálisan a tulajdonság nevét (3-54 ábra). 3-54 ábra: Saját elérési út megadása a forrástulajdonságra 71 . ami egyirányú kötés. tehát a cél változása is visszahat a forrásra. amelyre kötni szeretnénk (SelectedItem). Silverlightban három kötési mód van: a OneTime egy egyszeri kötés. és a TwoWay. a OneWay. tökéletesen elég az alapértelmezett OneWay kötés (3-53 ábra). Mivel azonban a ListBoxban lévő elemekről statikusan semmit nem tudunk. a forrásból történő kiolvasása után nem lesz szinkronizálás. Mivel csak megjeleníteni szeretnénk a szöveget. hogy kiválasszuk a Name vagy a City tulajdonságokat. például a kötés irányát.Adatkötés 3-52 ábra: Adatkötés egy vezérlőre A megjelenő ablakban kiválaszthatjuk a tulajdonságot. valamint megadhatunk különböző beállításokat. vagyis a forrás változása kihat a célra.

microsoft. hogy hogyan kell megjeleníteni egy Character típus példányát? Jobb híján csak annyit tehet. DependencyProperty-kkel szokás megoldani. az egyéb típusoknál pedig az INotifyPropertyChanged interfész implementálásával. mellyel megadhatjuk. hogy a szövegnél bonyolultabb objektumokat (a Character osztály már két stringet is tartalmaz). Utóbbiról egy leírás és példa: http://msdn. 3-55 ábra: A ListBox egy elemének kiválasztásával a két TextBlock tartalma frissül Ha teszteljük az alkalmazást. Az adatkötési keretrendszernek alapvető része a változásokról való értesítés. Ennek eredményét láttuk a képernyőn. Most. már nem működik annyira szépen a megjelenítés.3. nem enged szünet karaktert belerakni.com/enus/library/ms229614. Alkalmazásfejlesztés Windows Phone-on A Blend és a Visual Studio XAML értelmezője olyannyira kifinomult. Ezt a vezérlők esetében ún. hogy ha Name tulajdonságot lát. Ez nem meglepő: honnan tudná a Silverlight. a két TextBlock felirata automatikusan frissül. ahogy más elemre állunk a ListBoxban (3-55 ábra).aspx Az adatok megjelenésének testreszabása adatsablonokkal Amikor szövegeket helyeztünk el a ListBoxban. 3-56 ábra: A DisplayMemberPath tulajdonság beállítása 72 . vagy változtassuk meg a Name-et másra! Emellett írhatunk morcos leveleket a Microsoftnak. vagy ne rakjunk bele szünetet. hogy egy XAML-ben megadott string nem megfelelő a Name tulajdonságnak. azok gyönyörűen megjelentek. Hogyan tehetjük ezt szebbé? Listavezérlőink rendelkeznek egy DisplayMemberPath nevű tulajdonsággal. hogy az objektum melyik tulajdonsága jelenjen meg a ToString hívása helyett (3-56 ábra). hogy visszatér a kályhához: meghívja a számára ismeretlen típusú objektum ToString metódusát. Ha azt jelzi az IDE.

ha egyetlen tulajdonságot jelenítünk meg. 73 . 3-58 ábra – Az új adatsablon nevének és helyének megadása 3-59 ábra – A tervezőfelület tetején látható „breadcrumb” jelzi. Ezen belül elsőre csak a „Create Empty…” választható. hogy jobb gombbal a ListBoxra kattintunk. Ilyenkor használhatunk adatsablonokat (data template). hogy sablont szerkesztünk Itt ugyanúgy rakhatjuk össze a felületet. hol jöjjön az létre (az erőforrások létrehozásából már ismerős lehet). Sokszor viszont több adatot is szeretnénk megjeleníteni egy elemről. gyakran elég lehet. és azt. majd az „Edit Additional Templates” menüpont alatt az „Edit Generated Items (ItemTemplate)” parancsot választjuk. A ListBoxban lévő elemek sablonját úgy változtathatjuk meg. ezzel hozhatunk létre új adatsablont (3-57 ábra). mint ahogy az oldalakét is tettük. a tervezőfelület sablonszerkesztési módba vált (3-59 ábra). 3-57 ábra: Adatsablon létrehozása a ListBox elemeihez Ha a következő ablakban (3-58 ábra) megadjuk a sablon nevét.Az adatok megjelenésének testreszabása adatsablonokkal Mivel a mobilképernyő alapvetően kicsi.

Egy gomb mindössze.3. akár teljesen ki is cserélhetjük megjelenésüket. amire rá lehet kattintani” — esetünkben tapintani. Azonban ha ez nem elég. (Advanced options. A vezérlők kinézetének testreszabása vezérlősablonokkal Adatok megjelenését már testre tudjuk szabni. Tartozik hozzá egy alapértelmezett kinézet – 74 . „valami. Appearance és Layout csoportokba a Properties panelen. A korábban megismert adatkötési eljárással ez is könnyedén megoldható. a kinézetet nem. A Silverlight (illetve eredetileg a WPF) vezérlői „kinézetmentes” (lookless) vezérlők. custom expression. Data Context. De mi a helyzet magukkal a vezérlőkkel? A Silverlight vezérlői jól testreszabhatóak pusztán tulajdonságaikon keresztül: elég belenézni a Brushes.) 3-63 ábra: Az adatsablonnal megerősített program működés közben Az adatsablonok — ha erőforrásként hoztuk létre őket — újra felhasználhatóak. Alkalmazásfejlesztés Windows Phone-on 3-60 ábra: A Gridből és az abban lévő két TextBlockból álló adatsablon A 3-60 ábrán látható. tehát a fent elkészítettet átadhatjuk egy másik oldal másik ListBox objektumának is. a vezérlőt leíró osztály csupán a működést definiálja. Data Binding…. hogy két TextBlock van a sablonban.

Ehhez testre kell szabnunk a vezérlőt. Jobb egérgombbal kattintva az egyik gombra. amivel új Charactereket lehet hozzáadni a listához. illetve a lista kijelölt elemét törölni (3-62 ábra). Hogyan cserélhetjük le ezt az alapértelmezett megjelenést? Az előző. 3-63 ábra – Egy vezérlő sablonjának lecserélése üresre A megjelenő ablakban szokás szerint nevet adhatunk a sablonnak (erőforrásnak). ha a gombok kisebb feliratokkal jelennének meg. mert jelen pillanatban nem tud képet megjeleníteni. és kiválaszthatjuk a helyét (3-64 ábra). akkor elérhetővé válnak az „Edit Current” (jelenlegi szerkesztése) és az „Apply Resource” (használat erőforrásként) parancsok is. így. vagy a jelenlegit másolhatjuk le..” – a példában ezt teszem). hogy hogyan nézzen ki egy gomb. adatkötéses alkalmazást kiegészítettük még egy sorral. ha mi nem szabjuk meg.A vezérlők kinézetének testreszabása vezérlősablonokkal legtöbbször chrome-ként hivatkoznak erre –.. ezt az alapértelmezett kinézetet kapja. és szerkeszthetjük. és egy-egy kép is kapcsolódna hozzájuk. Itt vagy egy üres sablont hozhatunk létre („Create Empty. 75 . 3-62 ábra: Új vezérlők az előző példaalkalmazáshoz Szeretnénk. az „Edit Template” menüpontot kell választanunk. Ha már van egy saját sablon.

melyre adatkötést lehet létrehozni (3-66 ábra). Mi a helyzet a felirattal? Azt esetleg változtatni szeretnénk. mint a korábbi adatsablon létrehozása. amelyre éppen alkalmazzák – elvégre egy sablont több gombra is rá lehet majd húzni.szeretnénk. Két dolog maradt már csak hátra:   . A projektbe fel kell vennünk a megjelenítendő képet. a Text tulajdonság melletti Advanced optionsre kattintva a Template Bindingot kell választani.kell egy kép az Image-nek. esetleg egyszerűen csak nem akarjuk a vezérlősablonban rögzíteni. Ehhez a TemplateBindingot használjuk fel. Az első probléma egyszerűen megoldható. A TextBlock kijelölése után. vagy többnyelvűvé tenni. A TextBlocknak meg kell mondani.3. ugyanúgy működik. ha a gomb szövege meg is jelenne. mert előre rendelkezésre állt a kép. 76 . hogy Text tulajdonságában annak a Button vezérlőnek a Content tulajdonságát jelenítse meg. A megjelenő listában a sablon célvezérlőjének (esetünkben a Button) összes olyan tulajdonságát láthatjuk. illetve . 3-65 ábra: Kép kiválasztása egy Image elem forrásául Ez egyszerű volt. majd az Image vezérlő Source tulajdonságánál kiválasztani azt a lenyíló listából (3-65 ábra). Alkalmazásfejlesztés Windows Phone-on 3-64 ábra – Az új vezérlősablon nevének és helyének megadása Az üres Gridben egy Image és egy TextBlock vezérlőt elhelyezve (és tulajdonságaikat megfelelően beállítva) az alapvető elrendezés néhány másodperc alatt összeállítható.

77 . mert a Blendben sajnos nem tudjuk Build Action tulajdonságukat átállítani. a képet természetesen egy másikra állítva a Hozzáadás gomb is megszépíthető (3-68 ábra). 3-67 ábra: A vezérlősablon átveszi a vezérlőtől az értéket Ugyanezeket a lépéseket eljátszva. csupán a képeik térnek el. ez pedig elengedhetetlen. és az Image vezérlő forrását erre kötjük rá a TemplateBindinggal. érdemes saját vezérlőt készíteni. Érdemes a képeket Visual Studióban hozzáadni a projekthez. illetve a tervezőfelületen látszik. hogy a sablon már a gombtól veszi a feliratát (3-67). 3-68 ábra: Mindkét gomb külön sablonnal ellátva Mivel most a két gomb felépítése tulajdonképpen ugyanaz.A vezérlők kinézetének testreszabása vezérlősablonokkal 3-66 ábra: Vezérlősablon tulajdonságának a vezérlőhöz kötése a TemplateBinding segítségével A Content tulajdonság kiválasztása után meg is jelenik az adatkötést jelző sárga keret. amelynek egy plusz ImageSource tulajdonságot adunk.

3-70 ábra: Új állapotcsoport hozzáadása a States panelen A csoport létrehozása és elnevezése után létrehozhatjuk állapotainkat (3-71 ábra). ezért először egy csoportot kell létrehozni (3-70 ábra). ha a másikat. Az egy csoportban lévő állapotok kölcsönösen kizárják egymást. Alkalmazásfejlesztés Windows Phone-on Az alkalmazás állapotainak létrehozása VisualState-ek segítségével A Silverlight 3 óta alkalmazásainkban különböző vizuális állapotokat adhatunk meg. az egyik kép tűnik elő. amelyek két képhez kapcsolódnak olyan módon. ami a felület megjelenését közvetlenül befolyásolja. hogy ha a felhasználó megnyomja az egyik gombot. Ehelyett a States panelen hozzunk létre két állapotot! VisualState-jeink csoportokba rendezhetők. próbáljuk meg elkerülni. Vegyük példának az alábbi egyszerű alkalmazást! Két gombból áll.3. hogy olyan kódot írjunk. 78 . a másik pedig engedélyezetté (3-69 ábra). és az egyes állapotok közötti váltás is jelentősen leegyszerűsödik a korábbi módszerekhez képest. 3-69 ábra: A VisualState-eket bemutató program kinézete és szerkezete Ezt az egyszerű logikát leírhatjuk kódban is. Emellett pedig a megnyomott gomb letiltottá válik. a másik kép. Ezzel központosíthatjuk a felületleírást. melyekben leírhatjuk a felület elvárt állapotát bizonyos helyzetekben. tehát az alkalmazás egy VisualStateGroupnak egyszerre csak egy VisualState-jében lehet. de ha egy mód van rá.

3-72 ábra: Egy állapot szerkesztése közben a tervezőfelület piros keretet kap A vezérlők átlátszóságát az Opacity tulajdonsággal tudjuk állítani. Ezt megtehetjük kódban (a Click eseménykezelőkben meghívjuk a VisualStateManager GoToState metódusát. az nem az alkalmazás normál állapotában fog megjelenni. a vezérlő eltűnik (3-73 ábra). A Behavioröket az Assets panel Behaviors listájában találjuk (3-74 ábra). hogy amikor kijelölünk egy VisualState-et.Az alkalmazás állapotainak létrehozása VisualState-ek segítségével 3-71 ábra: Új állapot hozzáadása egy állapotcsoporthoz Vegyük észre. a GoToStateActiont aggathatjuk rá a gombra. A States panel tetején lévő Base gombra kattintva térhetünk vissza bármikor az állapotokon kívüli szerkesztéshez (3-72 ábra). átadva neki a célállapot nevét). hogy a gombnyomás hatására lefusson az állapotváltás. A Behaviorök segítségével meglévő vezérlőkhöz rendelhetünk hozzá extra viselkedéseket. akkor más módszerre lesz szükség. 79 . illetve tilthatjuk. hogy deklaratív módon szeretnénk a felületet leírni. de ha tartjuk magunkat ahhoz. Ha például arra van szükségünk. Ha egy állapot szerkesztése közben 0%ra állítjuk az Opacity értékét. vagyis bármit változtatunk a felületen. 3-73 ábra: Az Opacity beállítása A gombokat az IsEnabled tulajdonság állításával engedélyezhetjük. hanem csak akkor. amikor ebbe az állapotba lép az alkalmazás. a tervezőfelület állapotszerkesztési módba vált. hogy egy gomb valamilyen eseménye hatására (nem kell feltétlenül a Clicknek lennie) egy állapotváltást végezzen. Meg kell oldani.

3-76 ábra: A Behavior beállítása Ha futtatjuk az alkalmazást. és rákattintunk valamelyik gombra. miután rádobtuk egy gombra A GoToStateActiont kiválasztva a Properties panelen beállíthatjuk. amelyet meghatározunk a gomb számára (3-77 ábra). 80 . az alkalmazás felülete rögtön abba a vizuális állapotba vált. hogy mely esemény hatására (EventName) mely állapotba szeretnénk átváltani (StateName). Ennek eredményét az Objects and Timeline ablakban is láthatjuk (3-75 ábra). 3-75 ábra: A GoToStateAction Behavior. Alkalmazásfejlesztés Windows Phone-on 3-74 ábra: A GoToStateAction Behavior az Assets panelen Innen egyszerűen ráhúzhatjuk őket a gombokra.3.

Vagy például szeretnénk azt elérni. ha például a kép nem egy pillanat alatt váltana át. Vagyis az animációkat elég XAML-ben megfogalmazni: „milyen tulajdonságot. és a háttérben az erre optimalizált keretrendszer elvégzi helyettünk a bonyolult kód megírását. dragand-drop módszerrel érhető el.Az alkalmazás állapotainak létrehozása VisualState-ek segítségével 3-77 ábra: A program felülete „rage” állapotban Animációk hozzáadása Vannak esetek.és a végállapot között. hogy a megfelelő állapot legyen kijelölve. (A *  Célállapot nevű átmenet a bármely más állapotból az adott célállapotba történő animálást jelenti. „átúszna” a másik képbe. amikor a változtatásokat végzi az ember. Maga az animáció egy tulajdonság értékének adott idő alatti megváltoztatását jelenti. animált. hanem csak írja le (deklarálja). kinézetét a kiinduló. hogy az egyes állapotokat kiválasztva (States panel) az állapoton lévő „Add transition” gombbal hozzárendelünk egy állapotátmenet-animációt egy adott átmenethez. engedélyezett gomb legyen felül! Ez a tervezőfelületen.) 81 . de érezhetően kicsit fapados a kinézet működése. Mivel ennek az implementálása értékes időt vett el a fejlesztőtől. hogy mit is szeretne elérni. Szebb lenne. mindenféle kód nélkül össze tudjuk állítani a felületet a különböző állapotokban. hogy az ehhez hasonló látványelemeket ne imperatív kóddal valósítsa meg a fejlesztő. Szépen. de nem árt arra ügyelni. a Microsoft a WPF-fel előtérbe helyezte azt a megoldást. gyorsan. Korábban a legtöbb fejlesztőeszköznél ennek a leprogramozása teljes egészében a fejlesztő feladata volt: másodpercenként harmincszor feldobni egy eseményt. Ennek előnye. menyi idő alatt. milyen végértékre szeretnék hozni”. abban pedig kiszámolni a vezérlő aktuális elhelyezkedését. hogy könnyen generálható… A két korábban létrehozott VisualState egyikében cseréljük fel a gombok helyzetét! A lényeg. hogy mindig az a gomb legyen felül. hanem látványos. amit a felhasználó megnyomhat – és a gombok helycseréje se pillanatszerű legyen. hanem egy másodperc alatt elhalványulna. Ezután csak annyit kell tenni. A XAML előnye pedig. amikor ennyi nem elég. hogy minden állapotban a másik állapotba váltó. és utána (gyakran pixelről pixelre) kirajzolni a vezérlőt. hogy gyorsan leírható.

Alkalmazásfejlesztés Windows Phone-on 3-78 ábra: Állapotátmenet hozzáadása egy állapothoz Ha létrejött az animáció. illetve hogy milyen görbe mentén történjen (EasingFunction). Amikor kijelölünk egy állapotátmenetet a States panelen. hanem egy másodperc alatt változik az Opacity értéke 1-ről 0-ra és vissza. egyszerűen törölhetjük innen az animációt (3-80 ábra). itt jelzi a Blend. hogy a felületen lévő vezérlők közül melyek animáltak. hogy mennyi ideig tartson (1s).tutsplus. és pontosan mely tulajdonságaik. és a gombok is egy másodperc alatt csúsznak egyik helyről a másikra. ahogyan azt a 3-79 ábra jelzi. Néhány link a továbblépéshez: Mike Taulty bevezető screencastja a VisualState-ekhez: http://active. megadhatjuk. 3-80 ábra: Az animáció megjelenítése az Objects and Timeline panelen Mindezeket beállítva a program tesztelhető: az állapotok közötti átmenet nem pillanatszerűen megy végbe. 3-79 ábra: Az idő és az EasingFunction beállítása Érdemes egy pillantást vetni az Objects and Timeline ablakra is. A VisualState-ek témaköre ennél természetesen jóval terebélyesebb.com/tutorials/silverlight/understanding-visual-states-in-silverlight/ 82 .3. Ha valamelyik tulajdonságot mégsem szeretnénk animálni.

amelyet az oldalak címénél használnak az alkalmazások? Nem kell pontosan tudnunk. ez is adatköthető. Ez a lista felsorol minden olyan rendszerszintű erőforrást. színek. amelyet a felhasználó beállított a rendszer alapszínének? Vagy szeretnénk egy szöveget pontosan azzal a betűtípussal és betűmérettel megjeleníteni.com/2010/11/using-visualstates-in-custom-controls-in-silverlight/ Témák használata Ha szeretnénk. hogy az egy ilyen erőforrást használjon.Témák használata VisualState-ek használata egyéni vezérlőkben: http://www. Az alábbi példában a legutóbbi program (troll és rage) oldalcímének színét állítjuk be a telefonon kiválasztott alapszínre. 3-82 ábra: A PhoneAccentBrush rendszerszintű erőforrás kiválasztása 83 . A Silverlight az összes rendszerszintű alapbeállítást erőforrásként elérhetővé teszi számunkra. A PhoneAccentBrush az a szín. hogy alkalmazásaink illeszkedjenek a Windows Phone 7 megjelenésébe.vagy vezérlősablonban szeretnénk felhasználni azt a színt. betűtípusok milyenek is. Mi a helyzet például. amelynek típusa megegyezik a beállítani kívánt tulajdonság típusával. amely az operációs rendszernek a felhasználó által bármikor átállítható alapszíne (3-82 ábra). 3-81 ábra: A színek beállítása a Properties panelen Ahogy szinte minden. hogy a kiválasztott tulajdonság kapcsán néhány kattintással beállítjuk. A mellette lévő „Advanced options” gombra kattintva ezúttal a System Resources listából kell választani. launcherek (választók és indítók) használata. illetve egyéb operációs rendszerszintű integrációk elvégzése előtti első lépés. ha egy adat. hogy a felületet konzisztenssé tesszük magával az operációs rendszerrel. Mindössze annyit kell tennünk.timmykokke. A PageTitle TextBlock kijelölése után a Brushes csoportban található Foreground tulajdonsággal állítható be egy szöveg betűszíne (3-81 ábra). a chooserek. hogy ezek a méretek.

szövegmegjelenítési és szövegbeviteli vezérlőket. hogyan lehet felhasználni az operációs rendszer vizuális erőforrásait saját alkalmazásainkban. az animációból.és vezérlősablonokkal testre szabni egy adattípus megjelenését. 84 . és megnéztük. Megismerkedtünk az adatkötés fogalmával és az adatkötési keretrendszer használatával. Ezután áttekintettük. Ezután ízelítőt kaptunk a vizuális állapotok használatából. valamint a több elem megjelenítésére képes listavezérlőket. szinte teljes egészében elhagyva a saját kód megírását a felhasználói felület elkészítésénél. Mindezt a Visual Studio nélkül. hogyan lehet adat. Megnéztük. hogy a PageTitle-ben megjelenő felirat mindig az operációs rendszer színsémáját követi (3-83 ábra). hogy gazdag tartalmú és tudású felületeket építhessünk. 3-83 ábra: A PageTitle a telefon aktuális „accent” színével jelenik meg Összefoglalás Ebben a fejezetben röviden megismerkedhettünk a Silverlight grafikus felhasználói felületének alapvető elemeivel. hogy a beépített vezérlőtípusokon milyen szolgáltatásokat tesz elérhetővé a Silverlight. Alkalmazásfejlesztés Windows Phone-on Ennek kiválasztása után − ha elindítjuk az alkalmazást − látható. Számba vettük a leggyakrabban használt parancsvezérlőket. illetve hogy hogyan cserélhetjük le egy vezérlő kinézetét a nekünk megfelelőre. kizárólag Expression Blend felhasználásával tettük meg.3.

a webes verzióban is fellelhető kétféle nézet között váltogatni. amely megadott pozíciókat „pushpin”-ekkel (gombostű. A fejezet első részében a térképek megjelenítését. Térképek kezelése A Microsoft az utóbbi években folyamatosan növekvő erőfeszítéseket fektet online szolgáltatásainak továbbfejlesztésébe. POI) megjeleníteni. ha akarunk. segítenek a platformhoz illő felhasználói felületek és interakciók megteremtésében is. mégpedig úgy. amelyek mindenképpen szükségesek egy Windows Phone 7 alkalmazás fejlesztéséhez. de valószínűleg nem baj. amikbe jobb nem egy – esetleg több hónapon át tartó – fejlesztés végén belefutni. hogy ez a jelölés távolról csupán egy szövegdobozból álljon. Erre két módszert alkalmazunk: a tartalomegységeket az egyik esetben külön oldalakon jelenítjük meg – az ezek közti információcsere biztosításával –. Egy Live Id-t felhasználva jelentkezzünk be és fogadjuk el a feltételeket! Itt kivételesen érdemes elolvasni a feltételeket tartalmazó dokumentumot. rajzszeg) emel ki. hogy ezeket a térképeket – és a kiegészítő szolgáltatásokat – saját alkalmazásainkban is elérhetővé tegyük. Végül megismerkedünk a Silverlight Toolkit Windows Phone 7-hez tartozó részeivel.bingmapsportal. újság. De természetesen itt a fejlesztő teljes szabadságot kap. míg a másik esetben egy oldalon. böngészőket vagy a Mango óta XNA játékokat is megjelenítünk a kiemelt helyeken. majd rátérünk a tartalmak rendszerezésére. Haladó alkalmazásfejlesztés Windows Phone-on Az előző fejezetekben megismerkedhettünk azokkal az elvekkel és vezérlőkkel. Nem használhatunk pornográf pushpineket. ez kiegészül egy képpel. Például. ezek között optimális útvonalat tervezni. 85 . A közlekedési adatok nem használhatók televízió. akár teljesen kicserélődik egy videolejátszóra. Ez a csomag azon túl. amit kedvenc keresőnket alkalmazva címkeresésre. Pár ezek közül:      Nem írhatunk valós idejű navigációt megvalósító alkalmazást. rádió. azaz média esetében. útvonaltervezésre. Egyszerű DataTemplate definiálásával létrehozhatunk akár egy olyan oldalt. de amint a felhasználó ráközelít a területre. Ebben a fejezetben olyan eszközöket fogunk áttekinteni.com/ weblapon. amelyek amellett. mivel igen szigorú szabályok vonatkoznak például a telefonos felhasználásra. A programunk nem működhet együtt más térképszolgáltatásokkal. Nem tárolhatunk közlekedési adatokat. amelyek egyik megtestesülése a Bing Maps szolgáltatáscsomag. forgalomadatok szerzésére használhatunk. és mindezt a Silverlightban megszokott teljes testreszabhatóság megtartásával tehetjük. Feliratkozás a szolgáltatásra A szolgáltatás igénybevételéhez először regisztrálnunk kell a https://www. testreszabhatóságát vesszük át. hogy teljes világtérképet tartalmaz. egyszerűen tudunk kiemelt helyeket (Point of Interest. a horizontális strukturálást lehetővé tevő Panorama és Pivot vezérlők segítségével. ha ezekkel a lehetőségekkel nem mindig élünk. lehetővé teszi.4. amelyek a platform lehetőségeit még jobban kihasználják – a Metro felhasználói felülettel konzisztens módon. hogy számos új elemmel egészítik ki eszköztárunkat.

ez meg fog hiúsulni.Phone.0"> <maps:Map /> </Grid> A kód futtatásakor már láthatjuk is. akkor a vezérlő elkezd kommunikálni a szolgáltatással. Ha nagyítunk. 4-1 ábra: Bing Maps kulcs létrehozása A kitöltést követően meg is kapjuk az alkalmazás kulcsát. tehát a referencia hozzáadásával sem kell majd bajlódnunk. Ehhez a fiókhoz alkalmazásokat regisztrálhatunk... amire majd szükségünk lesz a Bing Maps vezérlő létrehozásakor (lásd a 4-2 ábrán). akkor létrejön számunkra egy felhasználói fiók. amit a térkép közepén megjelenő hibaüzenet tudat velünk. Haladó alkalmazásfejlesztés Windows Phone-on Mindenesetre ha ezek után is akarunk térképeket használni.Phone.0. 4-2 ábra: A kapott kulcs. Mivel még nem adtuk meg a regisztrációkor kapott kódot. Ezt természetesen kézzel is megtehetjük az alábbi kód segítségével: xmlns:maps="clrnamespace:Microsoft.Row="1" Margin="12. amint az a 4-4 ábrán látható. hogy a Bing Maps vezérlő megjelenik.Controls. hogy már az alap SDK-ban is megtalálható a számunkra fontos Map vezérlő (4-3 ábra). és elfogadtuk a feltételeket. nevezzük el „Advanced Development”-nek! A Toolboxot kinyitva láthatjuk. megpróbáljuk mozgatni a térképet. 4-3 ábra: A Map vezérlő megtalálható a Toolboxban Ha drag-and-drop módszerrel hozzáadjuk ezt a vezérlőt a megnyitott oldalunkhoz.Controls.12. erre szükségünk lesz a kliens hitelesítéséhez A Bing Maps vezérlő használata Hozzunk létre egy új Windows Phone Application projektet Visual Studioban.assembly=Microsoft. akkor annak névtere automatikusan belekerül a XAML kódba. ahogyan azt a 4-1 ábra is mutatja. ez az.4. 86 .Maps"> . aminek első feladata a kliens hitelesítése lesz. <Grid x:Name="ContentPanel" Grid. ha a menü Create or view keys elemére klikkelünk.Maps.

hanem az ezek alapján készített.. ugyanis a térkép Mode tulajdonsága egy olyan objektumpéldányt vár. AerialMode: Teljes műholdképek. Ez az alapértelmezett mód.. és rendesen használhatjuk a vezérlőt. függetlenül a Center pozíciótól..-122. középen a hitelesítés hiányát jelölő hibaüzenettel Állítsuk be tehát a hitelesítéshez szükséges kulcsot a vezérlő tulajdonságai között. amelyeken az előző nézet útvonalai természetesen ugyanúgy ki vannak emelve.. A vezérlő viszont még ezt követően is a teljes világtérképet fogja megjeleníteni. Adjunk meg egy középpontot a térképen a Center tulajdonság segítségével! Ez a tulajdonság GeoCoordinate típusú."/> Ennek hatására a figyelmeztetés eltűnik.639655. és nevezzük is el a térképet! <maps:Map Name="myMap CredentialsProvider="Ajdyq5FaN2RZvzvogm_. ami a MapMode osztályból származik – ez a megjelenítéshez szükséges 87 .129404" ZoomLevel="17" /> Az egyszerűbb felhasználás kedvéért és a tesztelés miatt is érdemes megjeleníteni a ZoomBar gombjait.. " Center="47. A módok közötti váltáshoz egy kicsit többet kell dolgoznunk. Ezt a ZoomLevel megadásával változtathatjuk meg: <maps:Map Name="myMap" CredentialsProvider="Ajdyq5FaN2RZvzvogm_.. hiszen nem állítottuk még be a nagyítás fokát. Ezek az emulátoron különösen hasznosak tudnak lenni a kicsinyítés és nagyítás gombokkal való vezérelhetősége miatt: ZoomBarVisibility="Visible" A térkép két különböző módban jelenhet meg:   RoadMode: Ebben az esetben nem a műholdképekkel találkozhatunk. csak az utakra összpontosító nézetet kapunk. és XAML kódból a pozíciót leíró koordinátákat is felhasználhatunk az értékadás során.Térképek kezelése 4-4 ábra: A térkép.

" Center="47.639655.639655.Mode = new AerialMode().. } Természetesen erre ugyanúgy lehetőségünk van a XAML leírásból is: <maps:Map Name="myMap" CredentialsProvider="Ajdyq5FaN2RZvzvogm_.129404" ZoomLevel="17" ZoomBarVisibility="Visible" LogoVisibility="Collapsed" CopyrightVisibility="Collapsed"> <maps:Map.. beállításokat tartalmazza. //.Mode> <maps:AerialMode /> </maps:Map. akkor a teljes eddigi kódunk (a névtér definíciója mellett) csupán ennyi: <maps:Map Name="myMap" CredentialsProvider="Ajdyq5FaN2RZvzvogm_..Mode> </maps:Map> A kód hatására meg is jelenik egy teljes funkcionalitással bíró térkép.Maps. például az alábbi módszerrel: using Microsoft. Haladó alkalmazásfejlesztés Windows Phone-on értékeket.-122.Mode> </maps:Map> Tűntessük még el a Bing logoját és copyright feliratát a LogoVisibility és CopyrightVisibility Collapsed-re állításával! Ha mindennel végeztünk.129404" ZoomLevel="17" ZoomBarVisibility="Visible"> <maps:Map. 88 ..4. azokat csak példányosítani kell. public MainPage() { InitializeComponent().. középen a Microsoft főhadiszállásával. amint az a 4-5 ábrán látható.-122.Phone.Controls. Az előbb leírt módok használatához szerencsére léteznek előre definiált osztályok.. myMap." Center="47.Mode> <maps:AerialMode /> </maps:Map.

Device. Ennek eszköze a szintén a Maps vezérlő névtérhez tartozó Pushpin osztály.12862). 4-6 ábra: Egyszerű Pushpinek a térképen 89 .639655.Children.129404" Content="Microsoft" /> Ugyanez a feladat kódban az osztály példányosításával és a térkép Children kollekciójához való hozzáfűzéssel jár: myMap. amint azt a 4-6 ábra is mutatja. Ez egyszerűen. Content = "C#" }).Location.GeoCoordinate(47.63876. XAML vagy C# kódból hozzáadogathatjuk a térképhez. viszont szükség esetén a Silverlightban megszokott könnyedséggel testre is szabhatjuk azt. csupán a tartalomnak beállított szöveget mutatják az adott pozíción. megjelölt pozíciók nélkül. Ezeket a pushpineket akár egyesével. de akár dinamikus listákat is köthetünk a vezérlőhöz.Add(new Pushpin { Location = new System. címek.-122. -122. Egy Pushpin felvétele XAML-ben az alábbi módon történhet: <maps:Pushpin Location="47. csupán koordináták és kiírandó szöveg megadásával használható vezérlő. Az így kapott jelöléseink végtelenül egyszerűek.Térképek kezelése 4-5 ábra: A térkép pozicionálva és nagyítva Aerial módban Pushpinek Egy térkép mit sem érne kiemelt információk.

Ennek kipróbálására hozzunk létre egy POI osztályt.png" Width="50" /> </StackPanel> </maps:Pushpin> Ezzel a kis módosítással már teljesen kézben tarthatjuk a pushpin megjelenítését. } } A példányokat egy privát. Ez a POI-k egyszerű hozzáadásával körülményes lenne. } public string Name { get. Name = "Old Man's" }.4. „property element” szintakszissal való leírásra: <maps:Pushpin Location="47.129404" Background="Transparent"> <StackPanel> <TextBlock Text="MS" HorizontalAlignment="Center" /> <Image Source="http://www.deviantart. amit az oldal létrehozásakor töltünk fel pár elemmel. azonban rétegekbe rendezve a megjelenített tartalmat a feladat sokkal egyszerűbbé válik. az itt alkalmazott kód például a 4-7 ábrán látható kinézetet eredményezi.Location. bár itt ennek előnyeit nem fogjuk kihasználni: private readonly ObservableCollection<POI> _pubs = new ObservableCollection<POI> { new POI { Location= new System. valamint a hely megjelölését. new POI { Location = new System. ugyanis itt csupán a Content attribútumszerű értékadását kell kicserélni az ún. és egy publikus.12862). csak olvasható lista tartalmazza.Device.-122. Egy valós projektben a listákat természetesen bármilyen adatforrás vagy webszolgáltatás előállíthatja. set. Ennek példányait két listába.63876. ami tartalmaz egy pozíciót. a benzinkutak és a bárok listájába fogjuk sorolni: public class POI { public GeoCoordinate Location { get. csak get metódussal rendelkező tulajdonságon keresztül érünk el. -122.com/download/128133698/ Windows_Vista_Icon_HD_by_magbanuamicah.Location.GeoCoordinate(47.GeoCoordinate(47.640055. 90 . a benzinkutakat rejtsük el). Name = "Oportó" } }. Az adatkötés miatt használjunk ObservableCollection típust.120204). 4-7 ábra: Testreszabott Pushpin Rétegek alkalmazása Sokszor elvárt funkcionalitás a kiemelt helyek szűrése egy adott kategória alapján (például a környező kocsmákat jelenítsük meg. Haladó alkalmazásfejlesztés Windows Phone-on A megjelenítés felüldefiniálása a XAML leírásból egyszerűbb. vagy akár teljes kikapcsolása.-122. set.639655.Device.

DataContext = this.ItemTemplate> </maps:MapItemsControl> </maps:MapLayer> A réteget egy MapLayer példány reprezentálja.Térképek kezelése public ObservableCollection<POI> Pubs { get { return _pubs. de magát az adatkötést még nem végeztük el. ahogyan azt az ItemTemplate részben meghatározzuk. Ha kódunkat így próbáljuk futtatni. this. ha ezt most az oldal konstruktorában tesszük meg az alábbi kóddal: public MainPage() { InitializeComponent(). Legegyszerűbb. amit korábban az Images mappába mentettünk. hozzunk létre egy új réteget a térképen belül: <maps:MapLayer Name="lPubs"> <maps:MapItemsControl ItemsSource="{Binding Pubs}"> <maps:MapItemsControl. Az előző módszerhez hasonlóan hozzunk létre egy listát. méghozzá úgy. Ezen belül a MapItemsControl teszi lehetővé azt. valamint egy olyan képet.png" Width="50" /> </StackPanel> </maps:Pushpin> </DataTemplate> </maps:MapItemsControl.xap csomag egy mappájába kerül. hogy később tudjunk rá hivatkozni. Ez tartalmazza a hely nevét. Képeknél a Build Actiont érdemes Contentre állítani. akkor a POI-k még nem fognak megjelenni a térképen. ami például benzinkutakat tartalmaz: 91 . hanem az egész lista tartalmát. hogy előállítottuk a megjelenítendő listát.ItemTemplate> <DataTemplate> <maps:Pushpin Location="{Binding Location}"> <StackPanel> <TextBlock Text="{Binding Name}" HorizontalAlignment="Center"/> <Image Source="Images/Beer. ennek egy nevet is adtunk. } } Most. hogy ne csak egy-egy elemet jelenítsünk meg. } Most futtatva a programot a definiált POI-k már meg is jelennek (4-8 ábra). Így a relatív hivatkozások révén könnyebb azt felhasználni programunkban. mivel ekkor a médiaelem nem lesz a szerelvény része. hanem a . hiszen hivatkoztunk ugyan a bekötendő adatokra. A kódban egy PushPin-t tűzünk ki a Location által meghatározott pozícióra.

helyezzünk el két gombot az ApplicationBar-on. EventArgs e) { if (lPubs.4.ApplicationBar> A gombokhoz tartozó eseménykezelők elvégzik a réteg Visibility tulajdonságának átbillentését: private void Pubs_Click(object sender.Windows. hogy kihasználjuk a rétegek előnyeit.Visibility. valamint a lenti vezérlőgombokkal ezeknek a rétegeknek a megjelenítését váltogathatjuk. amely két külön rétegen jelenít meg testreszabott pushpineket.Visibility. Haladó alkalmazásfejlesztés Windows Phone-on 4-8 ábra: A pozíció-listák a térképen megjelenítve Ahhoz. } else { lPubs.png" Text="Benzin" Click="PetrolStations_Click"/> </shell:ApplicationBar> </phone:PhoneApplicationPage. melyekkel a megfelelő réteg megjelenítését tudjuk ki-be kapcsolni: <phone:PhoneApplicationPage.Visibility.Visible. 92 .png" Text="Bárok" Click="Pubs_Click"/> <shell:ApplicationBarIconButton IconUri="/Images/petrol. Eddigi munkánk végeredménye tehát egy olyan térkép.Visibility = System.Windows.Visible) { lPubs.Visibility == System.Windows. amint azt a 4-9 ábra mutatja. } } A benzinkutak rétegéhez kapcsolódó PetrolStations_Click kódja teljesen hasonló ehhez.Collapsed.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/beer.Visibility = System.

amit egy térképprogramtól elvárhatunk. valamint meghatározhatjuk. itt csak a feladathoz szükséges mélységig érintjük a témát. Azaz nem csupán kezdő.virtualearth. nevezetes helyek.és végpontot adhatunk meg.virtualearth.net/webservices/v1/geocodeservice/geocodeservice. távolság.svc A szerverrel való kommunikációról bővebben a 9. Route Service – Útvonalak tervezése általunk megadott köztes pontok között.svc http://dev. koordinátákká alakítása vagy koordináták alapján ezek kinyerése. majd ezt a gráfot bejáró ponthalmazt ad vissza nekünk. földrajzi nevek keresése. Néhány fontosabb ezek közül:   Geocode Service – Címek. Ezen a listán a tervező algoritmus sorban végigmegy. Search Service – Nevezetes helyek. például éttermek.net/webservices/v1/routeservice/routeservice. sőt akár a forgalmi helyzettel való számolást is kérhetjük). mozik keresése – ez pozícióhoz is köthető.Térképek kezelése 4-9 ábra: Gombok az ApplicationBaron a rétegek megjelenítésének szabályozására Egyéb szolgáltatások A térképen kívül számos egyéb rendkívül hasznos szolgáltatást kínál számunkra a Bing Maps.virtualearth.svc http://dev. majd a felugró listán válasszuk az Add Service Reference opciót (4-10 ábra)! 93 . szabványos SOAP webszolgáltatásokon keresztül elérhető a fejlesztők számára. fejezet szól. hanem érintett pozíciók egész listáját. hogy milyen szempontból keressen optimális eredményt (sebesség.  A fenti szolgáltatások az alábbi címeken érhetők el: Szolgáltatás Geocode Service Route Service Search Service Cím http://dev. Gyakorlatilag az összes főbb funkció. A szolgáltatások hozzáadásához kattintsunk a projektre az egér jobb gombjával. Lehetőségünk van az utazás módjának beállítására (gyalog / autóval).net/webservices/v1/searchservice/searchservice.

A dialógusban lévő Discover gomb lehetőséget biztosít. 4-11 ábra: A szolgáltatás leírása alapján a Visual Studio felismeri az elérhető funkciókat Útvonaltervezés A táblázatból válasszuk ki a Route Service-t. ehelyett egy Credential típusú objektumot is létre kell hoznunk: 94 . amit a Bing Maps regisztrációjánál kaptunk. amelynek metódusai a szolgáltatást címzik meg.4. és ennek címét adjuk meg az Add Service Reference dialógusban! A generált osztály névtere legyen RouteService! Az OK gombra kattintva létrejönnek a kapcsolatot felépítő és a kommunikációt biztosító osztályok. Haladó alkalmazásfejlesztés Windows Phone-on 4-10 ábra: Szolgáltatás referenciájának hozzáadása Az itt felugró ablakon adjuk meg a választott szolgáltatás címét. a MainPage osztály elején. this.DataContext = this. de mi itt csak kliens alkalmazást fejlesztünk. természetesen a RouteService névteret fel kell vennünk egy using taggal a file elején: public MainPage() { InitializeComponent(). Itt már nem használhatjuk a XAML-ben rendelkezésünkre álló egyszerűsített értékadást. Hozzuk is létre ezt a proxyt a MainPage konstruktorában! Ahhoz. Ezt érdemes egy külön változóban tárolni. hogy a keretrendszer megtalálja ezt az osztályt. RouteServiceClient proxy = new RouteServiceClient(). } Ezeknél a szolgáltatásoknál szintén szükségünk lesz arra az azonosítóra. így erre nem lesz szükségünk. Ezt követően példányosítással létrehozhatunk egy proxy objektumot. majd kattintsunk a Go gombra (4-11 ábra)! Ekkor a Visual Studio lekéri a cím mögött lévő szolgáltatás WSDL leírását. és kiolvassa belőle az elérhető interfészeket és azokon belül a felkínált funkciókat. így a távoli metódusokat egyszerű függvényhívásokkal érhetjük el programunkból. hogy a környezet a mi saját Solutionünkön belül keressen elérhető szolgáltatásokat.

készítsük fel a megjelenítő felületet az adatok fogadására.Location}. Erre a RouteOptions osztályt alkalmazhatjuk. // autóval közlekedünk Mode = TravelMode.. Hozzuk most létre a bejárandó pontok listáját! Ez egy szintén a RouteService névtérben (vagy amilyen nevet a szolgáltatás referenciájának hozzáadásánál választottunk) lévő osztály. // végpont new Waypoint{Location = PetrolStations[0]. A kérésre adott válasz az egyéb fontos információkon felül tartalmazni fogja az érintett pontok listáját is.Location} }. // leggyorsabb útvonal keresése Optimization = RouteOptimization. // forgalom alapján is optimalizáljon az időre TrafficUsage = TrafficUsage. ami a kalkuláció szempontjait definiálja. a WayPoint példányait jelenti. mivel ez alapértelmezés szerint None. amely a majd átadott pontok között autóval a lehető leggyorsabban bejárható úgy. vagyis azokat a pontokat. amelyeket csupán egyenesekkel össze kell kötnünk és fel kell rajzolnunk a térképre. Térjünk vissza ezután a konstruktorba.MinimizeTime. Itt tartalmazzon csak két elemet. amelyben az egyéb beállítások mellett arra mindenképp figyeljünk. ".TrafficBasedTime. A XAML-ben keressük ki újra a térkép leírását. Ezzel a konfigurációval tehát olyan útvonalat keresünk. Options = options. A konfigurációs objektumok létrehozása után már előállíthatjuk azt a kérést. amit a szolgáltatás már fel tud dolgozni: var request = new RouteRequest { Credentials = cred. Ez a lista az út „töréspontjait” írja le. Waypoints = points }. hogy a RoutePathType tulajdonságot állítsuk a RoutePathType enumeráció Points elemére.Driving }. és állítsuk össze az útvonaltervezéshez szükséges kérést! Szükségünk lesz egy olyan objektumra. Mielőtt megpróbálkoznánk az útvonal előállításával. azaz az érintett pontok lekérdezését külön igényelnünk kell! var options = new RouteOptions { // a pontok listáját igényelnünk kell! RoutePathType = RoutePathType. private readonly Credentials cred = new Credentials { ApplicationId = credStr}. hogy a jelenlegi forgalmi helyzetet is figyelembe vesszük.Points.Térképek kezelése private const string credStr = "Ajdyq5FaN2Rzvzvogm_. és egészítsük ki az alábbi sorokkal: 95 .. a kiindulási és az érkezési pontot: // érintett pozíciók var points = new ObservableCollection<Waypoint> { // kezdőpont new Waypoint{Location = Pubs[0].

valamint egy BoundingRectangle nevű elemet. Ennek e paramétere egy CalculateRouteCompletedEventArgs típusú objektum. Ennek szellemében írjuk meg a lekérdezést: proxy. de ezt egy konverziós ciklussal orvosolhatjuk. ehelyett az eredmény elkészültét jelző események argumentumaiként juthatunk hozzá az igényelt adatokhoz.Result.CalculateRouteAsync(request).Add(item).RoutePath. ami tartalmazza a művelet végrehajtását leíró adatokat(pl.Result. az ennek megtételéhez szükséges időt. Ezen kívül minden adat kötése egyértelmű. Haladó alkalmazásfejlesztés Windows Phone-on <TextBlock Name="tbDistance" /> <maps:MapPolyline Name="lRoute" Stroke="#FF2C76B7" Opacity="0. foreach (var item in e.Distance. valamint a kalkulált útvonal részleteit.ToString(). var lc = new LocationCollection().Result. Ehhez csupán a vezérlő Locations tulajdonságát kell beállítani egy ObservableCollection<Waypoint> példányra.Result. Ennek nagy előnye.Summary. hogy a felhasználói felület nem áll le arra az időre. } lRoute. és nézzük meg. A CalculateRouteCompleted eseménykezelője az egyszerűség kedvéért lehet helyben definiált anonim metódus is. az lRoute nevű MapPolyline objektum pedig felrajzolja azt. azaz a készülék végig válaszra kész marad. amíg a kérésünkre előállított válasz megérkezik.Summary.Result. ami annak a téglalapnak az északkeleti és délnyugati koordinátáját tartalmazza. A pontok halmaza sajnos más típusban érkezik.Locations = lc. hogy hogyan jelenik meg mindez az emulátoron (412 ábra)! 96 . Ennek következménye.4.85" StrokeThickness="6" /> A tbDistance fogja megjeleníteni az útvonal hosszát. állítsuk a térkép nézetét a visszakapott BoundingRectangle-re! Nincs más hátra. amely magába foglalja a teljes útvonalat. Fordítsuk le és futtassuk a projektet. e) => { tbDistance. mint amit a megjelenítő elem vár.Text = e. aminek elemeit használva rajzolja majd ki az út szakaszait.Points) { lc. A Summary tulajdonságon keresztül elérhetjük a szakaszok együttes hosszát.Result.SetView(e. indítsuk el az aszinkron kérést! // kérés indítása proxy. }.CalculateRouteCompleted += (s.BoundingRectangle). // pozícionáljuk a térképet az útvonalra! myMap. sikeres volt-e). Miután ezeket a műveleteket elvégeztük. hogy azonnali visszatérési értékkel nem rendelkeznek a függvények. A szolgáltatás meghívása WP7 esetében a WCF automatikusan aszinkron műveleteket generál a szolgáltatással való kommunikációra.

a bal felső sarokban pedig megjelenik a szakaszok együttes hossza. 97 . NavigationService – ez egy osztály. míg az App az Application-ből származik. Navigating – A navigáció indítványozásakor következik be. Az oldalak közti navigáció megvalósítására két lehetőségünk van:         HyperlinkButton – egyszerűen használható vezérlő. tulajdonságai és eseményei: GoBack() – Visszanavigál az előző oldalra. egy önálló entitás. amin keresztül könnyen kézben tarthatjuk a navigációs folyamatokat. A NavigationService fontosabb metódusai. Az oldalak különálló egységeket alkotnak. ugyanis a MainPage szülő osztálya a PhoneApplicationPage. Ebben a részben ezeket a lehetőségeket fogjuk áttekinteni. Az egyszerű oldalváltáson túl függvényeket. amely elemeket jelenít meg. A PhoneApplicationPage elképzelhető úgy is. CurrentSource – Az éppen mutatott oldal címe. hogy a teljes útvonal kékkel kiemelve látszik. mint egy weblap. azonban ahogyan weblapok esetében is. és rendelkezik a más oldalak eléréséhez szükséges eszközökkel.xaml fájllal. ugyanúgy. eseményeket kínál számunkra. de felüldefiniálhatjuk a kinézetét. mint a Back gomb lenyomásakor.Navigáció 4-12 ábra: Az útvonaltervezést is tartalmazó kész alkalmazás Az ábrán látható. Navigáció A tartalom rendszerezésének egyik magától értetődő eszköze önálló oldalak létrehozása. itt is gyakran szükséges valamilyen kommunikációt biztosítani a lapok között. Navigated – A navigáció végét jelző esemény. Oldalak Minden Windows Phone 7 projekt a létrehozásakor két XAML állománnyal rendelkezik: egy MainPage nevű oldallal és egy alkalmazásszintű erőforrásokat és eseményeket tartalmazó App. Navigate(Uri) – Átnavigál az Uri által meghatározott címre. ami egy linkhez hasonlóan jelenik meg. akkor ezek hasonlónak tűnhetnek. Ha csak a Solution Explorerben nézünk rá a fájlrendszerre. de egészen másról van szó.

xml-t (4-14 ábra)! 98 . amivel ezt módosíthatjuk(RemoveBackEntry). csupán néhány alapbeállításban térnek el egymástól.xaml-t! Az oldalak közti váltás már működne.Relative)). A NavigationService a felsorolt lehetőségein túl elérhetővé teszi a korábbi oldalak listáját (BackStack) és egy eljárást is. de ez a WP7 esetében mindig false értékű lesz. amelyen keresztül elérhetjük a többi lapot. ami egy főmenüt fog tartalmazni.Row="1" Margin="12. azonban egy probléma még van: a MainPage nyílik meg először. UriKind. Ezen az új oldalon adjunk a ContentPanel nevű Gridhez egy StackPanelt. } A Navigate függvény egy URI-t vár. Az első segítségével férhetünk hozzá a QueryString-hez.12. amely alapértelmezés szerint abszolút.0"> <StackPanel> <Button Name="btnMap" Content="Térkép" Click="btnMap_Click" /> </StackPanel> </Grid> Menjünk át a kódot tartalmazó forráskód állományhoz (legegyszerűbb az F7 lenyomásával a XAML fájlhoz tartozó forráskódra ugrani). azon belül pedig helyezzünk el egy gombot: <Grid x:Name="ContentPanel" Grid. Ezzel a paranccsal címezzük meg a fejezet első részében létrehozott MainPage. Ezek kipróbálására egészítsük ki az előző alkalmazást egy új oldallal. az URL-ben átadható paraméterek kulcs-érték szótárát jelenti. ha ezt relatívra cseréljük. az oldal neve pedig legyen MainMenuPage! A többi sablon is ehhez hasonló szerkezetű. azaz a GoForward(Uri) függvény kivételt dob. onnan pedig sehova nem tudunk navigálni! A megoldáshoz nyissuk ki a Properties mappát. A PhoneApplicationPage navigációs eszköztára két fontosabb részből áll.4. RoutedEventArgs e) { NavigationService. Itt a gomb Click eseménykezelőjében használjuk fel a már említett NavigationService-t az oldalváltásra: private void btnMap_Click(object sender. a NavigationContext-ből és az előbb említett NavigationService-ből. Ehhez a projekt gyorsmenüjéből válasszuk az Add  New Item funkciót (4-13 ábra)! 4-13 ábra: Új elem hozzáadása a projekthez Az Add New Item ablakban válasszuk a Windows Phone Portrait Page sablont. nekünk viszont most egyszerűbb lesz. valamint az ehhez kapcsolódó előrenavigálás. Haladó alkalmazásfejlesztés Windows Phone-on   Source – A jelenleg aktív vagy mindjárt aktívvá váló oldal címe. mint weblapok esetében. azon belül pedig keressük ki a WMAppManifest.xaml".Navigate(new Uri("/MainPage. ami csakúgy. CanGoBack – Tudunk visszafelé navigálni? Azaz van-e bejegyzés az oldalak közti lépkedést rögzítő veremben? A NavigationService rendelkezik egy CanGoForward tulajdonsággal is.0. mint például a lap orientációja.

ehhez írjuk át a Tasks-on belül a DefaultTask-ot: <Tasks> <DefaultTask </Tasks> Name ="_default" NavigationPage="MainMenuPage. az operációs rendszer verzióját).Show(myParam).Navigate(new Uri("/MainPage.xaml"/> Most már tesztelhetjük programunkat! A kezdőképernyő a „Térkép” gombot fogja mutatni. ha például egy lista valamely elemének részleteit szeretnénk egy külön lapon megmutatni. } A paraméter kiolvasása a másik oldalon a NavigationContext segítségével egyszerűen megoldható: string myParam. amelyek közvetlenül az oldal létrejötte után vagy a deaktiválódása előtt futnak le.QueryString. Ha például nem használunk Push Notificationt. címét. így adva lehetőséget arra. mert itt tudjuk átírni alkalmazásunk metaadatait (például a kiadó nevét. Ekkor hasonlóan. RoutedEventArgs e) { NavigationService. out myParam)) { MessageBox. adatkezelést nélkülöző programoknál elég lehet az. Ennek legegyszerűbb megoldása a QueryStringek használata. Adatátvitel az oldalak között Egyszerű. } Navigációs metódusok A PhoneApplicationPage ősosztálya.TryGetValue("myParam". amire kattintva átjutunk a korábban létrehozott útvonaltervezőnkre. beállítani a kezdőoldalt. csak az URL-t kell kiegészítenünk az átadandó kulcs-érték párokkal: private void btnMap_Click(object sender. Mivel ezek virtuális eljárások. Ugyanez már kevés lehet. Ezenfelül a Capabilities szekcióban találhatjuk az igényelt képességek listáját. animálás) elvégezzünk. ahonnan pedig a hardveres Back gombbal térhetünk vissza. a Page a NavigationService osztályon túl tartalmaz virtuális metódusokat. akkor érdemes az erre vonatkozó elemet eltávolítani (bár ennek elmulasztásával sem vesztünk semmit). hogy független oldalak között váltogatunk. Most elegendő a kezdőoldalt kicserélnünk. mint weblapok esetében. hogy a navigációval kapcsolatos feladatokat (például argumentumok kiolvasása. if (NavigationContext. leírását. UriKind.xml a projekt Properties mappájában Azért is érdemes megismerkednünk ezzel az állománnyal. a Splash képet és az ikonokat.Relative)).Navigáció 4-14 ábra: A WMAppManifest. Ugyanis valahogyan meg kell mondanunk a részleteket tartalmazó oldalnak. hogy melyik elemet választotta a felhasználó. a saját oldalainkon felül tudjuk definiálni őket az override kulcsszó használatával: 99 .xaml?myParam=test".

if (NavigationContext. és visszanavigál erre az oldalra. Ilyenkor nem elegendő az ItemsSource-ot újra a BackStack- 100 . BackStack Az alkalmazásunkon belüli lapváltásokat egy verem tárolja. Hozzunk létre egy új oldalt Navigation névvel. A DisplayMemberPath tulajdonság beállításával jelezzük. úgyhogy új objektumra kell állítanunk az ItemsSource-ot! */ icNavigationList.Navigation.NavigationEventArgs e) { base.OnNavigatedTo(e). és ezzel módosíthatjuk a navigációs szolgáltatás működését! A kódfájlban írjuk felül az OnNavigatedTo eljárást. amiről a hardveres Back gomb leveszi a legfelső elemet. RoutedEventArgs e) { NavigationService.TryGetValue("myParam".Windows. hogy frissült. // saját kód string myParam.OnNavigatedTo(e). // saját kód } Ehhez hasonlóan hozzáférhetünk az oldal elhagyását megelőző OnNavigatingFrom és OnNavigatedFrom függvényekhez is.Navigation. amit készítsünk fel egy kapott paraméter és a korábbi címek kiírására a ContentPanel kiegészítésével! <Grid x:Name="ContentPanel" Grid.BackStack. hogy az beállítsa a XAML-ben definiált vezérlők hiányzó értékeit. amivel a verem legutóbbi elemét el tudjuk távolítani. } icNavigationList.Windows.Text = myParam. } private void btnDelete_Click(object sender. Mi viszont az egyszerűség kedvéért nem használtunk adatkötést.ItemsSource = NavigationService. hogy a későbbiekben bekötött elemek Source tulajdonságát akarjuk kiírni! Vegyünk fel még egy gombot is.ToList().12.ItemsSource = NavigationService. } Ha felveszünk valahova egy linket. A RemoveBackEntry függvény törli a navigációs verem felső elemét. Ehhez a veremhez mi is hozzáférhetünk. ami erre az oldalra mutat.NavigationEventArgs e) { base.QueryString. Haladó alkalmazásfejlesztés Windows Phone-on protected override void OnNavigatedTo(System.0. sőt a visszalépést is egyszerű függvényhívással megvalósíthatjuk. a gomb eseménykezelője viszont egy kis magyarázatot érdemel. és töltsük ki a gomb eseménykezelőjét is! protected override void OnNavigatedTo(System.BackStack.RemoveBackEntry().Row="1" Margin="12. out myParam)) { tbMyParam. azaz a BackStack nem ad magáról értesítést a megjelenítő vezérlőnek arról. /* nem használtunk adatkötést.0"> <StackPanel> <TextBlock Name="tbMyParam" Text="Nem érkezett paraméter"/> <Button Name="btnDelete" Content="Törlés" Click="btnDelete_Click" /> <ItemsControl Name="icNavigationList" DisplayMemberPath="Source"/> </StackPanel> </Grid> Az icNavigationList fogja megjeleníteni a látogatott oldalak vermét.4. már megfigyelhetjük a NavigationService működését. Az OnNavigatedTo működése magától értetődő.

amely használja a NavigationService-t.xaml-re navigál − akár paraméter átadásával −. A Vissza gomb pedig csupán akkor aktív.Navigáció re állítani. például a BackStack-ből előálló listára kell állítanunk az icNavigationList-et.org/markup-compatibility/2006" mc:Ignorable="d" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" d:DesignHeight="480" d:DesignWidth="480" Height="100" Width="450"> <Grid x:Name="LayoutRoot" HorizontalAlignment="Center"> <StackPanel> <HyperlinkButton Content="Navigation" NavigateUri="/Navigation.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas. hiszen ugyanezen verem alapján dolgozik az is. úgyhogy a vezérlő sem frissül.com/winfx/2006/xaml" xmlns:d="http://schemas. Ez azért is érdekes téma. és nevezzük el vezérlőnket NavigationBar-nak! Ezt a vezérlőt úgy alakítjuk ki. hogy a középső TextBox értékét átadja a megcímzett oldalnak. mert a UserControl osztály nem tartalmaz NavigationService-t.xaml" /> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <Button Name="btnBack" Content="Vissza" Click="btnBack_Click" /> <TextBox Name="tbNameParam" Width="200"/> <Button Name="btnNavigationPage" Content="Adatok" Click="btnNavigationPage_Click" /> </StackPanel> </StackPanel> </Grid> </UserControl> 101 . ami a paraméter nélküli oldalváltást teszi lehetővé. A dolog varázsa az. Több lap esetében pedig érdemes lehet a minden oldalon megvalósítandó funkciókat a folyamatos másolgatás helyett egy UserControl-ba szervezni.microsoft. Ennek megvalósításához az Add New Item menüben válasszuk a Windows Phone User Control sablont. A kész vezérlő megjelenítése a 4-15 ábrán látható. Komplexebb navigáció megvalósításához olyan felhasználói vezérlőt kell készítenünk.NavigationBar" xmlns="http://schemas. hogy bárhonnan a Navigation. valamint felkínál egy gombot. Így ha törüljük a legfelső elemet.microsoft. amikor a BackStack nem üres.microsoft. ami a hardveres vissza gombbal megegyező funkcionalitású. azzal a kiegészítéssel. 4-15 ábra: Az elkészítendő navigációs vezérlő Az ehhez tartozó XAML kód: <UserControl x:Class="_04_Advanced_Development.openxmlformats. azaz az alkalmazáson belül is tudunk még visszafelé navigálni. Az alkalmazás kiegészítése navigációs vezérlőkkel Az előző példa kevés oldal esetén még nem igazán látványos. hiszen a referencia ekkor nem változik. Az Adatok gomb ugyanezt valósítja meg. A Navigation vezérlő egy Hyperlink.com/expression/blend/2008" xmlns:mc="http://schemas. Ehelyett egy új példányra. akkor az előtte lévőre fog a gomb visszavezetni. hogy ezzel a törléssel a hardveres Back gomb működését is befolyásoljuk.

Haladó alkalmazásfejlesztés Windows Phone-on A felhasználói vezérlőkben a navigáció kulcsa az. } return _frame. RoutedEventArgs e) { Frame.GoBack(). és valósítsuk meg a Frame tulajdonságot. RootFrame nevű mezőt. e) => { btnBack. } Frame. tbNameParam. }. ami a beleágyazott oldalak cserélgetését segíti. } private void btnBack_Click(object sender.Navigate(new Uri(target. események) biztosításával.4. RoutedEventArgs e) { string target = "/Navigation. target. Menjünk most a NavigationBar kódfájljába. bárhol az oldalon: 102 . A WP7-es programokban szerencsére mindig található ilyen. Ezek tudatában fejezzük be a forrásfájl kiegészítését! public NavigationBar() { InitializeComponent(). UriKind. hiszen az App osztály tartalmaz egy publikus PhoneApplicationFrame típusú. Ez egy fix keret. navigációs függvények.Text).Relative)).Format("{0}?myParam={1}". nagyjából ugyanazokat a funkciókat érhetjük így is el. amely egy hivatkozás a RootFrame-re! private Frame _frame.Relative)).IsEnabled = Frame. már csak fel kell használni azt! Ehhez a XAML fájlokat kell csak módosítanunk. this. hogy referenciát szerzünk egy olyan objektumra.Navigate(new Uri(string. } private void btnNavigationPage_Click(object sender.Loaded += (s. public Frame Frame { get { if (_frame == null) { _frame = (App. ami rendelkezik az ehhez szükséges képességekkel.CanGoBack. többek között a navigációhoz szükséges feltételek (Source tulajdonság.Current.Text)) { Frame. UriKind.IsNullOrEmpty(tbNameParam. } A vezérlő ezzel elkészült. először vegyük fel a projekt névterét például local névvel: xmlns:local="clr-namespace:_04_Advanced_Development" Majd helyezzük el az egyéb tartalmak között. if (!string.xaml". mintha az egy NavigationService példány lenne. } } A Frame a navigációs feladatok során úgy kezelhető.RootVisual as PhoneApplicationFrame).

A WP7 programok kinézetének meghatározó formálói. Szorosabban kapcsolódó adatok megjelenítésére vagy egyszerűen látványosabb UI létrehozására is két remek vezérlő áll rendelkezésünkre. törlünk párat. 4-17 ábra: A Pivot és Panorama kapcsolata az osztályhierarchia alapján Példák a vezérlők alkalmazására az Office programból: 103 . nem véletlen. hogy bejárjuk az összes oldalt. pontosabban a TemplatedItemsControlból származik (4-17 ábra).Pivot és Panorama <local:NavigationBar VerticalAlignment="Bottom" /> Próbáljuk ki alkotásunkat úgy. és megnyomjuk a vissza gombokat! Ha minden jól működik. amelyeket ebben a részben ismerhetünk meg. akkor sikerült elsajátítani az oldalak közti navigáció trükkjeit (4-16 ábra)! 4-16 ábra: A BackStack tartalma és az átadott paraméter is látszik a Navigation oldalon Pivot és Panorama Az előző részben láttuk. hogy a beépített alkalmazások többsége is ezek felhasználásával készült el. hogyan tudjuk alkalmazásunkat oldalakkal strukturálni. majd a végén meglátogatjuk a navigációt összegző lapot. horizontálisan elnyúló vezérlő. Mindkettő az ItemsControlból. A Pivot és a Panorama két nagyon hasonló.

mivel a következő lap jobbról belóg az aktívba. Adatok rendszerezésére. A háttérkép horizontálisan fix (a tabokra definiálhatunk természetesen külön hátteret). Hozzunk létre ezekből egy-egy példányt. RSS olvasóban kategóriák szétválasztásakor használjuk. Érdemes nem telezsúfolni a lapokat. azaz egy PanoramaPage és egy PivotPage nevű oldalt! Az elemeket persze bármilyen oldalon létrehozhatjuk a vezérlő szokásos hozzáadásával is. A sablonból generált PanoramaPage tartalmaz egy Panorama vezérlőt. Ezek az elemek jelenleg csak üres Grideket jelenítenek meg. nem kell ragaszkodnunk a sablon használatához. Alkalmazás kezdőoldala. esetleg hierarchikus elrendezésre érdemes használni. Az összes elem egyszerre kerül leképzésre a megjelenítéshez. ezért ennek területét teljesen kihasználhatjuk. így ezen is lapozhatunk. hogy külön oldalsablont építettek be mindkettő számára (sőt. Pl. Csak az aktív lap és a mellette lévők kerülnek leképzésre a megjelenítéshez. ha erre szükségünk van. alkalmazássablont is találhatunk). de ha átírjuk őket. akkor bármilyen komplex lapot használhatnak. mint a kijelző. Fontos megjegyezni. egy címmel és két előre létrehozott elemmel. Pl. Figyelemkeltő kezdőoldalak. A háttérkép szélesebb. Panorama Egy horizontálisan elnyúló. funkciók bemutatása esetén hasznos. <Grid x:Name="LayoutRoot"> <controls:Panorama Title="my application"> <!--Panorama item one--> <controls:PanoramaItem Header="item1"> <Grid/> 104 . folyamatos oldal érzetét kelti. jobbra a leveleket csoportosító Pivot látható Különbségek Pivot Lapokra osztott rendszerezés az egyes lapok közti átmenet nélkül.4. Haladó alkalmazásfejlesztés Windows Phone-on 4-18 ábra: Balra az Office alkalmazás Panorama vezérlője. mindenképp használjunk Pivotot! Emellett a Panorama és a Pivot egymásba ágyazva nem használható! A vezérlők népszerűségét jelzi az is. hogy Panorama vezérlő esetén kerülni kell az ApplicationBar használatát. Egyszerre csak egy lap látszik. kategóriák kezelésére.

Silverlight Toolkit for Windows Phone7 Az eddig bemutatott vezérlőkkel már egy gazdag eszközkészletből válogathatunk.jpg" /> </controls:Panorama.com. beágyazásuk pedig a Background tulajdonság hozzáadásával történik (4-19 ábra): <controls:Panorama. 105 . Miután telepítettük a csomagot. Ilyeneket könnyen találunk az interneten. az elérhető a Visual Studio Add Reference dialógusából (4-20 ábra). ami új vezérlők felkínálásán túl a Metro stílus kialakításában is hasznos társunk lehet. Ezek elvégzését könnyíti meg a Silverlight Toolkit. de számos ismétlődő feladat még így is ránk hárul.Silverlight Toolkit for Windows Phone7 </controls:PanoramaItem> <!--Panorama item two--> <controls:PanoramaItem Header="item2"> <Grid/> </controls:PanoramaItem> </controls:Panorama> </Grid> A dolog látványossá tételéhez csupán egy széles háttérkép hiányzik.Background> 4-19 ábra: Panorama egy háttérkép megadása után A táblázatban kiemelt különbségeken túl a Pivot használata teljesen megegyezik a Panorama vezérlőjével. így ennek kipróbálására most nem térünk ki. Telepítés A készlet használatához töltsük le a telepítőt a projekt hivatalos weblapjáról: http://silverlight.codeplex.Background> <ImageBrush ImageSource="Images/bgPanorama.

assembly=Microsoft.Toolkit" Fontosabb vezérlők HubTile – A főoldal lapkáihoz hasonló dinamikus vezérlő. 4-21 ábra: A HubTile állapotai Ezt a vezérlőt az alábbi módon illeszthetjük be a felhasználói felületbe:: <toolkit:HubTile Name="hirekTile" Tap="hirekTile_Tap" Title="Hírek" Source="Images/news.1\Toolkit\Aug11 \Bin\Microsoft.4. a már ismert módon adjuk hozzá a névteret a leíráshoz: xmlns:toolkit="clrnamespace:Microsoft. Haladó alkalmazásfejlesztés Windows Phone-on 4-20 ábra: A Toolkit szerelvénye a telepítés után elérhető Ha mégsem találjuk itt.png" Background="#E51400" GroupTag="TileGroup" Margin="6" Notification="1 új hír" DisplayNotification="True" Message="Microsoft Minősített Szerviz Partner project"> MultiselectList – Az Office alkalmazás levéllistájához hasonlóan lehetővé teszi. nagyszerűen használható menük kialakítására.Phone.Controls. amelyek az egyszerű navigáción túl információt.Phone. hogy az elemeket a XAML-ben is elérjük.dll Ahhoz.Toolkit.Phone. hogy a felsorolt elemek közül többet is kiválasszunk (4-22 ábra). 106 . akkor keressük ki a Microsoftos SDK-k közül! Nálam ez a szerelvény itt található: C:\Program Files\Microsoft SDKs\Windows Phone\v7.Controls. üzeneteket is szolgáltatnak a felhasználó számára (4-21 ábra).Controls.

elem" /> </toolkit:MultiselectList> ExpanderView – Szintén a leveleknél (pontosabban a hosszabb levélváltásoknál) megszokott lista. amelynek egy elemét kiválasztva az lenyílik. elem" /> <toolkit:MultiselectItem Content="3.Expander> <Rectangle Height="80" Width="400" Fill="Blue" /> </toolkit:ExpanderView.Items> <TextBlock Text="Alelem 1" /> <TextBlock Text="Alelem 2" /> </toolkit:ExpanderView. elem" /> <toolkit:MultiselectItem Content="2.Expander> <toolkit:ExpanderView. és a részletei is láthatóvá válnak (4-23 ábra). 4-23 ábra: Hasonló vezérlő a levélváltások részletezésénél Ezt a vezérlőt az alábbi módon használhatjuk: <toolkit:ExpanderView> <toolkit:ExpanderView.Silverlight Toolkit for Windows Phone7 4-22 ábra: A levelek kiválasztásakor is egy ugyanilyen funkcionalitású vezérlővel találkozunk Használata: <toolkit:MultiselectList> <toolkit:MultiselectItem Content="1.Items> </toolkit:ExpanderView> 107 .

Ez hasznos lehet. az egyik szövegesen kiírja a jelenleg beállított időpontot. Segít a megszokott Metro stílusú átmeneteket egységes módon használni. erre kattintva pedig a másik. 4-25 ábra: A TimePicker két nézete 108 . ha eléri a sor (vagy oszlop) végét. Két nézettel rendelkezik. azaz nem tudunk róla a telefon kezeléséhez használt gesztusok segítségével a környező lapokra navigálni. ha horizontálisan görgethető elemeket használunk a lapon. WrapPanel – A Panel osztályból származó konténertípus. vagy egyszerűen csak lapoznánk. akkor a kitöltést a következő sorban (oszlopban) folytatja. A StackPanelhez hasonlóan egymás mellé vagy alá helyezi az elemeket az Orientation tulajdonságától függően. A StackPanellel szemben.4. ami lezárja az aktív lapot. Haladó alkalmazásfejlesztés Windows Phone-on LockablePivot – Kiegészíti a Pivotot egy zárolási lehetőséggel. az Alarm alkalmazásból ismerhetjük. az időpontot beállító elrendezést láthatjuk (4-25 ábra). például galériákat megjeleníteni (4-24 ábra). hiszen ilyenkor nem egyértelmű. 4-24 ábra: WrapPanel horizontális elrendezéssel Használata: <toolkit:WrapPanel> <toolkit:HubTile Background="Green" Title="Zöld" /> <toolkit:HubTile Background="Red" Title="Piros " /> <toolkit:HubTile Background="Blue" Title="Kék" /> </toolkit:WrapPanel> TimePicker – Időpontok megadására használható vezérlő. Ezzel egyszerűen tudunk ismeretlen elemszámú listákat. PageTransitions – Az oldalak közti átmenetet kísérő animációk használatát megkönnyítő osztály. hogy például egy ScrollBar értékét kívánjuk módosítani.

akkor az elemre vonatkozó menü ugrik fel.Background> <ImageBrush ImageSource="Images/tileBg.png" /> </Grid.ContextMenu> <toolkit:ContextMenu> <toolkit:MenuItem Header="Menü 1" Click="MenuItem_Click" /> </toolkit:ContextMenu> </toolkit:ContextMenuService. a menü előállításában pedig a ContextMenu vezérlő segít minket. pontosabban ezt kivéve minden más kissé távolabbra kerül. hiszen tájékoztatja a felhasználót a fontos funkciókról.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid. üzeneteket jeleníthet meg és látványos.0" Style="{StaticResource PhoneTextTitle1Style}"/> 109 .0.28"> <TextBlock x:Name="PageTitle" Text="OEM Portal" Margin="9.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid. 4-26 ábra: ContextMenu 1 elemmel. Ez a menü mindig egy másik vezérlőhöz kapcsolódik. így az animálással sem kell külön foglalkoznunk (4-26 ábra). a ContextMenuService-t kell felvennünk a funkcióval kiegészítendő kontrollba. A menü megjelenésén túl a hivatkozó vezérlő ki is emelkedik a többi közül. <Grid x:Name="LayoutRoot"> <Grid. így gyakorlatilag egy szolgáltatást. hogy ha egy elemre kattintunk az egér jobb gombjával.Silverlight Toolkit for Windows Phone7 Használata: <toolkit:TimePicker Name="tpAlarm"/> ContextMenu – A PC-ken megszokhattuk.Background> <Grid. animált felületet is biztosít.17. Egy ehhez hasonló lap remek belépési pont lehet bármely alkalmazás számára. a háttérben pedig látható a kiemelő effekt Használata: <toolkit:HubTile Tap="hirekTile_Tap" Title="Minden" Source="Images/all.-7. A WP7 platformon ezt a viselkedést egy elem hosszan lenyomva tartásával érhetjük el.png" Margin="6" Background="#FF008000" GroupTag="TileGroup" Notification="Noti" Message="Microsoft Minősített Szerviz Partner project"> <toolkit:ContextMenuService.0.Row="0" Margin="12. ami a toolkit előnyeit felhasználva egy áttekinthető. informatív és esztétikus menüt tartalmaz.ContextMenu> </toolkit:HubTile> Példaprogram Hozzunk létre egy olyan oldalt.

png" Margin="6" Background="#FFF79608" GroupTag="TileGroup" Notification="Noti" Message="Microsoft Minősített Szerviz Partner project"> </toolkit:HubTile> <toolkit:HubTile Tap="hirekTile_Tap" Title="Info" Source="Images/info.4. 110 .0.ContextMenu> </toolkit:HubTile> <toolkit:HubTile Name="hirekTile" Tap="hirekTile_Tap" Title="Hírek" Source="Images/news.0"> <toolkit:HubTile Tap="hirekTile_Tap" Title="Minden" Source="Images/all.place additional content here--> <toolkit:WrapPanel x:Name="ContentPanel" Grid.png" Margin="6" Background="#FF00FF" GroupTag="TileGroup" Notification="Noti" Message="Microsoft Minősített Szerviz Partner project"> </toolkit:HubTile> <toolkit:HubTile Tap="hirekTile_Tap" Title="Akció" Source="Images/akcio.12.Row="1" Margin="12. Haladó alkalmazásfejlesztés Windows Phone-on </StackPanel> <!--ContentPanel .ContextMenu> <toolkit:ContextMenu> <toolkit:MenuItem Header="Menü 1" Click="MenuItem_Click" /> </toolkit:ContextMenu> </toolkit:ContextMenuService.png" Background="#297FD5" Margin="6" GroupTag="TileGroup" Notification="2 új hír" DisplayNotification="True" Message="Microsoft Minősített Szerviz Partner project"> </toolkit:HubTile> <toolkit:HubTile Tap="hirekTile_Tap" Title="Esemény" Source="Images/calendar.png" Margin="6" Background="#FF008000" GroupTag="TileGroup" Notification="Noti" Message="Microsoft Minősített Szerviz Partner project"> <toolkit:ContextMenuService.png" Background="#E51400" GroupTag="TileGroup" Margin="6" Notification="1 új hír" DisplayNotification="True" Message="Microsoft Minősített Szerviz Partner project"> </toolkit:HubTile> <toolkit:HubTile Tap="hirekTile_Tap" Title="Letöltés" Source="Images/downloads.png" Margin="6" Background="#A500FF" GroupTag="TileGroup" Notification="Noti" Message="Microsoft Minősített Szerviz Partner project"> </toolkit:HubTile> </toolkit:WrapPanel> </Grid> A fenti kód pedig (természetesen a képek Images mappába másolása után) a 4-27 ábrán látható megjelenést eredményezi.

azokon belül pedig a Panorama és Pivot vezérlőket. az egyszerű címkereséssel és az útvonaltervezéssel. de könnyedén varázsolhatjuk a Metro stílushoz és a Mango felhasználói felület koncepciójához illeszkedő megjelenésűnek azokat.Összefoglalás 4-27 ábra: HubTile-ok WrapPanelbe csomagolva Összefoglalás A fejezet elején részletesen megismerkedhettünk a Bing Maps szolgáltatás felhasználási lehetőségeivel. Végül a Silverlight Toolkit előnyeit ismerhettük meg. ezek között a kiemelt pozíciók jelölésével. Ezekkel a módszerekkel nemcsak hogy rendkívül egyszerűen valósíthatunk meg komplex alkalmazásokat. 111 . Ezt követően átnéztük a tartalmak rendszerezésére szolgáló műveleteket: az oldalak kezelését.

.

Ezek után tovább folytatjuk az ismereteink bővítését olyan újdonságok áttekintésével. A felhasználót megtévesztjük a gyors CPU-nak köszönhetően és elhitetjük vele. amellyel apró darabokra szétbontva a csomagokat a háttérben végezhetünk szerver-kliens kommunikációt. amelyek elérhetőek saját alkalmazásunkból és a telefon beépített eszközeiből is. hogy miért is volt ez így. Ez Windows Phone 7. Asztali operációs rendszerek esetében már nem igazán találkozhatunk olyannal. egymástól teljes mértékben különböző dolgokat? A közös dolog bennük: ezek mind a háttérben képesek dolgozni! Multitasking A fenti kifejezéssel valószínűleg már mindenki találkozott valahol. Lehetőségünk van riasztások és naptárbejegyzések készítésére és felügyeletére is. Egyetemi óra keretein belül. amely a végrehajtandó feladatokat a legoptimálisabb módon juttatja el a központi egységhez. elterjedt mobilplatform esetében. megfelelően teret engedve egymásnak.5 esetében is teljes mértékben igaz. Háttérben futó adatszinkronizációt is megvalósíthatunk alkalmazásunkban. Számos olyan megoldás van a kíváncsi szemek elől elrejtve. mint a multitasking-rendszer ütemező komponenséről. mely egyedibbé. hogy igazodtunk az eredeti feltevéshez. hogy egyszerre több alkalmazás osztozhasson a telefon biztosította erőforrásokon. amely ezt a rendszert ne tartalmazná.NET világában. amely teljesítményben és funkcionalitásban rendkívül sokat hozzátesz a rendszer működéséhez. hanem a központi feldolgozóegység (CPU) kapacitását kihasználva ezek a programok egymás mellett dolgozhassanak. Mielőtt továbbhaladunk a funkcionalitás megismerésében. hogy az operációs rendszer egyszerre ne csak egy alkalmazást tudjon futtatni. ezzel biztosítva. Megnézzük. valahol az operációs rendszer lelkén belül. akik jártak már a . hanem onnan folytathassa. A való világra levetítve a dolgot makroszkopikusan nézve még mondhatjuk. az internetet böngészve. azonban a Windows Phone 7 első verziójában ezt még nem találjuk – legalábbis a fejlesztők által használható módon nem. A teljes fejezet célja – jól áttekinthető formában – megismerkedni az alkalmazások működésének keretével. Minden új technológia rendelkezik saját karakterisztikával. az addig megszokottól különbözővé teszi.5 (a továbbiakban csak a kódnevén említve Mango) újdonságai között nagyon fontos újra megismerkedni egy régi ismerőssel. hogy a felhasználónak a munkáját ne kelljen elölről kezdenie. Az alapötlet szerint a multitasking azért felelős. mint a zenelejátszóval való integráció vagy a hardveres hangerő-szabályozó gombok kezelése. de akár az operációs rendszer súgójának olvasása közben is belefuthatunk. ahol abbahagyta. és mégis rendkívül ismerős azoknak. mi minden történik a háttérben az alkalmazás indulásától a back vagy a Start gomb lenyomásáig. 113 . A Windows Phone 7.5. milyen feladatokat kell ellátnunk az alkalmazás indulásakor és kiléptetésekor. De miért is ebben a fejezetben tárgyaljuk a fent említett. hogyan tudjuk elmenteni a felhasználó által kialakított állapotot és azt a következő indításkor helyreállítani. azonban közelről tekintve ez nem igaz. hogy valóban egyszerre futtat számos programot. de valójában nem másról van szó. most már mi magunk is láthattuk. átnézni. amely lehetővé teszi. így ezeket egymás után nagyon gyorsan végrehajtva valóban a párhuzamosság érzetét kapjuk. azaz a belső ütemező rendszer. mint a többi. hogy ezekre az eszközökre fejleszteni majdnem minden apró mozzanatát tekintve más. kicsit vissza kell vennünk a lendületből és tartani egy apróbb kitérőt. amely nem más. mint a multitasking. Az alkalmazás életciklusa Az előző fejezetek átolvasása után egyre boldogabban tarthatjuk kezünkben Windows Phone telefonunkat. A következőkben választ fogunk rá kapni.

hogy az egymás mellett futó alkalmazások állapotait meg kell tartani. akkor alacsonyabb időigényű folyamatok el fogják pazarolni a nagyobbak elől a számítási időt. Ahhoz. Egységesen mindegyik kap például 100 ms processzoridőt. hogy van X darab folyamatunk (itt ne Windows vagy egyéb operációs rendszer folyamatra gondoljunk. hogy azt mondjuk. hogy ugyanazokat a feladatokat lássák el. asztali operációs rendszerek esetében ma már fel sem merül. A fenti algoritmust round-robin ütemezési algoritmusnak hívják. hogy a hatalmas számítási kapacitás mellett egy operációs rendszer megengedje magának azt a luxust. hogy könnyen implementálható. hogy 50 ms processzoridő el lett pazarolva. Jön először A folyamat. hogy tekintsen a számítógépes algoritmusokra és különböző matematikai problémákra. míg a telefonomban két processzormag 1. ezt úgy hívjuk. és nagyon sokat segít a Mangóban lévő megoldás megértésében – persze ahhoz. akkor ő ki lesz éheztetve. táblagépek.mint például a végtelen ideig tartó futás . ha pedig túl hosszú egy intervallum. és ezeket úgy kellene ütemeznünk a processzor felé. miszerint semelyik folyamatot nem éheztetjük ki. valamint ehhez tartozó magas áteresztőképességű vezetőrendszert tartalmaz. szintén csillogó szemekkel kell. és nagy előnye. hogy mindegyik folyamat dolgozhasson valamennyit. mi ezzel a probléma. Ebből látszik. és a legmagasabb prioritású megkezdheti a futását.4 GHz-es órajelen üzemeltetve. és a számítási sorok végén az eredményeket nagy szélességű buszokra továbbítják.5. így 50 ms üresen marad. Ezzel szemben a telefonom a számítógépem drabális hardvereit egyetlen chipbe tömöríti. Ezeken a problémákon hivatott segíteni a prioritásos ütemezés algoritmusa. bevezetjük itt is az időszeleteket. és annak kell biztosítania a másodpercenkénti 30 képkockát (telefonokon ez a szabványos képkockaszám másodpercenként) ahhoz. Ez matematikailag pont a fele lenne. Ha túl rövid egy időszelet. hogy egyszerre csak egy programot szolgál ki. Elsőre ez a különbség nem tűnik olyan nagynak! Az én laptopomban négy processzormag van 2. És az utolsó mondatból következik még egy probléma! Ha van egy nagyobb prioritású folyamatunk. amiket a számítógépünk − azonban a laptop és a telefon között is van néhány hatalmas különbség. Ez esetben négyszer fog magának lefoglalni egy 100 ms hosszú intervallumot. de a kettő a valóságban összehasonlíthatatlan. Gyorsan hozzászoktunk. a GPU (grafikus számítási egység) és egyéb vezérlők szerepeinek felvállalása minimális energiaellátás és hűtés hiánya mellett! Amikor telefonunkon egy játékkal játszunk. Az alkalmazás életciklusa A feladatütemezés elméletben Ez a rész talán nem illeszkedik szorosan a könyv témájához. Nem beszélve arról. mindegyik kap lehetőséget felszólalni.illetve optimalizáljunk is. Azonban az utóbbi évek során az informatika átesett egy újabb – és egyben sokadik – metamorfózisán. hogy egy játék élvezhető legyen. Azonban. Itt minden folyamat kap egy prioritási értéket. akkor a túl sok váltás lassuláshoz fog vezetni. Okos telefonok. és az addigi nézetek új irányba tolódtak el. ezzel gazdálkodhat egy menetben. Ezek a segédprocesszorok villámsebességgel végeznek el számos összetett aritmetikai műveletet. A legmagasabb 114 . A legegyszerűbb megoldás úgy néz ki. elemi szintű folyamatokról beszélünk). ezek alapján csökkenő sorrendbe állítjuk őket. utána jön C. annak a számítási feladatai mind ugyanahhoz a chiphez futnak be. de az utolsó iterációban 50 ms alatt befejezi a feladatát és terminál. hogy elvégezzen minden számítást. akkor megint A folyamat kerül előre a sorban. ezért az operatív memóriánkat is a lehető legjobban be kell osztanunk. nézzünk egy példát! A folyamatnak összesen 350 ms időre lesz szüksége ahhoz. közvetlenül elérhető és másodlagos tárat. Ahogy azt már említettem. hogy észrevegyük. azonban csak bizonyos ideig. és így a felhasználó azt az érzetet kapja. beágyazott rendszerek jelennek meg sorra és mindegyik valamelyik népszerű operációs rendszer mobilizált változatát használja fedélzeti szoftverként. Azt várjuk el ezektől a kütyüktől. hogy SoC (System on a Chip). dolgozik 100 milliszekundumig. egyik folyamatot sem éheztetjük ki. hogy az elején megelőzzünk súlyos problémákat .2 GHz-es teljesítménnyel. utána őt követi B. és ez alaposan ellentmond az eredeti feltevésünknek. A feladatunk az. a processzor szemszögéből nézzük a problémát. Miért? A számítógépem processzora rengeteg segédprocesszort. egymás mellett futnak az alkalmazásai. azonban véleményem szerint nagyon érdekes téma. hogy ezt a kedves Olvasó is át tudja érezni. Azonban vannak hátrányai. és lassan elképzelni sem tudjuk ezek nélkül az életünket (főleg amióta a szó minden értelmében közösségi lények vagyunk). hogy egyszerre. majd ha C végzett. Egyetlen apró chip feladata a CPU. csak jobban bele kell gondolni. megfelelő energiaellátás és hűtés mellett.

Multitasking prioritású futhat bizonyos ideig, azonban ha lejárt az idő, akkor a következő legmagasabb prioritású kap processzoridőt. A végtelen futás elkerülésének érdekében pedig minden iteráció végén csökkentjük a prioritási értéket, így az eddig legmagasabb prioritású „kevésbé lesz fontos” a következő körben. A mai modern operációs rendszerek is ilyen alapelvekre épülnek, és azt gondolom, a fenti példák és számolások után senki számára sem kétséges, hogy egy mobiltelefon esetében ezeknek az optimális implementálása komoly kihívást jelent. A helyzet messze nem olyan „egyszerű”, mint az operációs rendszerek nagy testvérei esetében: meg kell találni az arany középutat az energiaigény, hardver kihasználása és teljesítménye között.

A multitasking megvalósítása WP 7.5 platformon
Az eredeti Windows Phone 7 operációs rendszer nem tartalmazta a multitasking lehetőségét (ellenben több szálú alkalmazásokat írhattunk), ez a Mango frissítéssel jött. Azonban gondoljunk csak bele jobban, mit is jelent egy mobiltelefon esetében az, hogy több programot futtat! Nincs tálca, ahol egy szempillantás alatt válthatunk az alkalmazások között, nincsenek ablakok, ahol egymás takarásában futnak a programok külön rajzterületeken. Akkor mit nyerhetünk több program futtatásával? A választ két részben kapjuk meg. Először is nézzük az eredeti Windows Phone 7 operációs rendszert! Ha bezártunk egy alkalmazást, vagy az alkalmazás valamilyen okból passzív státuszba került (alkalmazásfelületek között navigálunk pl. egy fénykép készítésekor, vagy túl sokáig nem használtuk a telefont, és ő elment pihenni, stb.), akkor valahova el kellett menteni az aktuális állapotot, majd amikor visszatért a felhasználó az alkalmazáshoz, akkor vissza kellett tölteni az előzőleg elmentett adatokat. A válasz másik része pedig még sokkal szembetűnőbb! Böngészünk, és közben szeretnénk zenét hallgatni. A telefonnal érkezett, Microsoft által készített alkalmazások esetében ez eddig is működött! Mi is azt szeretnénk, hogy a saját alkalmazásunkban lejátszott zene akkor is tovább folytatódjon, ha éppen nem a saját alkalmazásunk aktív vagy a telefon aludni tért. Igen, erre mostantól fogva lehetőségünk van! Nem kell egyszerre látnunk az alkalmazásokat egy kis képernyőn, nem kell ablakban futniuk, ettől még ott lehetnek a háttérben, és ugyanúgy szükségük lehet a processzorra. A Microsoft az eredeti Windows Phone 7 operációs rendszerben nem akarta a telefonok korlátozott hardver erőforrása, energiaigénye és az alkalmazás életciklus-modellje miatt bevezetni a multitaskingot. Ezt azonban előbbutóbb kénytelen volt implementálni, hiszen olyan képességről beszélünk, amelyet nem lehet kikerülni. Az 5-1 ábrán látható, hogyan is épül fel egy alkalmazás életciklusa. Az egész egyetlen nagy állapotgéppel írható le, amelynek középpontjában az az állapot áll, amikor az alkalmazás fut. Azonban mi van olyankor, ha nem fut éppen? Több minden is történhet. Megmaradt az előbbiek során ismertetett állapotmentés mechanizmus is, de ez tovább bővült azzal, hogy a Windows Phone ütemező rendszere eldöntheti, mit tesz az alkalmazásunkkal, és az például egy navigációs művelet során ott maradhat a memóriában. Az állapotok mentésének a későbbiekben több módját is megnézzük, és láthatjuk majd, hogyan válthatunk gyorsan az alkalmazások között − a multitaskingnak köszönhetően.

115

5. Az alkalmazás életciklusa

5-1. ábra: A Windows Phone 7.5 alkalmazások állapotai Nézzük meg, hogy az egyes állapotok és események mit jelölnek! A későbbiek során még számos alkalommal hasznosnak bizonyulhat ez a tudás.  Launching esemény: új alkalmazáspéldányt indítottunk, azaz kiválasztjuk a Start felületen vagy az alkalmazáslistából az alkalmazás lapkáját, esetleg egy értesítéshez tartozó üzenet. Ha az alkalmazás logikája nem igényel mást, akkor itt ne folytassunk munkafolyamatot, ez valóban egy teljesen új példány legyen – persze ez alól vannak kivételek. Ez a kódból kezelhető állapotok közé tartozik. Továbbá fontos, hogy itt erőforrásigényes műveletet ne végezzünk, az alkalmazást engedjük betöltődni minél gyorsabban, nagyobb adategységek betöltését mögöttes szálon hajtsuk végre! Vannak olyan alkalmazások, ahol a státusz nem fontos (például egy közösségi oldal kliense, ahova az új híreket az alkalmazás következő indításakor újra le fogjuk tölteni). Azonban gondoljunk például egy képszerkesztő programra, ahonnan véletlen a vissza gombhoz érve kiléptünk. Amikor visszatérünk az alkalmazásba, szeretnénk az előző munkafolyamatot folytatni, így vigyáznunk kell arra, hogy az állapotot folyamatosan mentsük az adatvesztés elkerülése végett. Továbbá vigyázzunk, hogy nagy adatmennyiségeket ne töltsünk be és mentsünk ki egyszerre, ezt a feladatot végezzük el egy mögöttes szálon! Running: az alkalmazás egészen addig „futtatás alatt” állapotban fog maradni, amíg valamilyen felhasználói interakció hatására nem navigálunk valamerre, vagy éppen a felhasználó interakció hiányában a telefon nem tér aludni. OnNavigatedFrom esemény: akkor játszódik le, ha a felhasználó elnavigál az adott alkalmazásfelületről, vagy az alkalmazás deaktivált állapotba került. Itt el kell mentenünk az

116

Állapotok kezelése aktuális oldal állapotát, és ha a felhasználó visszatér ide, akkor helyre kell állítanunk. Érdemes még figyelni arra is, hogy ha visszafelé szeretnének navigálni az adott oldalról, akkor nem kell állapotot mentenünk, mivel a következő alkalommal, mikor ide visszatér a felhasználó, újra létrejön a felület. A megvalósítás módja természetesen nagyban függ az alkalmazás logikájától.  Deactivated esemény: ez az állapot akkor jelentkezik, ha a felhasználó átvált egy másik alkalmazásra, vagy megnyomja a Start gombot, illetve ha hosszú ideig nem volt felhasználói interakció, és a telefon zárolódik. Fontos megemlíteni, hogy ez az állapot következik be akkor is, ha valamilyen Chooser segítségével az alkalmazás az operációs rendszer beépített eszközeit szeretné használni, például a kamerát, kép kiválasztását, e-mail üzenet írását, és így tovább. Ennek az eseménynek a hatására mindenképpen el kell mentenünk az alkalmazás állapotát! Ennek módját a későbbiek során részletesen megnézzük. Dormant: miután a Deactivated állapot bekövetkezett, az alkalmazás folyamata és a hozzá tartozó szálak leállításra kerülnek, a rendszer még megpróbálja az alkalmazáshoz tartozó adatokat a memóriában tartani, hogy így azok később gyorsan visszanyerhetők legyenek. A folyamat teljesen automatikus, azonban legyünk vele óvatosak, mivel ha az alkalmazásunk után egy erőforrásigényesebb alkalmazást indít a felhasználó, akkor a mi alkalmazásunk valóban lezárásra kerül! Az esemény hatására le kell mentenünk az állapotát, az eddig elfoglalt memóriaterület pedig felszabadításra kerül. Tombstoned: a Windows Phone 7 rendelkezik egy Dictionary<T > típusú gyűjteménnyel, amelyen keresztül objektumokat menthetünk el. Ennek működését még részletezni fogjuk, azonban a mechanizmus ebben az állapotban nyeri el igazán az értelmét. Az alkalmazás leállításra kerül, az adatokat nem őrzi meg automatikusan a rendszer, de a fent említett gyűjteményt elmenti, így onnan vissza tudjuk majd az állapotot tölteni. Vigyázzunk vele, mert ha a telefont pl. újraindítják, akkor a gyűjtemény elveszik, így ebben az esetben más utat kell választanunk! Activated esemény: ha Domant vagy Tombstoned állapotból tér vissza az alkalmazásunk, akkor az Activated esemény fog lejátszódni. Itt tudjuk leellenőrizni, hogy hova volt az állapot elmentve, és ettől függően tudjuk visszaállítani. OnNavigatedTo esemény: akkor következik be, amikor a felhasználó egy új alkalmazásfelületre navigál, vagy amikor az adott lap az alkalmazás indulása után először kerül betöltésre. Itt szükséges leellenőrizni azt, hogy egy új példányra van-e szükségünk, vagy egy lementett állapotot szeretnénk helyreállítani! Closing esemény: az alkalmazás lezárása előtti utolsónak lezajló esemény. Nagyon fontos vigyázni arra, hogy itt maximum 10 másodpercig tartózkodhat az alkalmazás, ha ezt túllépi, a folyamatban lévő műveletek befejezése nélkül fog leállni. Itt tehát nem célszerű erőforrásigényes műveleteket használnunk!

Állapotok kezelése
Az előző részekben alaposan végignéztük, hogy mi minden történik a háttérben, amelyből mi semmit sem látunk. Megnéztük, milyen állapotok között ingázik egy alkalmazás az életciklusa során, és milyen teendőink vannak az egyes esetekben. Egy dolgot azonban még nem láttunk: Hogyan kell ezeket gyakorlatban megvalósítani?

Életciklus-események kezelése
Az 5-1. abrán láthattuk, mely eseményekkel kell foglalkoznunk, és az ábrát követő leírásban szerepelt szövegesen is, hogy az egyes eseményeknél mi a tennivalónk. Az áttekinthetőség kedvéért az alábbi táblázatban összefoglalom az eseményeket és a hozzájuk tartozó műveleteket:

117

5. Az alkalmazás életciklusa

Esemény Launching Activated Deactivated Closing OnNavigatedFrom OnNavigatedTo

Végrehajtandó művelet Minimális kód, semmi erőforrásigényes műveletet ne végezzünk! Állítsuk helyre az állapotot, ha lehet FAS (Fast Application Switching) segítségével! Mentsük el az állapotot! Ha lezáródott az alkalmazás, akkor biztosítsuk a perzisztens tárolást! Utólagos műveleteket végezzünk, vigyázzunk a 10 másodperces időhatárra! Ha nem visszafelé navigálunk, akkor mentsük el az adott felhasználó felülethez tartozó állapotot! Amennyiben nem egy új példányra van szükségünk, a tárból állítsuk helyre az alkalmazás állapotát!

Tanács: Egy Windows Phone alkalmazás ne tartalmazzon opciót a kilépésre, ezt a feladatot hagyjuk meg a telefon vissza gombjának! Próbáljuk ki mindezt a gyakorlatban! Indítsuk el a Visual Studio 2010-et, és hozzunk létre egy új projektet a File  New  Project parancs segítségével! A megjelenő dialóguson a C# nyelvű Silverlight for Windows Phone szekcióból válasszuk ki az egyszerű Windows Phone Application sablont, és az alkalmazásnak adjuk az AppLifecycle nevet (5-2 ábra)! A fejezet során végig ezt a projektet fogjuk használni.

5-2. ábra: A fejezethez szükséges projekt létrehozása Ha megnyitjuk az App.xaml.cs fájlt, akkor láthatjuk, hogy a fenti táblázatból négy különböző eseményvezérlő már előre el lett készítve. Pillanatnyilag még nem tudjuk őket semmilyen hasznos dologra felhasználni, azonban azért, hogy lássuk azok végrehajtási sorrendjét, helyezzünk el minden eseményvezérlőhöz egy töréspontot, ahogyan az 5-3. ábrán is látható! A megjelenő felületen válasszuk a

118

Állapotok kezelése Windows Phone 7.1 beállítást és hagyjuk jóvá! Ha ezzel megvagyunk, akkor hajtsuk végre a következő lépéseket, és figyeljük meg, hogy az egyes esetekben hol áll meg a kód végrehajtása!     Az F5 segítségével Debug üzemmódban futtassuk az alkalmazást! Ennek hatására elindul az emulátor. A kód végrehajtása megáll az Application_Launcing eseménykezelőnél. Ez a működés annak tudható be, hogy az alkalmazásnak ez volt az első elindítása. Ezután az emulátoron nyomjuk le a Start gombot! Ennek hatására úgy tűnik, mintha az alkalmazásunk kilépett volna. A Visual Studio most az Application_Deactivated eseménykezelőn elhelyezett töréspont hatására megáll. Az alkalmazás állapota megváltozott, és ha valamilyen logika már megvalósításra került volna, akkor itt kellene a állapotot mentenünk. Két eseményünkkel még nem találkoztunk, ezért F5 segítségével újra indítsuk el az alkalmazást! Az újra meg fog állni a Launching eseménynél. Léptessük tovább! Most az emulátoron nyomjuk le a Back (vissza) gombot, és figyeljük meg, hogy mi történik! Megállt a végrehajtás az Application_Closing eseményvezérlőnél. Ez azt jelenti, hogy innentől fogva 10 másodpercünk van az alkalmazás állapotának elmentésére, utána végérvényesen kilépünk!

  

Az Application_Activated eseményvezérlő egyszer sem került meghívásra. Ezt az okozta, hogy az alkalmazást egyszer sem futtattuk le az emulátoron található példány újrafuttatásával. Ezt hiába is próbáltuk volna meg, a Visual Studio hibakereső elengedi az alkalmazáspéldányunkat, miután megnyomtuk a Back vagy Start gombok valamelyikét.

5-3. ábra: töréspontok elhelyezése az App.xaml.cs fájlban Egyelőre nem sok minden történt, mindössze láttuk, hogy melyik esemény mikor játszódik le. A következő részben alkalmazásunkat úgy alakítjuk át, hogy az elmentse a legutóbbi állapotot és a következő indításkor visszaolvassa azt.

Az alkalmazás állapotának mentése és helyreállítása
Ha az alkalmazásunk adatorientált, és a felhasználó által tett módosításokat el kell tárolnia, akkor a memóriában található objektumokat perzisztens tárolóba kell elmentenünk. Erre többféle lehetőségünk van (sőt, van ahol egy lehetőségen belül is több irányba ágazik el az út). Először is válasszuk szét a műveletet az alapján, hogy az alkalmazás véglegesen leállt-e, vagy csak szüneteltetésre került valamilyen formában! Tudjuk, hogy a szüneteltetésnek két módja is van. Ha Dormant állapotba került a telefon, azaz

119

5. Az alkalmazás életciklusa minden hozzá tartozó adat a memóriában maradt, akkor rendkívül gyorsan folytatható a munkafolyamat, manuálisan semmit sem kell helyreállítanunk. Ekkor kizárólag azt kell megvizsgálnunk, hogy használható-e a Fast Application Switching mechanizmus. Ezt az Application_Activated eseményvezérlőn belül tesszük meg:
private void Application_Activated(object sender, ActivatedEventArgs e) { if ( e.IsApplicationInstancePreserved ) { // dormant állapotban voltunk, nem kell semmit sem tennünk manuálisan } else { // sajnos nem dormant volt, vissza kell hoznunk az adatokat } }

Ha nem Dormant állapotban volt az alkalmazásunk, akkor nekünk kell gondoskodnunk az adatok mentéséről. Erre egyik lehetőségünk a Tombstoning állapotban használható PhoneApplicationService, amely tartalmaz egy Dictionary<T> típusú generikus gyűjteményt, és az ebben eltárolt objektumokat a telefon automatikusan elmenti, amikor a Deactivated esemény lejátszódik. Ennek nagy előnye, hogy szintén gyorsan visszanyerhetjük az adatokat, hátránya viszont, hogy ez nem teljesen perzisztens megoldás. Ha a telefont újraindítjuk, vagy egy frissítés miatt az alkalmazásunk véglegesen leáll, akkor az adatai elvesznek. Erre jelenthet megoldást az adatok szerializálása az Isolated Storage-ba. Miután közvetlen fájlrendszer hozzáférésünk nincs, de mégis a telefon tárkapacitását szeretnénk használni adatok mentésére, így ő az egyik megoldás. Számos szerializációs módszert használhatunk (bináris, JSON, XML, DataContract, stb.), azonban ezek közül egyik sem tud sebességben versenyezni az előző megoldásokkal. Másik lehetőség lenne a Mangóban megjelent SQL CE adatbázismotor használata − ezt részletesebben az adatkezeléssel foglalkozó fejezet tárgyalja. Alakítsuk át az alkalmazásunkat úgy, hogy az kilistázza a telefon színtémáit, és ha a felhasználó kiválaszt egyet, akkor azt láthatóvá teszi! Sajnos, ténylegesen a telefon témáját nem tudjuk kódból változtatni (legalábbis nem legálisan), talán majd egy következő Windows Phone verzióban. Hozzunk létre egy új osztályt, amely a színek nevét és hexadecimális kódját tárolja! Ahhoz, hogy az osztályból létrehozott példányokat menteni tudjuk (Isolated Storage vagy a telefon beépített PhoneApplicationService megoldása segítségével), annak sorosíthatónak kell lennie, mégpedig a DataContractSerializer segítségével. Az ehhez szükséges objektumok Windows Phone esetében is implementálásra kerültek, semmi mást nem kell tennünk, mint felvenni a System.Runtime.Serialization assembly-t a könyvtár referenciák közé!
[DataContract] public class PhoneTheme { [DataMember] public string Name { get; set; } [DataMember] public string HexValue { get; set; } }

120

Állapotok kezelése Szükségünk lesz egy egyszerű felhasználói felületre is, amely mindösszesen egy listát fog tartalmazni a ListBox vezérlővel megvalósítva. Miután saját entitásokkal dolgozunk, a vezérlő alapesetben nem lenne alkalmas azok megjelenítésére, így egy sablon segítségével átalakítjuk. Ennek hatására a háttere a tárolt szín lesz, és minden listaelem közepén szövegesen is megjelenik majd az entitás neve:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox x:Name="accentList"> <ListBox.Resources> <DataTemplate x:Key="AccentItemTemplate"> <Grid Width="400" Height="100" Margin="28,0,0,20" Background="{Binding HexValue}"> <Border BorderBrush="White" BorderThickness="2"/> <TextBlock HorizontalAlignment="Center" Text="{Binding Name}" VerticalAlignment="Center" FontSize="24" /> </Grid> </DataTemplate> </ListBox.Resources> <ListBox.ItemTemplate> <StaticResource ResourceKey="AccentItemTemplate"/> </ListBox.ItemTemplate> </ListBox> </Grid>

Most már van olyan entitás osztályunk, amely képes az elemeket tárolni, és van hozzá egy felhasználói felületünk, amely megjeleníti azokat. Hozzuk létre a tényleges listánkat is! Egyszerű esettel van dolgunk, elegendő lesz egy List<T> generikus listapéldány, amelyet helyben inicializálunk is az új elemek megadásával. Nyissuk meg a MainPage.xaml.cs fájlt, és hozzuk létre a következő adattagot:
private { new new new new new new new new new new }; List<PhoneTheme> themes = new List<PhoneTheme> PhoneTheme PhoneTheme PhoneTheme PhoneTheme PhoneTheme PhoneTheme PhoneTheme PhoneTheme PhoneTheme PhoneTheme { { { { { { { { { { Name Name Name Name Name Name Name Name Name Name = = = = = = = = = = "Blue", HexValue = "#FF1BA1E2" }, "Brown", HexValue = "#FFA05000" }, "Green", HexValue = "#FF339933" }, "Lime", HexValue = "#FFA2C139" }, "Magenta", HexValue = "#FFD80073" }, "Mango", HexValue = "#FFF09609" }, "Pink", HexValue = "#FFE671B8" }, "Purple", HexValue = "#FFA200FF" }, "Red", HexValue = "#FFE51400" }, "Teal", HexValue = "#FF00ABA9" },

Mielőtt elsiklanánk felette, szükségünk lesz egy metódusra, amely a szövegesen megadott színkódokat úgy alakítja át, hogy a Silverlight azt megjeleníthesse. De mit is tud a Silverlight megjeleníteni? Hiszen XAML kódban is névvel vagy hexadecimális kóddal adjuk meg a színeket, itt miért nem jó ez? A XAML-ben megadott kódot az objektum képes interpretálni, és a szükséges változtatásokat elvégezni automatikusan, azonban erre nincs lehetőségünk mögöttes kódból. Itt a Brush alaposztály valamelyik leszármazottját kell segítségül hívnunk, amely a mi esetünkben a SolidColorBrush lesz, ez egyszínű kitöltést tesz lehetővé. Ennek az objektumnak a konstruktora egy Color típusú objektumpéldányt vár, így a szövegesen megadott színkódunkat ilyen típusra kell átalakítanunk. Ennek az elvégzése rendkívül egyszerű:
private SolidColorBrush GetColorFromHex( string color ) { return new SolidColorBrush( Color.FromArgb( Convert.ToByte( color.Substring( 1, 2 ), 16 ), Convert.ToByte( color.Substring( 3, 2 ), 16 ),

121

5. Az alkalmazás életciklusa

Convert.ToByte( color.Substring( 5, 2 ), 16 ), Convert.ToByte( color.Substring( 7, 2 ), 16 ) ) ); }

Kattintsunk tervezői nézetben kettőt a telefon felületén, és a Visual Studio létrehozza a Loaded eseménykezelőt. Ebben első dolgunk az, hogy az előbb létrehozott listát átadjuk a felületen elhelyezett ListBox vezérlőnek. Ezt könnyedén megtehetjük, mivel a ListBox ItemsSource tulajdonságának a feltöltése után a Silverlight adatkötő motor automatikusan kivezeti a listaelemeket a felületre, ahol a vezérlő a nemrég létrehozott sablon segítségével meg is jeleníti azokat. Itt viszont lesz még egy feladatunk! Ha el volt mentve az állapot, akkor azt itt helyre kell állítanunk! Először nézzük ezt meg a telefon beépített eszközével megvalósítva, amelyet a PhoneApplicationService osztályon keresztül érhetünk el! Ennek az osztálynak van egy State nevezetű gyűjteménye, amelyen megvizsgáljuk, hogy tartalmazza-e a „Theme” nevű kulcsot. Ha igen, akkor nem először használjuk az alkalmazást, és korábban mentettünk már állapotot. Nincs is más dolgunk, mint kiolvasni a kulcshoz tartozó értéket és a felületen átállítani az adott színre a hátteret:
void MainPage_Loaded(object sender, RoutedEventArgs e) { accentList.ItemsSource = themes; if ( PhoneApplicationService.Current.State.ContainsKey( "Theme" ) ) LayoutRoot.Background = GetColorFromHex( ((PhoneTheme)PhoneApplicationService.Current.State[ "Theme" ]).HexValue ); }

Valahol az előbb betöltött objektumot el is kellett mentenünk, erre a legmegfelelőbb hely a listában kiválasztott elem változtatását jelző esemény. Ha a tervezői nézetben duplán kattintunk a ListBox vezérlőre, akkor a Visual Studio létrehozza a SelectionChanged eseménykezelőt, ezen belül dolgozunk tovább. Le kell kérdeznünk az aktuálisan kiválasztott elemet. Mivel az adatkötő motor felhasználásával a tényleges objektumpéldányokat adtuk át a ListBox-nak, így lekérdezhetjük magát az elemet, de ugyanúgy megfelelne az index is, mivel a forráslistát az osztály továbbra is tárolja:
private void accentList_SelectionChanged(object sender, SelectionChangedEventArgs e) { PhoneTheme theme = accentList.SelectedItem as PhoneTheme; LayoutRoot.Background = GetColorFromHex( theme.HexValue ); PhoneApplicationService.Current.State[ "Theme" ] = theme; }

Mielőtt futtatnánk az alkalmazást, tennünk kell a beállítások között is egy változtatást. A Mangóban a multitasking bevezetésével az emulátor is megváltozott. Ez alapértelmezésben nem engedélyezi a Tombstoning állapot tesztelését. Ahhoz, hogy ezt engedélyezzük, jobb egérgombbal kattintsunk a projekt nevére, és válasszuk a Properties opciót! Ezen belül válasszuk a Debug fület, és az egyetlen itt található „Tombstone upon deactivation while debugging” opciót jelöljük be! Ezek után futtathatjuk az alkalmazást.

122

Állapotok kezelése

5-4. ábra: Alvó állapot engedélyezése Visual Studióban A tesztelést a következő lépésekben végezzük el:       Indítsuk el Debug módban az emulátort és benne az alkalmazást! Válasszunk ki egy színt a listából, majd a Start gomb segítségével lépjünk ki! Itt be tudjuk tölteni az Internet Explorert vagy egy másik, az emulátorra telepített alkalmazást. Lépjünk ki a vissza gombbal, és térjünk vissza a saját alkalmazásunkhoz! Az állapota megfelelően helyre lesz állítva. (Ha nem a Resuming állapot következik be, akkor zárjuk be az emulátort, és fordítsuk újra a projektet, majd futtassuk újra!

5-5. ábra: Az alkalmazás futásának pillanatfelvételei A fenti módszer nem menti el az adatokat végérvényesen. Ha valóban perzisztálni szeretnénk azokat, akkor az Isolated Storage-ba kell mentenünk. Mivel általánosítható megoldást szeretnék mutatni és nem csak az alkalmazásra specifikusat, így az adatsorosítást választottam. Az entitásosztályt fel kell készíteni DataContractSerializerrel való együttműködésre, most ezt ki is próbáljuk. Szükségünk van egy alkalmazásszintű statikus példányra a PhoneTheme osztályból, a memóriában ide fogjuk menteni a felületen végzett változtatásokat, és ide fogjuk majd visszatölteni azokat. Ezenkívül két metódusra is szükségünk van még, az egyik feladata az adatok mentése, a másiké pedig azok visszatöltése.

123

5. Az alkalmazás életciklusa

public static PhoneTheme Theme { get; set; } private void SaveData() { using ( IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication() ) { using ( IsolatedStorageFileStream stream = file.CreateFile( "theme.xml" ) ) { // új DataContractSerializer példány, a megfelelő típussal ellátva DataContractSerializer serializer = new DataContractSerializer( Theme.GetType() ); // az objektum sorosítása a megnyitott adatfolyamra serializer.WriteObject( stream, Theme ); } } } private void LoadData() { using ( IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication() ) { // vizsgáljuk meg létezik-e már a fájl if ( !file.FileExists( "theme.xml" ) ) Theme = new PhoneTheme { Name = "Blue", HexValue = "#FF1BA1E2" }; else using ( IsolatedStorageFileStream stream = file.OpenFile( "theme.xml", FileMode.Open, FileAccess.Read ) ) { // létezett a fájl, így megfelelő típussal visszaolvassuk az adatokat. DataContractSerializer serializer = new DataContractSerializer( typeof( PhoneTheme ) ); Theme = (PhoneTheme)serializer.ReadObject( stream ); } } }

A beolvasás esetére megvizsgáltuk, hogy létezik-e már a fájl, így a LoadData() metódus is nyugodtan használható. Nincs is más dolgunk, mint az alkalmazás indításakor és leállításakor meghívni az oda tartozó metódusokat (nem szükséges megkülönböztetni, hogy milyen típusú indításról és leállításról van szó).
private void Application_Launching(object sender, LaunchingEventArgs e) { LoadData(); } private void Application_Activated(object sender, ActivatedEventArgs e) { if ( e.IsApplicationInstancePreserved ) { } else { LoadData(); } } private void Application_Deactivated(object sender, DeactivatedEventArgs e) { SaveData(); }

124

Folyamatok a háttérben

private void Application_Closing(object sender, ClosingEventArgs e) { SaveData(); }

A felhasználó felület mögöttes kódja az alábbiak szerint módosul, felhasználva az alkalmazásszinten elhelyezett statikus objektumpéldányt:
void MainPage_Loaded(object sender, RoutedEventArgs e) { accentList.ItemsSource = themes; LayoutRoot.Background = GetColorFromHex( App.Theme.HexValue ); } private void accentList_SelectionChanged(object sender, SelectionChangedEventArgs e) { PhoneTheme theme = accentList.SelectedItem as PhoneTheme; LayoutRoot.Background = GetColorFromHex( theme.HexValue ); App.Theme = theme; }

Folyamatok a háttérben
A fejezet elején említettem, hogy a Windows Phone 7 nem engedte az alkalmazásoknak, hogy amikor nem ők voltak előtérben, a háttérben műveleteket végezzenek. Részletesen leírtam, hogyan működik a multitasking, és ennek hiányában miért nem tehette az operációs rendszer ezeket a funkciókat elérhetővé.

Elméleti áttekintés
Alapesetben egy alkalmazásra úgy tekintünk, hogy annak az előtérben kell futnia. Azonban vannak olyan esetek, amikor szeretnénk, hogy olyankor is történjen valami, amikor a felhasználó éppen más alkalmazást futtat, vagy egyáltalán nem is használja a telefonját. Tipikus eseteket is felsorolhatunk:  Van egy zenelejátszó alkalmazásunk. A felhasználó valószínűleg nem fogja folyamatosan a kezében a telefonját, és nem használja aktívan, lehet, hogy közben egy könyvet olvas, vagy éppen a munkáját végzi. Ilyenkor a telefon alvó állapotba helyezné a lejátszónkat, és a zene lejátszása megszakadna. Szeretnénk, ha a zene lejátszása folytatódna a háttérben. Főzéshez készítünk egy időmérő alkalmazást, amelynek az a feladata, hogy bizonyos idő letelte után riasszon bennünket, így biztosan nem felejtjük ott tovább az ételt, és az nem fog odaégni. Főzés közben biztosan nem használjuk a telefonunkat, így ebben az esetben is kellemetlen lenne, ha alvó állapotba kerülne az alkalmazás. Megjegyzésként megemlíteném, akár azt is megoldhatjuk, hogy a telefon ne tudjon aludni, amíg manuálisan ki nem lépünk az alkalmazásból. Ezzel azonban az akkumulátort nagyon hamar lemeríthetjük, így használata nem javasolt. Időjárás-figyelő alkalmazást készítünk, amelynek extra funkciója, hogy vihar közeledése esetén időben riaszt bennünket. A funkció riasztáshoz kapcsolódó részére pontosan azok az elvek érvényesek, amit az előző listapontban említettem, viszont itt még valamivel számolnunk kell. Az időjárás-adatokat nem elegendő akkor lekérnünk egy webes szolgáltatástól, amikor a felhasználó az alkalmazásunkat használja, mert így nem biztos, hogy mindig a legfrissebb információkkal fogunk rendelkezni! Szinkronizálnunk kell a háttérben, ez pedig időről időre adatok letöltését jelenti – a felhasználó beavatkozása nélkül is.

A fenti példákat szándékosan választottam, még találkozni fogunk velük az alfejezetek során, ahol részletesen bemutatom ezeket az eseteket.

125

és akkor is csak rövid ideig.xaml-nek! A felületet az alábbi kódok szerint alakítsuk ki. amilyennel csak szeretnénk.0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <Grid x:Name="ContentPanel" Grid. és így olyan forrásadattal dolgozhatunk. egy előre. és nevezzük el a fájlt AudioPlayerPage. Álljon itt egy példa ennek az állománynak a szerkezetére: <ExtendedTask Name="BackgroundTask"> <BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="LocationTaskAgent" Source="LocationTaskAgent" Type="LocationTaskAgent. és ez csak gyűjtőnév. vagy a telefon zárolást feloldó képernyőjén található zenelejátszás kezelőfelületet is.0. amely az a WPAppManifest.12. az adott audió bekerül a Zune Media Queue-ba. Ha túl alacsony a telefon akkumulátorának a töltöttségi szintje. Az AudioPlayerAgent egy listát vár zenéinkből. hanem rögtön kettőt is kapunk. Természetesen akkor is kikapcsolásra fognak kerülni. melyek közül kettőt rögtön érdemes megemlíteni:   PeriodicTask: periodikusan (például minden 30.xml fájlon keresztül kapcsolódik az alkalmazáshoz. akkor a háttérben élő folyamatok futtatási joga megvonható az alkalmazástól. Előre pontosan meghatározott feladatkör szerint dolgozhat alkalmazásunk a háttérben. hogy a telefon számára fogyasztható audio formátumokkal kódolt zenei állományokra hivatkozzunk. Amikor alkalmazásunk zenét játszik le.-7. és valamilyen gyorsan végrehajtható feladatot lát el.ScheduledAgent" /> </ExtendedTask> Zenelejátszás integrálása saját alkalmazásokba Az összes népszerű mobil operációs rendszerre számos zene.dll állományban) helyezkedik el az ágens feladatát leíró kód. legfeljebb 10 percig futhat.és egy hátratekerés gombot tartalmaz: <StackPanel x:Name="TitlePanel" Grid. Sajnálatosan Windows Phone-ra eddig egyáltalán nem volt lehetőségünk saját lejátszók készítésére. Az AudioStreamingAgent esetében mi írhatjuk meg azt a komponenst.17. A Mango megjelenésével nemcsak egy ilyen ágenst. A zene lejátszásáért felelős ágens mélyen az operációs rendszerben található Zune komponensbe van integrálva. de még a beépített Zune lejátszóval sem tudtuk integrálni alkalmazásainkat.28"> <TextBlock x:Name="ApplicationTitle" Text="BACKGROUND AUDIO PLAYER" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="play a song" Margin="9. Az alkalmazás életciklusa A Windows Phone Mango egy energiatakarékos módját választotta a háttérműveletek kezelésének. mint bármelyik zenénk a médiagyűjteményben. Ezeket az ágenseket Task típusok gyűjtik magukba. így használhatjuk a hangerővezérlés hardveres gombjait. adatok tömörítése/kitömörítése).Row="0" Margin="12.0. ResourceIntensiveTask: nagyobb számítási feladatok ellátására szolgál (pl.0"> 126 . a valós feladatok során ezek több speciális változatát vehetjük használatba. amikor külön projektben (és ezért külön .5. amikor az alkalmazásunk előtérben fut. melyek helyben tároltak vagy akár egy távoli címen elérhetőek is lehetnek. az csak egy lejátszás. így hasznos. percben) meghívódik.Row="1" Margin="12. így ugyanabban a bánásmódban részesül. A Windows Phone Mango megjelenésével szerencsére ez gyökeresen megváltozott! A multitasking bevezetésével a Microsoft létrehozta a háttérben futó folyamatokat.0. Az ágensek létrehozása során többször találkozunk olyan esettel. amely a zenei információt képes dekódolni. A következő mintaalkalmazásban az AudioPlayerAgent-et használjuk fel.és videólejátszó szoftver létezik. Itt vigyáznunk kell arra. Ezeknek a folyamatoknak a neve Background Agents. ha most az elején elő is készítünk néhány MP3 zeneszámot a kedvenceink közül! Adjunk hozzá meglévő alkalmazásunkhoz egy új lapot! A projekt gyorsmenüjéből válasszuk ki az Add  New Item  Windows Phone Portrait Page parancsot. így „aktív” állapotban más módot kell találnunk az egyébként háttérben futó feladatok ellátására. vagy ha a felhasználó akarja.

40. 5-6. így Zune-on keresztül a telefonra másolt zenéket ne is próbáljuk meg elérni! Az App.cs fájlban helyezzük el az alábbi metódust. ehhez hasonló eredményt kell kapnunk. és ne felejtsük azt az App osztály konstruktorából meghívni! Természetesen a zeneszámokat tartalmazó fájlok listáját mindenkinek a saját fájljaira kell szabnia.18. amiket szeretnénk majd lejátszani! Jelöljük ki a zenefájlokat. hogy az AudioPlayerAgent csak Isolated Storage-ban és távoli elérési úton elhelyezett audio fájlokat tud lejátszani.193. a Zune gyűjteményünkhöz nincs hozzáférése. jobb kattintással rajtuk a Properties parancsot választva állítsuk be a Copy To Output Directory tulajdonságot a Copy if newer opcióra! Az én projekt struktúrám az 5-6.0. ábra: A projekt struktúrája Következő tennivalónk a zenefájlok átmásolása az Isolated Storage-ba.Folyamatok a háttérben <StackPanel Orientation="Horizontal" Width="420" Margin="18. Fontos megemlíteni. 127 .0" VerticalAlignment="Top"> <Button Content="prev" x:Name="prevButton" Height="140" Width="140" Click="prevButton_Click"/> <Button Content="play" x:Name="playButton" Height="140" Width="140" Click="playButton_Click"/> <Button Content="next" x:Name="nextButton" Height="140" Width="140" Click="nextButton_Click"/> </StackPanel> <TextBlock x:Name="txtCurrentTrack" Height="75" HorizontalAlignment="Left" Margin="12.xaml. ábrán látható.0" VerticalAlignment="Top" Width="438" TextWrapping="Wrap" /> </Grid> Hozzunk létre egy új mappát és másoljuk bele az MP3 fájlokat.

0. "1-03 Dark Side.mp3".FileExists(_filePath)) { StreamResourceInfo resource = Application. az ezekhez tartozó funkcionalitást meg kell írnunk! A BackgroundAudioPlayer egy singleton osztály. } } } } } } Van már tehát lejátszható zeneszámunk. hogy a zeneszámok között váltogassunk. azonban még nem működik az alkalmazásunk. akkor már a megfelelő felületet fogjuk látni. 128 .Read(bytes.5. byteCount). Az alkalmazás életciklusa using System.Resources. esetleg lekérdezzük a zenelejátszó státuszát. hogy az alkalmazás újbóli előtérbe kerülése esetén a gombok megfelelő állapotban jelenjenek meg a felületen. megállítsuk vagy elindítsuk az aktuális zeneszámot. using System. UriKind. ha futtatjuk emulátorban a projektet. 0. byte[] bytes = new byte[chunkSize]. ha futtatjuk.mp3" }. akkor nem a megfelelő felület jelenik meg.GetResourceStream( new Uri(_filePath. int byteCount. private void CopyToIsolatedStorage() { using (IsolatedStorageFile storage = IsolatedStorageFile. ennek függvényében változtatjuk a lejátszás/szüneteltetés gomb tartalmát. így azt példányosítás nélkül a megfelelő névtér feloldása után használhatjuk is.Stream. chunkSize)) > 0) { file. hogy melyik lap (Page objektum) legyen az alkalmazás indításakor az alapértelmezett. így vigyáznunk kell arra is. Még felhasználói felület is van hozzá. A következőkben a feladatunk az. Ehhez be kell állítani. Mivel a zene lejátszása az alkalmazásból való kilépéskor is folytatódik. több dolog is hiányzik ehhez! Először is.Write(bytes.Relative)).Windows. hogy a projekten belül található Properties mappában az ott lévő WPAppManifest.xaml"/> Ezek után.GetUserStoreForApplication()) { string[] files = new string[] { "1-01 Mr. Know It All. foreach (var _fileName in files) { string _filePath = "Audio/" + _fileName. hogy ezeket a műveleteket fel is használjuk. while ((byteCount = resource. if (!storage.IO.IsolatedStorage. Ennek az osztálynak a műveleteit tudjuk arra felhasználni.mp3". illetve az aktuális zeneszámról megjelenített információt.CreateFile(_fileName)) { int chunkSize = 4096. using (IsolatedStorageFileStream file = storage.xml fájlban átírjuk a szükséges hivatkozást a következőre: <Tasks> <DefaultTask </Tasks> Name ="_default" NavigationPage="MusicPlayerPage. Figyelnünk kell a zenelejátszás státuszára is. Ezt úgy tudjuk megtenni. Azonban még mindig nem működik! Van három gombunk. "1-02 What Doesn't Kill You (Stronger).

RoutedEventArgs e) { BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged). void Instance_PlayStateChanged(object sender.Content = "play". txtCurrentTrack. } else { BackgroundAudioPlayer.PlayerState) { BackgroundAudioPlayer.PlayerState) { playButton. RoutedEventArgs e) { if (PlayState.Instance.SkipPrevious().Instance.SkipNext().Track) { txtCurrentTrack.Playing == BackgroundAudioPlayer.Artist. break. break. case PlayState.Paused: case PlayState. } } 129 .Text = BackgroundAudioPlayer. } } private void nextButton_Click(object sender. EventArgs e) { switch (BackgroundAudioPlayer.Instance.Content = "pause".Content = "play".Instance. RoutedEventArgs e) { BackgroundAudioPlayer. } if (null != BackgroundAudioPlayer.Track.Pause().Instance. using Microsoft. private void prevButton_Click(object sender.Navigation. } private void playButton_Click(object sender.Phone.Folyamatok a háttérben using System. } // ezt a konstruktorban helyezzük el! BackgroundAudioPlayer.Instance.Text = "".Play().Title + " by " + BackgroundAudioPlayer.Artist.Instance.Playing: playButton.Instance.Instance.Instance.Stopped: playButton.Content = "pause". } else { playButton.PlayerState) { case PlayState. } } protected override void OnNavigatedTo(NavigationEventArgs e) { if (PlayState.Track.Track.Instance. txtCurrentTrack.Playing == BackgroundAudioPlayer.Windows.Track.Title + " by " + BackgroundAudioPlayer.Text = BackgroundAudioPlayer.Instance.BackgroundAudio.

lemez címe. "Episode 29".mp3".Absolute).com/wpradio/WPRadio_29. UriKind. Ha visszafelé lépkedünk a zeneszámok között. illetve váltani listában a felhasználó igénye szerint: static int currentTrackNumber = 0. "Stronger". mint a szükséges helyeken meghívni a lejátszásért felelős függvényt. Mielőtt továbbhaladnánk.5.Count . Az AudioTrack konstruktora egymás után a következő paramétereket fogadja: zenefájl. amelyben dolgozni fogunk. private void PlayNextTrack(BackgroundAudioPlayer player) { if (++currentTrackNumber >= _playList. "Stronger". new AudioTrack(new Uri("http://traffic. 0 után a lista utolsó elemére ugrunk. "Dark Side". "Kelly Clarkson".1. "Stronger". akkor túl vagyunk az utolsó zeneszámon. "Mr. amely azt tárolja. hiszen egy nagyon fontos komponens még hiányzik! Ez nem más. "Stronger".Relative). hogy a zenék lejátszása még mindig nem működik. "Windows Phone Radio". null). "Windows Phone Radio Podcast". UriKind. amely a zenefájlokra hivatkozik.libsyn. Pótoljuk a hiányosságot. UriKind. adjuk hozzá az új projekt referenciáját a Windows Phone projektünkhöz! Szükségünk lesz egy listára. lemez képe. mint maga a zenét lejátszó ágens. Ezek után nincs semmi más dolgunk. null). Ez nem is csoda. 130 . null) }.Relative). azt tapasztaljuk.mp3". new AudioTrack(new Uri("1-02 What Doesn't Kill You (Stronger). dal címe. ebben a listában AudioTrack típusú objektumpéldányokat sorolunk fel. és a Solution Explorerben adjuk hozzá egy új projektet jelenlegi megoldásunkhoz! Válasszuk ki a projekt gyorsmenüjéből az Add  New Project parancsot. private static List<AudioTrack> _playList = new List<AudioTrack> { new AudioTrack(new Uri("1-01 Mr. Know It All". Szükségünk lesz még egy számlálóra is.mp3". Az alkalmazás életciklusa Ha fordítjuk és futtatjuk a projektet. majd projekt típusaként a Windows Phone Audio Playback Agent-et válasszuk! Adjuk neki az AudioPlayer nevet! A Visual Studio létrehozza a projektet és abban egy AudioPlayer. Know It All. és a nulladik sorszámúra kell ugranunk.Relative).mp3". "Kelly Clarkson". null). new AudioTrack(new Uri("1-03 Dark Side.cs fájlt. hogy éppen melyik zeneszámot játsszuk le! Ha annak értéke egyenlő a lista méretével. } PlayTrack(player). "Kelly Clarkson". } private void PlayPreviousTrack(BackgroundAudioPlayer player) { if (--currentTrackNumber < 0) { currentTrackNumber = _playList. UriKind.Count) { currentTrackNumber = 0. előadó. akkor pedig a logikát megfordítva.

TrackReady: player. 131 . } Teszteljük alkalmazásunkat emulátorban. break.SkipPrevious: PlayPreviousTrack(player). } NotifyComplete(). hogyha rendelkezésünkre áll! Az 5-7. object param) { switch (action) { case UserAction. break. case PlayState. ábra az alkalmazást mutatja be futás közben. } protected override void OnPlayStateChanged(BackgroundAudioPlayer player. case UserAction. vagy akár éles eszközön. } NotifyComplete(). } protected override void OnUserAction(BackgroundAudioPlayer player.Track = _playList[currentTrackNumber].Pause: player.Play: PlayTrack(player).Play(). AudioTrack track. } private void PlayTrack(BackgroundAudioPlayer player) { player.Pause(). break. break. UserAction action. case UserAction. break. AudioTrack track.Folyamatok a háttérben } PlayTrack(player). case UserAction. PlayState playState) { switch (playState) { case PlayState. break.SkipNext: PlayNextTrack(player).TrackEnded: PlayNextTrack(player).

illetve ha a felhasználó változtatást végzett a háttérben. akkor ki tudjuk azt keresni és törölni tudjuk a sorból.Ceiling( beginTime. amely főzés közben segít nekem.AddMinutes(Math.Now. ScheduledActionService.AddMinutes(Math. és meg kell adni a riasztás időpontját. azonban ekkor figyeljünk arra. } A fenti példában látható. melyek egymástól független mérik az idő előrehaladását.Now. figyelmeztetnek bennünket. A neve Cook Timer és megtalálható a Windows Phone Marketben. hogy az adott MP3 az alkalmazás mellé legyen 132 . alarm. alarm. melyen keresztül egy új emlékeztetőt be tudunk ütemezni. UriKind. Példáként egy saját alkalmazásomat mutatom be.ExpirationTime = DateTime.Relative ).Content = "Time is up!\n" + Name + " is/are done now!".AddSeconds( 10 ). ábra: Az Audio Player alkalmazás futás közben Figyelmeztetések és riasztások kezelése A Windows Phone Mango lehetővé teszi. Az alkalmazás életciklusa 5-7. alarm.Sound = new Uri( "Sounds/House Fire Alarm.Add( alarm ). Új időzítés hozzáadásra a következő kódrészlet mutat példát: private void MakeAlarm() { alarm = new Alarm( Name ).Ceiling(beginTime. hogy saját riasztásokat és emlékeztetőket készítsünk.BeginTime = DateTime. illetve azt. alarm. alarm. a figyelmeztetések akkor is működni fognak! Ezeket a ScheduledActionService objektum felügyeli. hogy a riasztásnak egy nevet kell adnunk. hogy újra emlékeztessen-e. Három különböző időzítőt tudunk beállítani.Value )). az nyugodtan deaktivált állapotba kerülhet.Value )) . definiálni kell a megjelenítendő tartalmát.5. Saját hangokat is rendelhetünk hozzá.mp3".None. Természetesen ehhez nem kell folyamatosan használnunk az alkalmazást.RecurrenceType = RecurrenceInterval. esetleg le szeretné állítani a riasztást. és amikor elkészült az adott étel.

IsScheduled == false ) ScheduledActionService. ne Zune média könyvtárból akarjuk elérni. ábra az alkalmazást mutatja be működés közben. Sajnos az FTP protokoll használata jelenleg nem támogatott. stb) Fájl letöltése WIFI hálózaton (akkumulátorról) Maximális méret 5 MB 20 MB 100 MB 133 . esetleg nagyobb állományok letöltése vált szükségessé. 5-8. hogy az alkalmazásunk időről időre adatokat szeretne szinkronizálni valamilyen szerver oldali komponenssel.Title ).Folyamatok a háttérben csomagolva. Mielőtt részletesen megnéznénk.Name ). if ( reminder != null && reminder.Find( item. ábra: a Cook Timer alkalmazás működés közben Adatok letöltése a háttérben Elképzelhető. mert ahhoz itt sincs hozzáférésünk! Ha időközben szeretnénk leállítani a riasztást és törölni a sorból. } Az 5-8.Remove( reminder. amelyekkel számolnunk kell! Méretkorlátok: Adatforgalmazás típusa Fájl feltöltése Fájl letöltése mobil csatornán (3G. HSDPA. nézzük meg azokat a korlátozásokat. melyek HTTP és HTTPS protokollokon képesek adatokat forgalmazni. hogyan is történik letöltés. akkor arra a következő kódrészlet mutat példát: void CleanupOldReminder( AlarmItem item ) { var reminder = ScheduledActionService. A Windows Phone Mango bevezette a Background File Transfer objektumokat.

A BackgroundTransferRequest objektumnak meg kell adnunk. Ha a beállításokkal végeztünk. //megadjuk.RelativeOrAbsolute ). request. Uri downloadUri = new Uri( "shared/transfers/" + downloadFile. és a HTTP protokoll melyik igéjét szeretnénk hozzá használni. hogy honnan kell a letöltést végeznie. akkor a kivételkezelést figyelembe véve megkezdhetjük a letöltést a BackgroundTransferService objektum segítségével. esetleg várjunk töltő csatlakoztatására. Két objektumtípus segít bennünket ezeknek a feladatoknak a megvalósításában.RelativeOrAbsolute ).0 fejlesztőknek című könyv PDF változatát tölti le a háttérben: // Silverlight 4. UriKind. A következő kódrészlet a Silverlight 4. } catch(Exception ex) { // ha valami probléma volt } 134 . hogy a letöltések szüneteltetésre kerülnek. try { // a háttérben beütemezzük a letöltést BackgroundTransferService. ahova ezeket a Windows Phone bemásolhatja. akkor ez előfordulhat). request. ez egy olyan sorként képzelhető el. UriKind.0 fejlesztőknek könyv pdf-ben string transferFileName = "http://goo.5. Az egyik a BackgroundTransferRequest. ha 3G hálózat esetében 50 Kbps és WIFI esetében 100 Kbps alá csökken a hálózat áteresztő képessége. request. hanem mondjuk GPRS vagy EDGE módban működünk.Method = "GET". hogy hova töltse le a fájlt string downloadFile = transferFileName. hanghívás megzavarhatja-e a letöltést (ha nem 3G hálózaton vagyunk. Miután fájlrendszerbe fognak letöltődni a fájlok.AllowCellularAndBattery. hogy milyen beállítások mellett szeretnénk az adatforgalmazást engedélyezni. Az alkalmazás életciklusa Egyéb korlátozások: Korlátozás típusa Az adatforgalmazó sorban lévő elemek száma Maximális érték 5 (a teljesített letöltéseket manuálisan kell törölnünk kódból) Egyidejű adatforgalmazás adott telefonról (több 2 alkalmazás által) Maximálisan beütemezhető (várakozási sorba kerülnek) HTTP fejlécek száma kérésenként HTTP fejlécek maximális mérete letöltések 500 15 16 KB külön-külön Fontos azt is tudni.DownloadLocation = downloadUri. BackgroundTransferRequest request = new BackgroundTransferRequest( transferUri ). Ilyen beállítás például az.EscapeUriString( transferFileName ). Uri transferUri = new Uri( Uri.gl/9dkcY".Add(request).Substring(transferFileName. hogy csak a celluláris hálózaton. amely egyesével végrehajtja az átadott letöltés-kéréseket.TransferPreferences = TransferPreferences. esetleg Wifin keresztül kívánjuk ezt lehetővé tenni.LastIndexOf( "/" ) + 1 ). így egy olyan helyi elérési útra is szükségünk lesz. és így tovább. A másik a BackroundTransferService. amely leírja magát a kérést egyetlen távoli állományra mutatva. Azt is megadhatjuk.

amelyre eddig csak nagyon nehézkesen vagy esetleg egyáltalán nem találhattunk megoldást. minden feladatnak speciálisan a hozzá illeszkedő feladat kategóriába kell kerülnie. ahol a megfelelő objektumok végrehajtják az általunk megvalósított feladatok logikáját. hogy semmilyen esetben se veszhessenek el a felhasználó munkafolyamataihoz tartozó adatok. 135 . hogy nem végezhetünk akármit szabadon a háttérben. Láthattuk. hogy az első Windows Phone 7 verzióhoz képest – amely alig egy évvel ezelőtt jelent meg – mennyit fejlődött az operációs rendszer Mango kódnevű legújabb kiadása.Összefoglalás Összefoglalás A fejezetben láthattuk. Az elméleti bevezetést követően gyakorlatban is láthattuk azokat a lépéseket. és arról gondoskodnak. Az új multitasking környezet számos új dolgot tesz lehetővé a fejlesztőknek. melyek az alkalmazást segítik beilleszkedni a Windows Phone életciklus modelljébe.

.

Tasks névtérben találhatóak. vagyis a többi programtól elzárt „homokozóban” fut. a lényeg csupán a feladat elvégzése. amelyek ugyan szintén sandboxban futnak. Ez a saját tér tartalmazza az alkalmazás izolált tárhelyét (Isolated Storage) és a program kontextusát. fényképek készítése. deaktiválódik. valamint a teljes háttértárra vonatkozó fájlrendszer fogalma sem értelmezhető az alkalmazások szemszögéből. Más szavakkal: kontextusváltás történik. Ennek következménye az. a CLR réteg alatt futó biztonsági mechanizmusokkal rendelkezik. az érintett állapotokat és az ezek közti eseményeket a 6-1 ábra mutatja. 137 . ha nem kapnánk vissza az elkészült képet. Egy taszk indításakor alkalmazásunk a háttérbe kerül. Az alkalmazások tehát egymás elől rejtve futnak és léteznek. de ennek köszönhető az is. bevezették az úgynevezett taszkok (Task) rendszerét. Ezzel szemben egy fénykép készítése során értelmetlen lenne. Ezeket a funkciókat a platform részeként szállított alkalmazások valósítják meg. Alapvető telefonos funkciók használata A Windows Phone 7 platform megalkotása során az egyik legfontosabb szempont a biztonság. hogy ahhoz külső alkalmazások ne tudjanak hozzáférni. tehát ezt a funkciót egy Chooser valósítja meg. de ide tartozik a médiatár és a kapcsolattár elérése is. amelyekre számos programnak szüksége lehet. 6-1 ábra: Események és állapotváltozások taszk indításakor A taszkok két fő csoportra bonthatók: a valamilyen adatot visszatérési értékként szolgáltató Chooserekre és az egyszerű programindítást elvégző Launcherekre. a rendszer sebezhetetlensége volt. A folyamat lefutását. fejezet taglalja. hogy az összes alkalmazás úgynevezett sandbox-ban. de bármely alkalmazás által elérhetőek az SDK-n keresztül. A taszkok a Microsoft. Egy telefonhívás indítása például egy Launcher. oly módon. e-mail vagy SMS küldése. Emiatt a platform natív. Ilyen feladat egy telefonhívás indítása. viszont előfordulnak olyan általános feladatok. indításuk a példányosítást és helyes paraméterezést követő Show() függvényhívással történik. a futtatott feladat pedig aktívvá válik. amelynek működését bővebben az 5.6. hogy a programok nem egy felhasználó kontextusában futnak. A taszkok a platform főbb funkcióihoz hozzáférést biztosító programok.Phone. sőt annak létezéséről ne is tudhassanak. hogy ezekhez fejlesztőként mi is hozzáférhessünk. Azért. hiszen nem várunk semmi adatot.

138 . amely feladatát egy-egy beépített vezérlő is képes ellátni. Erre elegáns módszer a 4. A példaalkalmazás létrehozása A fejezet első részében a felsorolt taszkokkal fogunk részletesen megismerkedni. Amennyiben viszont nincsenek egyedi igényeink a funkcióval kapcsolatban. érdemes ezek mentén külön lapokra bontani a megjelenítési felületet is. fejezetben bemutatott Pivot vezérlő. akkor nemcsak egyszerűbb a taszk használata. Alapvető telefonos funkciók használata A Mango verzióban elérhető Launcherek az alábbiak: Launcher neve EmailComposeTask MediaPlayerLauncher PhoneCallTask SmsComposeTask WebBrowserTask SearchTask MarketplaceDetailTask MarketplaceHubTask MarketplaceReviewTask MarketplaceSearchTask Megvalósított funkció E-mail üzenet írása és küldése Megadott média (video / audio) lejátszása Telefonhívás indítása SMS írása Böngésző indítása Webes keresés Alkalmazás részleteinek mutatása a Marketplace kliensben Marketplace kliens indítása Vélemény írása alkalmazásunkról a Marketplace-re Keresés indítása a Marketplace kliensben A Chooserek listája: Choose neve SavePhoneNumberTask SaveContactTask SaveEmailAddressTask EmailAddressChooserTask AddressChooserTask CameraCaptureTask PhoneNumberChooserTask PhotoChooserTask SaveRingtoneTask GameInviteTask Megvalósított funkció Telefonszám mentése a kapcsolatok tárába Új partner felvétele a kapcsolatlistára E-mail cím mentése a kapcsolatok tárába E-mail cím kiválasztása kapcsolatlistánkról Cím kiválasztása kapcsolatlistánkról Kép készítése alkalmazásunk számára Telefonszám kiválasztása kapcsolatlistánkról Fénykép kiválasztása a fényképtárból Csengőhang mentése Több résztvevős játékokban a partnerek meghívását teszi lehetővé Több olyan taszk is létezik.6. Ez a felhasználó számára sokkal egységesebb rendszerképet és könnyebb kezelhetőséget garantál. de a platform többi részével konzisztens megoldást is biztosít. Ehhez hozzunk létre egy új projektet 06 – Integrating with the Phone névvel! Mivel a Chooserek és Launcherek két jól szeparálható részre osztják a feladatot. amit legegyszerűbben a Windows Phone Pivot Application projektsablon kiválasztásával (6-2 ábra) helyezhetünk el alkalmazásunkban.

mivel példát mutat arra. A ViewModels mappa fogja össze azokat az osztályokat. hogyan tudjuk az MVVM modellnek megfelelően szervezni kódunkat.xaml állománya. 6-3 ábra: A sablon által generált projekt Ez a megközelítés a lehető legjobban elválasztja a különböző felelősségeket (adatszolgáltatás. ami XAML formátumban rögzít néhány tesztbejegyzést a tervezésidejű megjelenítéshez (a Blend és a Visual Studio design felülete is ezt használja). Ilyen adatforrás például a SampleData MainViewModelSampleData. logika. hogy ezt a forrást a tervező eszközök meg is jelenítsék.A példaalkalmazás létrehozása 6-2 ábra: Windows Phone Pivot Application sablon kiválasztása a projekt létrehozásakor A következő dialógusban mindenképpen válasszuk a Windows Phone OS 7. megjelenítés). amelyek az egyes oldalak.1-es verziót. Ahhoz. csak az alábbi attribútumokat kell hozzáadni a PhoneApplicationPage deklarációjához (természetesen a sablon alapján ezt a VS már megtette helyettünk): 139 . mivel a taszkok egy része csupán a Mango frissítéssel vált elérhetővé! A sablonból generált projekt felépítését (6-3 ábra) érdemes tüzetesebben átvizsgálni. és kihasználja a Silverlight által biztosított adatkötési mechanizmust. megjelenítési felületek által elvárt formában tárolják az egyéb adatforrásból származó információt.

ami a valós adatok előállításáért felelős.-12.microsoft.xaml}" Futtatáskor azonban nem ezeket az adatokat fogjuk látni.xaml. //.ItemTemplate> <DataTemplate> <StackPanel Margin="0.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" d:DataContext="{d:DesignData SampleData/MainViewModelSampleData..0. ugyanis a MainViewModel osztály rendelkezik egy LoadData metódussal. A Model osztály példányát az App. de ezt a Visual Studio már megtette helyettünk.Controls.0" Style="{StaticResource PhoneTextSubtleStyle}"/> </StackPanel> </DataTemplate> </ListBox.cs állítja elő. <Grid x:Name="LayoutRoot" Background="Transparent"> <!--Pivot Control--> <controls:Pivot Title="MY APPLICATION"> <!--Pivot item one--> <controls:PivotItem Header="first"> <!--Double line list with text wrapping--> <ListBox x:Name="FirstListBox" Margin="0. és publikálja egy statikus mező formájában: private static MainViewModel viewModel = null.0.assembly=Microsoft. xmlns:controls="clr-namespace:Microsoft.12.Phone.. Használatához hivatkoznunk kell a Microsoft.0.Phone.0" ItemsSource="{Binding Items}"> <ListBox..-6.17"> 140 .Controls" . A listák adatkötés használatával tárják elénk a ViewModelekben definiált publikus tulajdonságokat.17" Width="432" Height="78"> <TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/> <TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12.6. public static MainViewModel ViewModel { get { // ViewModel létrehozásának elhalasztása addig.com/expression/blend/2008" xmlns:mc="http://schemas. az oldal központi eleme ez a vezérlő.0. és azokon egyegy ListBoxot helyezett el. amíg szükségünk nem lesz rá if (viewModel == null) viewModel = new MainViewModel(). return viewModel.0.. sőt felvett két lapot a Pivotba.openxmlformats. } } A megjelenítésért a MainPage.ItemTemplate> <DataTemplate> <StackPanel Margin="0.-12.0.Phone.ItemTemplate> </ListBox> </controls:PivotItem> <!--Pivot item two--> <controls:PivotItem Header="second"> <!--Triple line list no text wrapping--> <ListBox x:Name="SecondListBox" Margin="0.xaml és a hozzá tartozó kódfájl felelős.Controls névtérre.0" ItemsSource="{Binding Items}"> <ListBox. Mivel a Pivot sablont választottuk. Alapvető telefonos funkciók használata xmlns:d="http://schemas.

amint elkészült az oldal. hogy a panel görgethetővé válik. ezek pozicionálását pedig bízzuk egy StackPanelre! A StackPanelt viszont mindenképpen egy ScrollVieweren belül definiáljuk.A példaalkalmazás létrehozása <TextBlock Text="{Binding LineOne}" TextWrapping="NoWrap" Margin="12.0" Style="{StaticResource PhoneTextSubtleStyle}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </controls:PivotItem> </controls:Pivot> </Grid> A megjelenítés és az adatok megismerése után már csak a két oldal közötti kapocs kialakítása maradt hátra. fejezete tökéletes kiindulópontot jelent a tanuláshoz. // Adatkötés DataContext = App. Az oldal kontextusát a MainPage konstruktora állítja a megfelelő ViewModelre: // Constructor public MainPage() { InitializeComponent(). Alakítsuk át a projektet a taszkok teszteléséhez szükséges formába! A Pivot két lapot tartalmazzon. viszont ha komolyan érdeklődünk a téma iránt. } // Adatok betöltése. és ami mögötte van című könyv 10. amennyiben a tartalom túlnyúlik a rendelkezésre álló helyen! <controls:Pivot Title="Integrating with the Phone"> <controls:PivotItem Header="launchers"> <ScrollViewer> <StackPanel> <Button Content="PhoneCallTask" Name="btnPhoneCallTask" Click="btnPhoneCallTask_Click"/> <Button Content="SmsComposeTask" Name="btnSmsComposeTask" Click="btnSmsComposeTask_Click"/> <Button Content="WebBrowserTask" Name="btnWebBrowserTask" Click="btnWebBrowserTask_Click" /> <Button Content="EmailComposeTask" Name="btnEmailLauncher" Click="btnEmailLauncher_Click" /> <Button Content="MediaPlayerLauncher" Name="btnMediaLauncher" Click="btnMediaLauncher_Click" /> <Button Content="SearchTask" Name="btnSearchTask" 141 . egyet a launcherek és egyet a chooserek számára. this.ViewModel. hiszen ezzel biztosítható az.0.IsDataLoaded) { App.LoadData(). RoutedEventArgs e) { if (!App.0" Style="{StaticResource PhoneTextExtraLargeStyle}"/> <TextBlock Text="{Binding LineThree}" TextWrapping="NoWrap" Margin="12. Minden taszk indítására vegyünk fel külön gombot.ViewModel. private void MainPage_Loaded(object sender.Loaded += new RoutedEventHandler(MainPage_Loaded).ViewModel.0. akkor a Silverlight 4: A technológia.-6.0. } } A generált projekt megvizsgálásával egy kis betekintést nyerhettünk az MVVM architekturális minta használatába.

ami először lehetőséget ad a felhasználónak a hívás elindítására vagy elutasítására. A chooserek lapja tartalmazzon egy Image vezérlőt is. } A Show() metódus elindítja a taszkot. némítási lehetőségekkel. hiszen a visszatérési értékek tartalmazhatnak szöveget és képet is! A szöveges válaszok megjelenítésére tökéletes egy felugró ablak (MessageBox). de így is megadhatjuk a számot phoneCallTask. mivel ezeket a 12.PhoneNumber = "00361/123-4567". Launcherek PhoneCallTask Telefonhívás indításakor kötelező megadni a hívandó telefonszámot. // ezt nem kötelező megadni phoneCallTask. csupán az érintett tulajdonság különbözik. fejezet részletesen taglalja. de vizuális elemeket ez sajnos nem tartalmazhat.Show(). 142 . A hívás lebonyolítása a megszokott felületen történik. RoutedEventArgs e) { PhoneCallTask phoneCallTask = new PhoneCallTask(). a kihangosítási. hiszen működésük teljesen azonos. // a tagolás nem kötelező.6. Emellett egy nevet is megjeleníthetünk. de ennek hiánya sem okoz problémát: private void btnPhoneCallTask_Click(object sender.DisplayName = "WP7 support". phoneCallTask. Ezenfelül fölösleges különbséget tenni a telefonszámot vagy e-mail címet szolgáltató és módosító feladatok között. majd a hívást összegző üzenetet láthatjuk (6-4 ábra). Alapvető telefonos funkciók használata Click="btnSearchTask_Click"/> </StackPanel> </ScrollViewer> </controls:PivotItem> <controls:PivotItem Header="choosers"> <ScrollViewer> <StackPanel> <Button Content="SavePhoneNumberTask" Name="btnSavePhone" Click="btnSavePhone_Click" /> <Button Content="PhoneNumberChooserTask" Name="btnPhoneNumberChooserTask" Click="btnPhoneNumberChooserTask_Click" /> <Button Content="CameraCaptureTask" Name="btnCameraCaptureTask" Click="btnCameraCaptureTask_Click" /> <Button Content="PhotoChooserTask" Name="btnPhotoChooserTask" Click="btnPhotoChooserTask_Click" /> <Image Name="imgResult" Width="400" Height="400" /> </StackPanel> </ScrollViewer> </controls:PivotItem> </controls:Pivot> A launcherek és chooserek listájáról hiányoznak a Marketplace-szel kapcsolatos taszkok.

987-6543".To = "123-4567. smsComposeTask. amit az üzenetváltásban jelez számunkra a rendszer(6-5 ábra). ahogyan az üzenet szövegét is átírhatjuk. de mindkét érték elhagyható: private void btnSmsComposeTask_Click(object sender.Show().Body = "szöveg". 6-5 ábra: Sms küldése SmsComposeTask használatával 143 . smsComposeTask. smsComposeTask.Launcherek 6-4 ábra: Telefonhívás lebonyolítása alkalmazásunkból SmsComposeTask Sms küldésekor lehetőségünk van megadni a címzettek listáját és az üzenet szövegét is. Természetesen a küldés az emulátoron meg fog hiúsulni. RoutedEventArgs e) { SmsComposeTask smsComposeTask = new SmsComposeTask(). } A feladat indításakor a megadott értékek megjelennek az sms-ek küldését végző alkalmazásban. A címzetteket a + gombra kattintva kiegészíthetjük. Az ApplicationBaron található gombokkal médiaelem csatolására és üzenet diktálására is lehetőségünk van.

Bcc = "delta@test. Mivel az emulátoron jelenleg nincs mód arra.Show(). pusztán a Show() függvényhívással egy üres e-mail alkalmazást nyissunk.Cc = "charlie@test. de bizonyos esetekben jó tudni arról. (Ezeket az emulátorokat többnyire ingyenesen tölthetjük le. 144 .com". // task indítása emailTask. // elavult.Subject = "tárgy". Az egyik az. a levélküldés sajnos nem lesz tesztelhető.com".Body = "üzenet szövege". Két megoldás létezik arra. hogy telefonkészülékre telepítjük az alkalmazásunkat. ezt követően jelenik csak meg a szerkesztő felület. Szerencsére ez nem jelent külön feladatot. hogy melyik fiókot szeretné használni a feladathoz. a másik pedig az.URL = "xy.com. RoutedEventArgs e) { EmailComposeTask emailTask = new EmailComposeTask(). Mi a készüléken való kipróbálást ajánljuk. A levelek küldése előtt a taszk megkérdezi a felhasználót. Erre tökéletes megoldás a WebBrowser vezérlő. de lehetőség van arra is.) 6-6 ábra: A levélküldés sajnos nem elérhető az emulátorról private void btnEmailLauncher_Click(object sender. RoutedEventArgs e) { WebBrowserTask webBrowserTask = new WebBrowserTask(). } Az üzenet minden adata a kódból is beállítható. ugyanis az a megbízhatóbb.com". hogy létezik más megoldás is. // rejtett másolat emailTask. emailTask. viszont ez önmagában csak egy megjelenítő és értelmező felület. amelyet a szolgáltatások igénybevétele során használ. a beépített Internet Explorer 9 előnyeit. már ne használjuk! //webBrowserTask. Ha nincsenek olyan egyedi igényeink. az alsó URL sávot. hogy ezek nélkül. bravo@test. hogy ezt a funkciót kipróbáljuk. emailTask. hogy ilyen fiókokat állítsunk be. WebBrowserTask Gyakori igény alkalmazásokban teljes weboldalak megjelenítése.6.To ="alpha@test. mint például saját elemek felvétele az ApplicationBarba. hogy keresünk egy a Microsoft által nem támogatott emulátort. hiszen a telefon konfigurálása során valószínűleg minden felhasználó beállít egy felhasználói fiókot. // több címzett megadása emailTask. akkor érdemes lehet a böngésző programot elindító WebBrowserTaskot használnunk: private void btnWebBrowserTask_Click(object sender. // másolat küldése emailTask. Alapvető telefonos funkciók használata EmailComposeTask Levelek küldéséhez szükségünk van egy levelező szerverre is. ami alkalmas ennek a szolgáltatásnak a kipróbálására.com". a kedvencek és előzmények rendszerezését és még számos funkciót elveszítünk a használatával. csak készülékre telepítve (6-6 ábra).

Media = new Uri(@"http://mschannel9. Ennek megfelelően ki kell választanunk. ami teljes testreszabhatóságot biztosít számunkra.Controls = MediaPlaybackControls.Show(). ezt pedig a MediaPlayerLauncher Location tulajdonságán keresztül tehetjük meg.vo. Az egyik a Toolboxban megtalálható MediaElement vezérlő. A példában egy internetes videót választottam. ami lehet lokális vagy távoli. } A böngésző első indításakor engedélyt kér a böngészés adatainak felhasználására a Bing kereső továbbfejlesztésének érdekében. RoutedEventArgs e) { MediaPlayerLauncher mpl = new MediaPlayerLauncher(). } 145 .All. így a generált oldal teljesen megegyezik a számítógépeken megszokottal. mpl.Absolute).net/o9/mix/09/wmv/key01.wmv". UriKind.Data. A böngésző a Mango frissítésnek hála teljes HTML 5 támogatással rendelkezik. hogy az alkalmazással telepített vagy az Isolated Storage-be mentett médiát címzünk meg.Launcherek webBrowserTask.hu/wp7". ami a 6-7 ábrán látható. mpl.Absolute). 6-7 ábra: A https://devportal.hu/wp7 oldal egy WebBrowserTaskban megjelenítve MediaPlayerLauncher A platform két rendkívül egyszerűen használható lehetőséget biztosít médiaelemek lejátszására. //mpl. UriKind. Ha a telefonon található tartalmat szeretnénk lejátszani.hu/wp7 oldal. hogy relatív vagy abszolút címzésről van szó.Uri = new Uri("http://www. Jó példa erre az Orchard keretrendszerben elkészített HTML 5-öt használó https://devportal.devportal. akkor meg kell adnunk.msecnd. webBrowserTask.Show(). internetről származó is. mpl. Választásunkat követően az oldal betöltődik az Internet Explorer 9 mobilos változatába. így most abszolút címzést alkalmazunk. a másik pedig a pár kódsorral paraméterezhető MediaPlayerLauncher taszk (6-8 ábra). private void btnMediaLauncher_Click(object sender. A taszk használatakor a példányosítást követően meg kell adnunk a lejátszandó video vagy audio elem címét.Location = MediaLocationType.

a beviteli mező jobb szélén található mikrofon gombra kattintva akár diktálva is. A 6-8 ábrán az összes elem együttes használata látható. minden beépített vezérlővel SearchTask Kereső funkciót megvalósító taszk. aminek hála a keresés a Marketplace alkalmazásait is megvizsgálja. private void btnSearchTask_Click(object sender. Skip. hogy milyen előre definiált vezérlők jelenjenek meg a médialejátszóban. Pause. Rewind. és a többi találat előtt ajánlja az illeszkedő alkalmazásokat. None. Ez a mező a MediaPlaybackControl enumeráció (All. aminek lapjait a 6-9 ábra mutatja. A Mango újdonsága az ún. Segítségével a megadott kulcsszó alapján kereshetünk a weben.6.SearchQuery = "pizza". Stop) egy értékét veheti fel. akkor a pozíciónk körüli kiemelt helyek között is. Alapvető telefonos funkciók használata A Controls tulajdonságon keresztül kiválaszthatjuk. FastForward. searchTask. akár képek között. } 6-9 ábra: A SearchTask találatainak listája 146 . RoutedEventArgs e) { SearchTask searchTask = new SearchTask(). searchTask. 6-8 ábra: MediaPlayerLauncher taszk egy videó lejátszása közben. A keresőszót a taszkon belül módosíthatjuk. de ha engedélyeztük a Location Servicest. A találatok egy Pivot vezérlőn jelennek meg.Show(). App Connect.

A visszatérési érték TaskResult mezője a TaskResult felsorolás egyik lehetséges értékével jelzi a futás kimenetelét. érdemes lambda kifejezéssel megadott anonim metódust alkalmazni. spn. de egy telefonszám mentését indítványozó SavePhoneNumberTask kimenete közvetlenül nem érzékelhető.None: MessageBox.Show("Mentés megszakítva!"). mivel egy fellépő hibáról azonnal értesül a felhasználó. Az állapotátmenetek működésével az 5. esetleges meghiúsulásukról kell értesítenünk a felhasználót. hogy amíg nem zártuk be a MessageBoxot az OK gombbal. } }. } A Completed eseménykezelőjét megadhatjuk külön eljárásként is. Ennek megfelelően a taszk felparaméterezése után definiálnunk kell egy eseménykezelő függvényt. hibája pedig adatvesztéshez vezethet. spn. és újra a mi alkalmazásunk kerül előtérbe. Ennek az a következménye.Chooserek Chooserek A chooserek közé tartoznak azok a taszkok.Show("Telefonszám elmentve!"). 147 .Cancel: MessageBox. result) => { switch (result. azaz a Completed eseménykezelő közvetlenül az Application_Activated után fut le. képet).Show(). meghiúsult). Emiatt az ilyen taszkok visszatérési értékkel rendelkeznek. hogy nem fogunk máshol használni. amit nekünk kell a felhasználó felé továbbítanunk egy üzenetdoboz megjelenítésével: private void btnSavePhone_Click(object sender. SavePhoneNumberTask Az első megvizsgált chooser esetében nem valamilyen szolgáltatott adatra. A taszkok természetesen külön szálon futnak. amelyek adatot szolgáltatnak alkalmazásunk számára. Egy telefonhívás indítása launcher. a képeket pedig a gombok alatt található Image vezérlőben. valamint azok is. mivel a MessageBox megjelenítése. break. valamint bármilyen a taszk jellegéből adódó adatot (pl. Ez azt jelenti. amelyekkel a műveletek kimenetéről. amely akkor fut le. de mivel egyszerű.TaskResult) { case TaskResult. hogy valamely ismerősünk adatait egy új telefonszámmal egészítsük ki. amit egészen biztos. fejezet foglalkozik részletesen.PhoneNumber = "0000/1234567". rövid kódról van szó. case TaskResult. hogy ha túl sokáig hagyjuk fent a párbeszédablakot. hogy az állapotváltás eseménykezelője fut. A SavePhoneNumberTask a Contacts alkalmazást indítja el. break. spn. akkor a rendszer – az alkalmazás eseményeinek 10 másodperces időkorlátja miatt – leállítja programunk futását. RoutedEventArgs e) { SavePhoneNumberTask spn = new SavePhoneNumberTask(). ami tartalmazhat egy kivételt (Exception).Completed += (s. amikor a taszk futása már befejeződött. hanem a művelet eredményességére vagyunk kíváncsiak. case TaskResult.Show("A telefonszám mentése nem sikerült!"). illetve a futás kimenetelét (sikeres.OK: MessageBox. A példa során ebben a metódusban egy párbeszédablakban fogjuk megjeleníteni a szöveges visszatérési értékeket. Egy valós alkalmazás során ez a megközelítés nem lenne működőképes. addig a rendszer úgy érzékeli. így a kommunikáció egy eseménykezelő (Completed) implementálásával történik. mégis képes „megfogni” programunk aktiválódását. break. amelyben lehetőséget biztosít arra.

OK) { string name = result. akkor a telefonszám mentésére lehetőséget biztosító oldal következik. number)). Ha itt kiválasztunk egy partnert. string number = result. MessageBox. A folyamat a 6-10 ábrán tekinthető meg. } 6-11 ábra: A kiválasztott partner neve és telefonszáma 148 . 6-10 ábra: Egy telefonszám mentésének lépései és a visszatérési érték megjelenítése PhoneNumberChooserTask A PhoneNumberChooserTask szintén a Contacts alkalmazást nyitja meg.Error == null && result.Show(string. } }.6. Ekkor fut le az általunk definiált eseménykezelő. A módosítások mentése után a kapcsolat adatait részletező oldalra kerülünk. amelyek a tesztelések megkönnyítésére kerültek be az emulátorba. ami megvizsgálja és az általunk definiált eljárás alapján jelzi a visszatérési értéket. result) => { if (result. RoutedEventArgs e) { PhoneNumberChooserTask phoneNumberChooser = new PhoneNumberChooserTask(). name. amin keresztül elérhetjük a kiválasztott partner nevét és telefonszámát (611 ábra): private void btnPhoneNumberChooserTask_Click(object sender. A Completed eseménykezelő második paramétere egy PhoneNumberResult példány.PhoneNumber.Format("Név: {0}\nTelefonszám:{1}". viszont ez a taszk már adatot is szolgáltat a hívó alkalmazás számára.Show(). ahonnan a Back gomb megnyomásával térhetünk vissza a taszkot indító alkalmazásba.TaskResult == TaskResult.DisplayName. Alapvető telefonos funkciók használata A Contacts alkalmazás indulásakor néhány előre definiált partner közül választhatunk. phoneNumberChooser. phoneNumberChooser.Completed += (s.

akkor a teljes kiválasztott képet visszakapjuk. RoutedEventArgs e) { CameraCaptureTask cameraTask = new CameraCaptureTask(). result) => { if (result. Ha ezeket üresen hagyjuk.Windows. } Az emulátor szerencsére egy kamera működését is szimulálni tudja.Show(). private void btnCameraCaptureTask_Click(object sender.Chooserek CameraCaptureTask A kamera használatának legegyszerűbb módja egy CameraCaptureTask indítása.Source = bmp. így a kapott képet meg tudjuk jeleníteni (6-12 ábra).Imaging. cameraTask. Meghatározhatjuk az általunk elvárt kép dimenzióit is a PixelHeight és PixelWitdh tulajdonságok értékének beállításával. akkor kikerül a különböző képtárak listája alá egy CameraCaptureTaskot indító gomb is. de a célra tökéletesen megfelelő mozgó fekete kockával szembesülhetünk a taszk indításakor. amit nem lehet közvetlenül képforrásként használni. ha nem is naplementés tájképekkel. 6-12 ábra: Kép készítése CameraCaptureTask használatával PhotoChooserTask A PhotoChooserTask egy kép kiválasztását teszi lehetővé a telefon médiatárából.Completed += (s. cameraTask. imgResult.Media. Az osztály rendelkezik egy ShowCamera tulajdonsággal.SetSource(result. ha a dimenziók rögzítése mellett döntünk. amit ha engedélyezünk. 149 . akkor lehetőségünk lesz a képen kijelölni a kívánt területet. abban az esetben viszont. Ez a SetSource metódusával már fel tudja dolgozni a streamet.OK) { // System. ezért be kell vezetnünk egy BitmapImage változót is. A feladat egy Streammel tér vissza. } }.BitmapImage BitmapImage bmp = new BitmapImage(). erről a fejezet következő részében lesz szó. bmp.TaskResult == TaskResult. A Mango frissítéssel megjelent a PhotoCamera osztály is az eszközkészletben.ChosenPhoto).

ChosenPhoto).OriginalFileName).PixelHeight = 50.Show().ShowCamera = true. ami egy kijelölt tárterületen képes lekérdezéseket futtatni. a találatokat pedig generikus listán szolgáltatja a hívó alkalmazásnak.Completed += (s. RoutedEventArgs e) { PhotoChooserTask photoChooserTask = new PhotoChooserTask().6. BitmapImage bmp = new BitmapImage(). // lehetőséget adhatunk a kamera taszk indítására is egy gomb engedélyezésével photoChooserTask. Jelenleg két implementációja. // dimenziók beállítása photoChooserTask. bmp. Az új fejlesztői készletben megjelent ugyanis a PhoneDataSharingContext osztály. Alapvető telefonos funkciók használata private void btnPhotoChooserTask_Click(object sender.TaskResult == TaskResult. } A példakódban egy 50 pixel magas és 200 pixel széles képet szeretnénk beolvasni. és csupán az ezen belül található képrészt adja majd vissza alkalmazásunk számára (6-13 ábra). Ezek bemutatására vegyünk fel egy új lapot a korábban használt pivotra datasharing névvel! Az új lapon definiáljunk egy-egy gombot.OriginalFileName != null) { MessageBox. valamint egy új képet a két feladathoz: <controls:PivotItem Header="datasharing"> <ScrollViewer> <StackPanel> <Button Content="Contacts" Name="btnContacts" Click="btnContacts_Click" /> <Button Content="Appointments" Name="btnAppointments" Click="btnAppointments_Click" /> <Image Name="imgDataSharing" Width="400" Height="400" /> 150 .OK && result. a Contacts és az Appointments osztály érhető el. imgResult.Show(result. } }.SetSource(result. photoChooserTask.Source = bmp.PixelWidth = 200. 6-13 ábra: Meghatározott méretű kép kiválasztása és megjelenítése Adatok megosztása alkalmazások között A taszkok rendszere mellett a Mango frissítéssel bekerült egy új lehetőség az alkalmazások közti adatmegosztásra. photoChooserTask. photoChooserTask. result) => { if (result. így a taszk lehetőséget kínál egy ekkora terület kijelölésére.

stb. stb. céges. SignificantOther és OfficeLocation tulajdonságokat! 151 . és egy közös tárban teszi hozzáférhetővé. mivel a telefonszám módosítását követően a Contacts alkalmazásban maradunk addig. hogy egy felhasználó tartalmazhat több telefonszámot. Az emulátoron szereplő kapcsolatlista jó kiindulási alap a teszteléshez. hogy kitűztük-e a felhasználó hivatkozását a kezdőlapra. hogy a különböző helyekről származó adatokat összefésüli. facebook. Az ezen keresztül elérhető tulajdonságok az alábbi táblázatban találhatók: Tulajdonság Accounts Addresses Birthdays Children Companies CompleteName DisplayName EmailAddresses IsPinnedToStart Notes PhoneNumbers SignificantOthers Websites GetPicture() Leírás Azon források listája. A partnerhez rögzített jegyzeteink listája A partner telefonszámai. hanem metódus. A partnerlista egyik nagyszerű tulajdonsága az. telefonszám vagy minden mező alapján kereshetünk. amíg a Back gombbal vissza nem navigálunk az alkalmazásunkba. FirstName. A Contacts nem túl meglepő módon a Contact osztály példányainak listáját szolgáltatja. ezek uniójaként egy felhasználót látunk a partnerlistánkon (némely esetben a felhasználók összekapcsolását nekünk kell elvégeznünk. annak összes adatát egyetlen helyről. Live. de akár olyan ellentmondásos helyzetek is kialakulhatnak. Ennek természetes velejárója az. hogy aki a SIM kártyánkra mentett ismerősünk. MiddleName. Tartalmazzák a számot és a telefonszám típusát is (otthoni. mobil. Itt válasszunk egy profilképet. de fontos megjegyezni. és töltsük ki a JobTitle. transzparens módon érhetjük el.) A partner párkapcsolatai Weblapok listája Ugyan nem tulajdonság. LastName).) Címek listája Partnerünk összes szülinapjának listája Ismerős gyermekei Munkahelyek listája A partner teljes neve. Birthday. amiket le szeretnénk kérdezni! A módosításokhoz használhatjuk akár a SavePhoneNumberTaskot is. Tehát annak ellenére. megmutatja. e-mail cím. de szerepel például a facebookos vagy hotmailes ismerőseink listáján is. hiszen a név nem egyedi azonosító egy személy esetében). hogy a felhasználó képének lekérésére is van lehetőségünk. Megjelenített név E-mail címek listája Boolean érték.Adatok megosztása alkalmazások között </StackPanel> </ScrollViewer> </controls:PivotItem> Contacts A Contacts osztály a telefonon tárolt összes kapcsolatunkhoz hozzáférést biztosít alkalmazásunk számára. hogy több információforrásunk is van. a találatoknak pedig minden információjához hozzáférhetünk. Ez azt jelenti. párkapcsolattal (ennek megítélése nyilván felhasználófüggő) rendelkezik. Típusosan elérhető a név összes része (Nickname. Segítségével név. amelyeken partnerünk a felhasználó (pl. amikor egy partnerünk több szülinappal. e-mail címet. de a biztonság kedvéért egészítsük ki például Chris Sells adatait azokkal az információkkal.

string significantOther = contact.Birthdays.First(). contacts.CompanyName.Notes. string birthday = contact.SignificantOthers. string note = contact. imgDataSharing. sajnos az emulátoron mindig egy üres listát fogunk visszakapni.First(). Facebook. // csak a nevek között keresünk contacts.First(). string title = contact. birthday. viszont mivel ezek az adatok mindenképpen felhasználói fiókhoz kötődnek (Live.First().First(). company. bmp. RoutedEventArgs e) { Contacts contacts = new Contacts().Source = bmp. stb. ahol a tulajdonságok többsége szintén egy IEnumerable példány. FilterKind.SetSource(contact.ToShortDateString().First().).SearchCompleted += (s. } A fenti kódban minden listának csak az első elemét kérdeztük le. Hotmail.Show(string.Results. MessageBox. name.JobTitle.DisplayName. null).6. // felhasználó képének lekérése BitmapImage bmp = new BitmapImage(). A függvény futásának eredménye a 6-14 ábrán látható. // megjelenítés string formatStr = "Name: {0}\nCompany: {1}\nTitle: {2}\n" + "Birthday: {3}\nSignificantOther: {4}\nNote: {5}".Companies. 6-14 ábra: Partner adatainak lekérdezése PhoneDataSharingContext használatával Appointments A naptárbejegyzések lekérdezése a kapcsolatok kezeléséhez hasonlít.Format(formatStr. de természetesen a keresés ettől függetlenül felhasználók listáját adja vissza. Alapvető telefonos funkciók használata A módosításokat követően írjuk meg a Contacts gomb klikk eseménykezelőjét! private void btnContacts_Click(object sender. string company = contact. }. significantOther. result) => { var contact = result. // egyéb adatok string name = contact. title.Companies. A bejegyzést megtestesítő Appointment osztály főbb tulajdonságai a következő táblázatban láthatók: 152 .CompleteName.FirstName. note)).GetPicture()).SearchAsync("c".

Kamera használata taszk nélkül

Tulajdonság
Account Attendees Details StartTime EndTime IsAllDayEvent IsPrivate Location Organizer Status Subject

Leírás A naptárbejegyzést tároló felhasználói fiók Résztvevő felhasználók (Attendee lista) A bejegyzés szöveges leírása Kezdés ideje Befejezés ideje Boolean, egész napos eseményről van-e szó? Mindenki által látható vagy privát esemény? A találkozó helye (szövegként) A szervező személy (Attendee példány) Részvételi állapotunk A bejegyzés tárgya röviden

Alkalmazása tehát nagyon hasonlít a partneradatok lekérdezéséhez. A SearchAsync() hívása új szálon elindítja a keresést, a visszatérési értéket pedig a SearchCompleted eseménykezelőben használhatjuk fel:
private void btnAppointments_Click(object sender, RoutedEventArgs e) { Appointments apps = new Appointments(); apps.SearchCompleted += (s, result) => { var events = result.Results; if (events != null && events.Count() > 0) { var myEvent = events.OrderBy(c => c.StartTime).First(); string formatStr = @"A következő esemény {0} napon kezdődik, tárgya: {1}, résztvevői pedig:\n{2}"; StringBuilder builder = new StringBuilder(); foreach (var item in myEvent.Attendees) { builder.AppendFormat("{0}\n", item.DisplayName); } MessageBox.Show(string.Format(formatStr, myEvent.StartTime.ToShortDateString(), myEvent.Subject, builder.ToString())); } }; apps.SearchAsync(DateTime.Now, DateTime.Now.AddMonths(6), null); }

Kamera használata taszk nélkül
A CameraCaptureTask használatán túl lehetőségünk van közvetlenebb módon is kommunikálnunk a készülék kameráival. Az operációs rendszer Mango verziója ugyanis elérhetővé teszi számunkra a fényképek készítését lehetővé tevő PhotoCamera és a videorögzítést megkönnyítő VideoCaptureDevice osztályokat. Ezek működése nagyrészt hasonlít egymáshoz, a különbség főként az adatok tárolásakor mutatkozik meg. Mindkét esetben az Isolated Storage-be vagy a Media Library-ba menthetünk, de videó rögzítésekor a folyamatos adatfolyam miatt a FileSink segédosztályt is használnunk kell. A következő példa során valós idejű képet fogunk mutatni a kamera képéről, és lehetőséget adunk fénykép készítésére akár a fő, hátlapon lévő kamerát, akár az előlapon lévőt használva.

153

6. Alapvető telefonos funkciók használata Mindenekelőtt a WMAppManifest.xml állományban jelezzük, hogy alkalmazásunk fogja használni a készülék kameráit. Ehhez egészítsük ki a Capabilities szekciót a két kamera azonosítójával (a hátlapon lévő kamera bejegyzése valószínűleg már a generált állományban is megtalálható):
<Capabilities> <Capability Name="ID_HW_FRONTCAMERA"/> <Capability Name="ID_CAP_ISV_CAMERA"/> ... </Capabilities>

Vegyünk fel egy Windows Phone Landscape Page -et projektünkbe Camera névvel (6-15 ábra)! Ez a sablon egy olyan oldalt generál, amely csak Landscape módban jelenik meg, de természetesen ez két tulajdonság módosításával felüldefiniálható.

6-15 ábra: Windows Phone Landscape Page sablon Mivel az oldalt a továbbiakban fektetett módban fogjuk használni, érdemes az emulátort is ehhez igazítani. Ehhez az emulátor jobb oldali menüjében találjuk a jobbra és balra forgató gombokat (6-16 ábra).

6-16 ábra: Emulátor forgatása Adjunk hozzá egy gombot az eddig szerkesztett MainPage oldalhoz, ami az új Camera.xaml oldalunkra fog navigálni!
<Button Content="Camera" Name="btnCamera" Click="btnCamera_Click" /> // kódfájl: private void btnCamera_Click(object sender, RoutedEventArgs e) { NavigationService.Navigate(new Uri("/Camera.xaml", UriKind.Relative)); }

Mielőtt nekiállnánk a kódfájlban létrehozni minden objektumot és a funkcionalitást implementálni, gondoljuk végig, hogy mire lesz szükségünk! Mivel két kamera képét egyszerre nem tudjuk kezelni, lehetővé kell tennünk a felhasználó számára, hogy váltani tudjon azok között. Erre tökéletesen megfelel egy Slider, ami két értéket vehet fel. Azért is szerencsés ez a választás, mert az operációs rendszer legtöbb beállításánál is így vannak megvalósítva a kapcsolók, és az sohasem baj, ha a platformmal konzisztensek maradunk. A kapcsoló állásától függ a kirajzolt kép és az adatmentés forrása. Egy gombbal pedig

154

Kamera használata taszk nélkül lehetőséget kell adnunk a fénykép készítésére is, viszont a feldolgozás idejére ezt inaktívvá is kell tennünk. Látszik, hogy itt az előző taszkindításoknál bonyolultabb dolgunk lesz, például adatkötéseket is meg kell valósítanunk. Ennek érdekében a feladatot a fejezet elején leírt modell szerint egészítsük ki, azaz hozzunk létre egy ViewModelt az oldal számára! A ViewModels mappához adjunk hozzá egy új osztályt CameraViewModel névvel, ez pedig valósítsa meg az INotifyPropertyChanged interfészt:
public class CameraViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler(this, new PropertyChangedEventArgs(propertyName)); } } }

Ez az osztály tároljon minden tulajdonságot és logikát, amit a Camera.xaml-nek a megjelenítés során alkalmaznia kell! Vegyük is fel ezeket az alábbiak szerint:
public PhotoCamera Camera { get; set; } private VideoBrush cameraBrush; /// <summary> /// Az élő képet megjelenítő VideoBrush /// </summary> public VideoBrush CameraBrush { get { return cameraBrush; } set { cameraBrush = value; NotifyPropertyChanged("CameraBrush"); } } private bool isCameraChooserEnabled; /// <summary> /// True, ha mindkét kamera elérhető, azaz a választó /// slide-nak aktívnak kell lennie /// </summary> public bool IsCameraChooserEnabled { get { return isCameraChooserEnabled; } set { isCameraChooserEnabled = value; Deployment.Current.Dispatcher.BeginInvoke(() => { NotifyPropertyChanged("IsCameraChooserEnabled"); }); } } private bool isFrontCamera; /// <summary> /// True, ha az előlapi kamera aktív, egyébként false /// </summary> public bool IsFrontCamera {

155

6. Alapvető telefonos funkciók használata

get { return isFrontCamera; } set { isCameraChooserEnabled = value; Deployment.Current.Dispatcher.BeginInvoke(() => { NotifyPropertyChanged("IsFrontCamera"); }); } } private bool isPhotoEnabled; /// <summary> /// True, ha készen állunk fénykép készítésére, /// azaz a fotó gomb aktív /// </summary> public bool IsPhotoEnabled { get { return isPhotoEnabled; } set { isPhotoEnabled = value; Deployment.Current.Dispatcher.BeginInvoke(() => { NotifyPropertyChanged("IsPhotoEnabled"); }); } } /// <summary> /// Fénykép készítése /// </summary> public void TakePhoto() { // nem készíthetünk új képet, amíg ezt nem dolgoztuk fel IsPhotoEnabled = false; Camera.CaptureImage(); }

A kódban kiemelem azokat a tulajdonságokat, amelyeket kötnünk kell egy vezérlőhöz a megjelenítő oldalon. Ezeknél a set metódust úgy kell módosítani, hogy az értékadást követően egy NotifyPropertyChanged hívással jelezzék a mögöttes érték változását. Emiatt nem lehet a rövidített public string PropertyName { get; set; } formátumot használni, a teljes kifejtésre van szükség. Szerencsére ez a „prop” + TAB + TAB beírásával legenerálható, és így a gépelés nagy részét megúszhatjuk. Mivel a kamerával kapcsolatos feladatok nem az UI szálon futnak, szükségünk lesz a Dispatcher használatára, hogy a változásokat a felhasználói felületen is megjeleníthessük. Kezdjük el leprogramozni a vezérlő logikáját! A két kamerát egyszerre nem tudjuk kezelni, így valahol meg kell oldanunk a kiválasztott eszköz eseményeinek figyelését, míg a másik kamerát ki kell kapcsolnunk. Magától értetődő választás erre az IsFrontCamera tulajdonság set metódusa, mivel a kamera kiválasztásakor közvetlenül ez az eljárás fog futni. Itt szabaduljunk meg egy Dispose hívással a korábbi kamerától, majd példányosítsunk egy megfelelő típusú PhotoCamera-t (Primary, FrontFacing)! Definiáljuk az új objektum CaptureImageAvailable eseménykezelőjét, ami a kép elkészültekor fog lefutni. Emellett gondoskodjunk az IsCameraChooserEnabled tulajdonság kezeléséről is, mivel az objektum inicializálása viszonylag sok időt vesz igénybe, és ha még eközben kamerát váltunk, akkor a Dispose() hívás a félkész objektumon hibát fog eredményezni.
public bool IsFrontCamera { get { return isFrontCamera; } set

156

Kamera használata taszk nélkül

{ isFrontCamera = value; // előzőleg beállított kamera törlése, ha volt if (Camera != null) { Camera.Dispose(); } if (isFrontCamera) {// előlapi kamera Camera = new PhotoCamera(CameraType.FrontFacing); } else {// hátlapi kamera Camera = new PhotoCamera(CameraType.Primary); } // Init lezárása előtt ne lehessen kamerát váltani (Dispose) IsCameraChooserEnabled = false; Camera.Initialized += (s, e) => { if (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) && PhotoCamera.IsCameraTypeSupported(CameraType.Primary)) { // kameraváltás újbóli engedélyezése IsCameraChooserEnabled = true; } }; Camera.CaptureImageAvailable += (s, e) => { string name = DateTime.Now.ToShortTimeString() + ".jpg"; // TODO: mentés megírása // újra fotózhatunk IsPhotoEnabled = true; Deployment.Current.Dispatcher.BeginInvoke(() => { // visszajelzés küldése (UI szál) MessageBox.Show(name + " mentve!"); }); }; NotifyPropertyChanged("IsFrontCamera"); } }

A kép már elkészül, azt viszont még csak a telefon pozíciójából tudjuk kikövetkeztetni, hogy mit fotóztunk. Ennek kiküszöbölésére csak annyi a teendőnk, hogy a korábban deklarált ecsetet összekötjük a kamerával, még ugyanebben a set metódusban, például a NotifyPropertyChanged("IsFrontCamera"); hívása előtt:
// ... // VideoBrush beállítása a kiválasztott kamerára cameraBrush.SetSource(Camera); NotifyPropertyChanged("IsFrontCamera"); }

A tulajdonságok halmaza és a logika már kész, már csak inicializálni kell az értékeket. Vegyünk fel erre egy új függvényt, LoadData névvel:

157

6. Alapvető telefonos funkciók használata

public void LoadData() { CameraBrush = new VideoBrush(); IsPhotoEnabled = true; if (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) && PhotoCamera.IsCameraTypeSupported(CameraType.Primary)) { // mindkét kamera elérhető --> választhassunk IsCameraChooserEnabled = true; IsFrontCamera = true; } else { // csak az egyik kamera érhető el (vagy egyik sem) IsCameraChooserEnabled = false; if (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing)) { IsFrontCamera = true; } else if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary)) { IsFrontCamera = false; } else { MessageBox.Show("Nincs elérhető kamera!"); } } }

Ennek az eljárásnak az a feladata, hogy kiderítse, hozzáférünk-e egyáltalán a kamerákhoz, és ennek megfelelően inicializálja a tulajdonságokat. Nem lenne szép megoldás, ha ezt a ViewModelt egy Camera objektum példányosítaná, ehelyett vegyünk fel egy statikus tulajdonságot az App osztályban, amin keresztül a View eléri a hozzá tartozó ViewModelt:
private static CameraViewModel cameraVM; public static CameraViewModel CameraVM { get { if (cameraVM == null) { cameraVM = new CameraViewModel(); } return cameraVM; } }

A Camera.xaml kódfájljában pedig módosítsuk úgy a konstruktort, hogy az kérje el az App osztálytól a statikus ViewModelt, majd ezt állítsa be DataContextnek! Amint az oldal betöltődött, inicializáljuk az értékeket a LoadData meghívásával:
CameraViewModel ViewModel; public Camera() { InitializeComponent(); ViewModel = App.CameraVM; DataContext = ViewModel;

158

hogy a mozgóképet jelképező fekete téglalap melyik irányban mozog. már csupán a megjelenítő felületet kell létrehoznunk.Kamera használata taszk nélkül this.ColumnDefinitions> <ColumnDefinition Width="600" /> <ColumnDefinition Width="*" /> </Grid. jobbra mellé pedig a vezérlő gombok: <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid. így a vezérlő értékének módosításával a mögöttes tulajdonság értéke is változik! Egyetlen feladatunk maradt hátra. } Ha sehol nem hibáztunk.LoadData(). } Ezzel be is fejeztük a logika megírását és a ViewModel „behuzalozását”. itt csupán egy függvényhívásra van szükségünk: private void btnPhoto_Click(object sender. A kiválasztott kamerát az alapján tudjuk azonosítani.Loaded += (s. amikor nincs folyamatban lévő képfeldolgozás. a képkészítést indító gomb eseménykezelőjének megírása. a hátlapon lévő fő kamera esetében pedig azzal megegyező. Fontos. e) => { ViewModel. }. A fektetett megjelenítés miatt a bal oldalra kerülhet az élőképet mutató Canvas. a gombhoz pedig bekötjük az IsPhotoEnabled tulajdonságot.Column="1"> <Button Name="btnPhoto" Content="Kép" Click="btnPhoto_Click" IsEnabled="{Binding IsPhotoEnabled}"/> <Slider Value="{Binding IsFrontCamera. így az csak akkor lesz aktív. 159 .place additional content here--> <Canvas Name="ContentCanvas" Width="600" Height="440" Background="{Binding CameraBrush}"> </Canvas> <StackPanel Grid. Az előlapon lévő kamera kiválasztása esetén ez a mozgás az óramutató járásával ellentétes lesz. Mode=TwoWay}" IsEnabled="{Binding IsCameraChooserEnabled}" Minimum="0" Maximum="1"/> </StackPanel> </Grid> A CameraBrush háttérnek való bekötésével festjük fel a pillanatnyi képet a Canvas felületére. akkor a projekt telepítése után a 6-17 ábrán látható elrendezést fogjuk látni. A Slider lesz az a vezérlő. RoutedEventArgs e) { ViewModel.TakePhoto(). amellyel a kamerák között válthatunk.ColumnDefinitions> <!--ContentPanel . amennyiben az IsCameraChooserEnabled tulajdonság true értéket tartalmaz. hogy az adatkötés kétirányú legyen. Mivel a ViewModel megvalósítja a műveletet.

hogy a kapott képpel kezdjünk is valamit. például tároljuk el a készülék médiatárában. ahol korábban már egy // TODO: mentés megírása sort hagytunk. amiből tudhatjuk. A mentés helye a CaptureImageAvailable eseménykezelő. majd a feldolgozás végén egy üzenetablakban kapunk értesítést a feladat befejeződéséről (6-18 ábra). amikor a kép már elkészült. ezért hivatkozzunk erre a dll-re projektünkben! A tárolás szintén a ViewModel dolga.Framework szerelvény része.Frameword dll! MediaLibrary library = new MediaLibrary(). ezt cseréljük most ki az alábbiaknak megfelelően: 160 . Az osztály a Microsoft. A mentés akkor történjen. 6-18 ábra: Értesítés a feldolgozás befejeződéséről Már csak annyi maradt hátra. de a felhasználó számára még nem küldtük el az értesítést erről! Így hibakezelésre is lehetőségünk van − de ettől most eltekintünk. Kép készítésekor a gomb egy időre inaktívvá válik.Xna. Alapvető telefonos funkciók használata 6-17 ábra: A kamerák képét mutató alkalmazás felülete A slider értékének megváltoztatását követően a téglalap irányt vált. amelyen keresztül hozzáférhetünk a telefonon tárolt zenékhez és képekhez. hogy a kamera váltása megtörtént.6.Xna. Ehhez egy MediaLibrary példányra lesz szükségünk. így a MediaLibrary típusú library objektumot a CameraViewModel osztályban deklaráljuk: // Microsoft.

e. megkülönböztetve a visszatérési értéket is szolgáltató choosereket és a csupán feladatindítást kínáló launchereket. amelyek egyszerű hozzáférést biztosítanak a telefon valamely funkciójához. Ezt követően megnéztük a partner. Összefoglalás A fejezet során rengeteg olyan lehetőséggel ismerkedtünk meg.Összefoglalás Camera. A funkció működését a fejezet korábbi részeiben bemutatott PhotoChooserTask segítségével ellenőrizhetjük. }).ImageStream).SavePictureToCameraRoll(name.jpg". az előlapon lévő kamera képét ugyanis egy bal oldalra mutató sárga pötty. }.CaptureImageAvailable += (s. 6-19 ábra: A kamerák által készített képek Az emulátor ezeknél a képeknél is különbséget tesz a két eszköz között. // mentés a médiatárba library. Végigvettük az erre kínált taszkokat.Current. míg a hátlapon lévőét egy felfelé mutató jelképezi. Deployment. 161 . e) => { string name = DateTime. Az én emulátoromon például a 6-19 ábra művészeti remekművei készültek.Show(name + " mentve!"). // újra fotózhatunk IsPhotoEnabled = true.Dispatcher. A fejezet végén pedig egy példaalkalmazás írásán keresztül láthattuk.és naptárbejegyzési adatok elérésére megoldást kínáló egyéb lehetőségeket is a PhoneDataSharingContext használatával.Now.BeginInvoke(() => { // visszajelzés küldése (UI szál) MessageBox. hogy hogyan tudunk a taszkoknál közvetlenebb módon hozzáférni a kamerákhoz és azok képét a médiatárban rögzíteni.ToShortTimeString() + ".

.

Az esemény kiváltásának helyét a GetPosition metódussal kérdezhetjük le. amely ma már elengedhetetlen része okostelefonjainknak. Alapvető érintési események Ezeknek az eseménynek a kezelői egy GestureEventArgs típusú paraméterrel rendelkeznek. a Hold. amit a UIElement osztályon definiáltak. Minél mélyebb szinten programozunk. Akkor következik be. lemehetünk egy szinttel mélyebbre a Manipulation eseményekhez. hogy lekérdezhető belőle az esemény bekövetkezésének helye. mely – azonfelül. Bár ma teljesen természetesnek számít. Ez az érintőképernyő − kétségkívül a legfontosabb szenzor. Ebben a fejezetben azt vizsgáljuk. Tegyük hozzá: elég gyakran még ez az információ sem érdekes. amikor a felhasználó megérinti egy elem felületét – tulajdonképpen ez a kattintás megfelelője az érintőképernyőn. hogy ott van a telefonban. Ez akkor következik be. amikor a felhasználó megérint egy vizuális elemet. illetve OriginalSource tulajdonságokat – tulajdonképpen csak annyi hasznos információval szolgál. Attól függően. ehhez a vizuális elemhez képest adja vissza az érintés pozícióját.FrameReportedig. és amelyet a felhasználó lassan már anélkül használ. A harmadik érintési esemény. a Touch. hogy ismerik a RoutedEventArgs leszármazottakra jellemző Handled. Ebbe a kategóriába három esemény tartozik: 7-1 táblázat: Érintési események Esemény Tap Leírás A Tap esemény akkor következik be. mint a Tap (érintés) és társai. hogy egyáltalán észrevenné azt. További telefonos funkciók használata Eddig jobbára a telefon szoftveres képességeivel játszottunk. hanem kb. amely egy UIElement típusú paramétert vár. és ennek az érintés miatt értelme sincsen. néhány évvel ezelőtt még ritkán építették bele. hogyan tudjuk kihasználni a Windows Phone 7. azzal a különbséggel. figyelhetünk az egyszerű eseményekre. bonyolultabb algoritmusokat építhetünk az eseményekre. vagyis érzékelőket. A Silverlight for Windows Phone több szinten teszi elérhetővé a fejlesztő számára az érintőképernyő eseményeit. most azonban egy kicsit mélyebbre hatolunk. hogy Tap esetén nem lehet megkülönböztetni bal/jobb egérgombot és egyéb egérre jellemző tulajdonságokat. Az érintőképernyő kezelése Elsőként azzal az érzékelővel foglalkozunk. de ujját nem emeli fel.7. Szintén a UIElementből származó vezérlőkön és vizuális elemeken értelmezett a DoubleTap esemény. annál pontosabb. vagy a legmélyebb szintre. ahol a nyers adatokkal dolgozhatunk. de annál több munkánk is lesz vele. egy másodpercig rajta hagyja az elemen.5 operációs rendszert futtató telefonokba alapfelszereltségként beépített szenzorokat. hogy milyen bonyolultan szeretnénk hozzáférni. amikor a felhasználó rövid időn belül kétszer megérinti egy vizuális elem felületét. hogyan lehet felhasználni ezeket az eseményeket! 163 . DoubleTap Hold Lássuk.

</Rectangle> Ezután már csak fel kell iratkozni a Tap eseményre – ezt a szokásos módon tehetjük meg: <Rectangle x:Name="rect" Width="100" Height="100" Fill="{StaticResource PhoneAccentBrush}" Tap="rect_Tap" RenderTransformOrigin=".0. } Teszteljük le az alkalmazást! A négyzet nyomkodás hatására forog (7-1 ábra). További telefonos funkciók használata Készítsünk egy Windows Phone Application sablonra épülő alkalmazást.Row="1" Margin="12. vagy ha több különálló transzformációra lesz szükségünk. </Rectangle> A mögöttes kódban pedig csak módosítanunk kell az előbb létrehozott transzformáció Angle tulajdonságát.5. hogy az egyes tengelyeken hol helyezkedjen el a középpont. hogy hogyan tudunk ilyen transzformációt létrehozni XAML-ben: <Rectangle x:Name="rect" Width="100" Height="100" Fill="{StaticResource PhoneAccentBrush}"> <Rectangle. amit állítgathatunk.. hogy az Angle-t lássuk: private void rect_Tap(object sender. Az alábbi kód szemlélteti. 164 .RenderTransform). hogy elhelyezzünk a négyzetben egy transzformációt. hogy átállítjuk a Rectangle RenderTransformOrigin tulajdonságát. hogy mennyivel kell elfordulnia az elemnek a RenderTransformOriginben megadott pont körül. Ez fokokban adja meg. Forgatásra a RotateTransform a legmegfelelőbb.5"> ...0"> <Rectangle x:Name="rect" Width="100" Height="100" Fill="{StaticResource PhoneAccentBrush}" /> </Grid> A megoldandó feladat annyi. és helyezzünk el benne −konkrétan a ContentPanel nevű Gridben − egy négyzetet! <Grid x:Name="ContentPanel" Grid.12. GestureEventArgs e) { ((RotateTransform)rect... Itt 0 és 1 között relatívan adhatjuk meg. hogy tapintásra a négyzet forduljon el középpontja körül 10 fokkal jobbra! Ehhez arra lesz szükség.RenderTransform> <RotateTransform Angle="0"/> </Rectangle.. Természetesen a RenderTransform tulajdonság nem RotateTransform típusú – elvégre 5-6 másik transzformáció-típust is tudnia kell fogadni –. Ezt úgy tudjuk átállítani az elem középpontjára.Angle += 10. de alkalmazhatunk CompositeTransformot. így át kell alakítanunk.RenderTransform> </Rectangle> A forgatás alapesetben a vizuális elem befoglaló négyzetének bal felső sarka körül történik.5. <Rectangle x:Name="rect" Width="100" Height="100" Fill="{StaticResource PhoneAccentBrush}" RenderTransformOrigin=". A transzformációt a UIElement RenderTransform tulajdonságán keresztül tudjuk beállítani. TransformGroupot is.5"> .7.

akkor elfordul a négyzet. hogy a négyzet nyomva tartása (Hold) esetén a négyzet nagyobbra nőjön. Így megkímélhetjük magunkat a sok típuskonverziótól.. rect.Az érintőképernyő kezelése 7-1 ábra: A Tap esemény hatása Ha egy transzformációt gyakran akarunk a mögöttes kódban használni.5"> . } Tesztelésnél látható.5.. GestureEventArgs e) { rect.Width += 20. ha adunk neki egy nevet az x:Name tulajdonságon keresztül. két gyors egymás utáni tapintás (DoubleTap) pedig alaphelyzetbe állítsa! Iratkozzunk fel a Hold eseményre! <Rectangle x:Name="rect" Width="100" Height="100" Fill="{StaticResource PhoneAccentBrush}" Tap="rect_Tap" Hold="rect_Hold" RenderTransformOrigin=". </Rectangle> Az eseménykezelőben növeljük meg a négyzet méretét! private void rect_Hold(object sender. egyszerűbb. (Emellett persze továbbra is működik a Tap..Height += 20. tehát ha 1 mp-en belül felengedjük az ujjunkat. Oldjuk meg azt is.) 7-2 ábra – A Hold (és a Tap) esemény hatása 165 . hogy a Hold esemény hatására a négyzet 20-20 képpontonként nő.

Ehhez nem kell több ujját használnia – már egy érintéstől is kiváltásra kerül az esemény. } Multitouch manipulációk Az előző események egyetlen ujj érintését jelzik vissza felénk. További telefonos funkciók használata A DoubleTap megoldása is az előbb leírtakat követi.. Itt is három eseményt találunk: 7-2 táblázat: Manipulation események Esemény ManipulationStarted Leírás A ManipulationStarted esemény akkor következik be. rect. hogy előre megfontolt szándékkal egyszerre több ujjával is megérintse a kijelzőt. hanem a ManipulationCompleted esemény fut majd le. hogy mely objektumhoz viszonyítva történik a manipuláció (ez maga a manipulált objektum). az operációs rendszer lezártnak tekinti a manipulációt. Először is fel kell iratkozni az eseményre: <Rectangle x:Name="rect" Width="100" Height="100" Fill="{StaticResource PhoneAccentBrush}" Tap="rect_Tap" DoubleTap="rect_DoubleTap" Hold="rect_Hold" RenderTransformOrigin=".Angle = 0.RenderTransform). Ennek egyik paramétere egy ManipulationStartedEventArgs típusú objektum. Ennek ManipulationContainer tulajdonsága megadja.Height = 100.7. tehát ha a felhasználó továbbra is a kijelzőn tartja ujját. amit megnyomtak. Az események második szintje a többpontos (multitouch) érintések kezelését is lehetővé tevő úgynevezett Manipulation események csoportja. GestureEventArgs e) { rect.5.5"> <Rectangle. így elviekben semmi nem gátolja a felhasználót abban. Ha ezt meghívjuk. 166 . hogy szintén a ManipulationStartedEventArgs része a Complete metódus.RenderTransform> <RotateTransform Angle="0"/> </Rectangle. illetve a ManipulationOrigin tulajdonság.Width = 100. A Windows Phone-nal felszerelt telefonokban alapkövetelmény a legalább négy érintési pontot kezelni képes kapacitív kijelző. ((RotateTransform)rect. Készítsük be a telefont. ha többérintéses eseményeket szeretnénk tesztelni – az emulátor nem támogatja a több érintést.RenderTransform> </Rectangle> Ezután a mögöttes kódban vissza kell állítani alaphelyzetbe az előzőleg megváltoztatott három tulajdonságot: private void rect_DoubleTap(object sender. nem a ManipulationDelta. Hasznos lehet még tudni. amikor a felhasználó megérinti a kijelzőt. ami a manipulálás indításakor a ManipulationContainer bal felső sarkához viszonyított pozíciót adja meg – tehát hogy hol nyomták meg az elemet.

melyből az ujjak egymástól való távolodásának (ExpansionVelocity) és az eltolásnak a (LinearVelocity) sebességét kaphatjuk meg. A különbség a CumulativeManipulation és a DeltaManipulation között.12. amelyek a korábban ismertetettel egyező működésűek. FinalVelocities tulajdonságával pedig azt mutatja. Ennek Scale tulajdonságából megkapjuk azt. hogy előbbi a manipuláció kezdete óta összegyűlt eltéréseket mutatja. ManipulationDelta típusú tulajdonságon keresztül adja tudtunkra. hogy a manipuláció kezdete óta mekkora eltolás és átméretezés történt. Típusuk megegyezik: ManipulationDelta. míg utóbbi csak annak változását. hogy a több ujj arányában mennyit távolodott egymástól vagy közeledett egymáshoz. amely a több ujj által kifejtett manipulációt összegzi. Amikor az utolsó ujj is elhagyja az érintőképernyőt. Említésre méltó ezenfelül a ManipulationDeltaEventArgs Velocities tulajdonsága. Ennek ManipulationCompletedEventArgs típusú paramétere egy TotalManipulation nevű.0. magát a ContentPanelt pedig módosítsuk Gridről Canvas típusúra! <Canvas x:Name="ContentPanel" Grid.0"> <Border Name="brd" Width="100" Height="100" BorderBrush="BlanchedAlmond" Background="{StaticResource PhoneAccentBrush}" /> </Canvas> Az átméretezést egy ScaleTransform segítségével szeretnénk végrehajtani – egészítsük ki ezzel a Bordert! 167 . hogy mennyit tolódott el az ujjak által kijelölt középpont. vagyis amíg legalább egy ujj érinti a kijelzőt.Az érintőképernyő kezelése Esemény ManipulationDelta Leírás A manipuláció időtartama alatt. illetve Complete metódust. vagyis a legutóbbi ManipulationDelta esemény óta történt elmozdulást. hogy az utolsó ujj felemelésekor milyen sebességű volt az átméretezés és eltolás. vagyis lehetővé tegyük. Emellett pedig a felhasználó két ujjának közelítésével vagy távolításával képes lesz növelni és csökkenteni a négyzet méretét. a ManipulationCompleted eseményt jelzi a rendszer. A Windows Phone Application sablon alapján készített alkalmazás MainPage lapjának ContentPaneljébe ezúttal egy Bordert helyezzünk el. hogy a felhasználó ujjmozdulatok segítségével húzzon arrébb egy objektumot a felületen. ManipulationCompleted A következőkben arra fogjuk felhasználni ezt a három eseményt. a ManipulationDelta eseményt kaphatjuk el.Row="1" Margin="12. Ezenkívül két talán legfontosabb tulajdonsága a CumulativeManipulation és a DeltaManipulation. hogy egy „Drag” műveletet hajtsunk végre. Ennek ManipulationDeltaEventArgs paramétere szintén tartalmaz egy ManipulationContainer és egy ManipulationOrigin tulajdonságot. Translation tulajdonságából pedig.

amelyen használjuk). Ennek Translation tulajdonsága egy X és egy Y értékkel adja meg.Translation.RenderTransform> </Border> </Canvas> Iratkozzunk fel a három Manipulation eseményre a Borderen! <Border Name="brd" Width="100" Height="100" BorderBrush="BlanchedAlmond" Background="{StaticResource PhoneAccentBrush}" ManipulationStarted="brd_ManipulationStarted" ManipulationDelta="brd_ManipulationDelta" ManipulationCompleted="brd_ManipulationCompleted"> .TopProperty. nem összeadunk. ManipulationDeltaEventArgs e) { brd. vagyis az ujjak elmozdulását jelző esemény kezelőjének megírása ennél kicsit bonyolultabb. hogy hány képponttal kell arrébb mozgatnunk a Bordert.DeltaManipulation. Csak egy-egy sor nem túl bonyolult C#-kódra lesz szükségünk: private void brd_ManipulationStarted(object sender. Itt a Borderbe ágyazott ScaleTransform objektum ScaleX és ScaleY tulajdonságát állítgatjuk.Translation.Left és Canvas. ManipulationStartedEventArgs e) { brd. a végén pedig ismét eltüntetjük.7. Mivel arányokról van szó (az esemény argumentuma azt adja meg.DeltaManipulation. Külön kell kezelnünk a 168 . nem közvetlenül a Borderen találjuk.Y *st. amelyet nem az az objektum definiál.0"> <Border Name="brd" Width="100" Height="100" BorderBrush="BlanchedAlmond" Background="{StaticResource PhoneAccentBrush}" RenderTransformOrigin=". brd.TopProperty) + e.BorderThickness = new Thickness(0).0. (double)brd..LeftProperty) + e. hanem a GetValue és SetValue metódusok segítségével kérhetjük le.Row="1" Margin="12. } Mivel minden egyes elmozduláskor szeretnénk az előző pozícióhoz képest elmozdítani a vizuális elemet. ManipulationCompletedEventArgs e) { brd. melyik objektum változik.ScaleY). } A ManipulationDelta.Top tulajdonságainak változtatásával állítjuk – vagyis a Bordert az őt tartalmazó Canvas bal felső sarkához képest mozgatjuk. Mivel ez a tulajdonság ún..RenderTransform> <ScaleTransform x:Name="st" /> </Border. hanem az előbb említett tulajdonságokat felszorozzuk a megfelelő skálázási komponenssel.SetValue(Canvas.GetValue( Canvas. } private void brd_ManipulationCompleted(object sender.12.GetValue( Canvas. Hasonló módon valósíthatjuk meg a többujjas átméretezést.BorderThickness = new Thickness(5).ScaleX). attached property (csatolt tulajdonság. Az eltolást a brd nevű Borderünk Canvas.LeftProperty. További telefonos funkciók használata <Canvas x:Name="ContentPanel" Grid.5"> <Border.X * st.5. hogy ha mozgatja ujjait. Első körben csak az elmozdítást (vagyis a „Drag” effekt megvalósítását) nézzük meg. </Border> A manipuláció indulásakor és végén vizuális visszajelzést akarunk adni a felhasználónak arról. (double)brd. hogy a korábbi hányszorosára nőtt a méret). a DeltaManipulationt vesszük igénybe. illetve állíthatjuk be: private void brd_ManipulationDelta(object sender. Induláskor láthatóvá tesszük a Border keretét..SetValue(Canvas.

csak FrameReported eseményeket kapunk. hogy pontosan mi is történik az érintőfelületen.ScaleX). } Ennyi az egész.Translation. ManipulationDeltaEventArgs e) { brd. hogy a magasabb szintű eseményeket is feldobja a rendszer. A GetPrimaryTouchPoint az elsődleges érintési pontot adja vissza – amelyik legkorábban megérintette a képernyőt. Bármilyen változás történik az érintőfelületen – egy ujj megérinti a képernyőt. mindenképpen szükségünk lesz egy telefonra is (7-3 ábra). amelyekkel követhetjük az ujjak pillanatnyi állapotát. Amíg minden ujj el nem engedi a kijelzőt. stb. mélyebb szintű adatokra van szükségünk.SetValue(Canvas.X * st. amikor az ujjak közötti távolság nem változna érzékelhető mértékben.DeltaManipulation. különben a négyzet eltűnne. ez a FrameReported. –. vagyis ki tudjuk rángatni a Bordert a Canvasról! Ha az átméretezés működését is tesztelni szeretnénk.Scale. if (e. (double)brd. Egyetlen tulajdonsága a TimeStamp nevű integer.DeltaManipulation. 7-3 ábra: A négyzet.LeftProperty) + e. A Touch.ScaleX *= e.TopProperty) + e. melynek segítségével az események egymástól való időben egymástól való távolságát mérhetjük le.X.GetValue( Canvas. amikor pontosabb.FrameReported esemény A Touch osztály csupán egyetlen eseménnyel bír. (double)brd.Scale. Gyakran ez elég is.Y *st.Translation. magasabb szinten nem támogatott ujjmozdulat kezelése megvalósítható. private void brd_ManipulationDelta(object sender. Mindkét metódus egy UIElement paramétert vár: ehhez az elemhez képest adja vissza a pontokat. brd.DeltaManipulation. amelyek leírják. kapunk róla egy FrameReported eseményt. a TouchFrameEventArgs osztály SuspendMousePromotionUntilTouchUp metódusának meghívásával érhetjük ezt el.DeltaManipulation.DeltaManipulation. akad azonban olyan szituáció. hogy az elmozdítás történhet a Canvashoz képest akár negatív irányba is. elmozdul.Az érintőképernyő kezelése nulla átméretezés esetét: ki kell szűrni.Y != 0) st.SetValue(Canvas. hogy a több ujj elmozdulásából mit számoltak ki.ScaleY). a Manipulation események segítségével jó néhány.LeftProperty. Ennek eseményargumentuma TouchFrameEventArgs típusú.DeltaManipulation.GetValue( Canvas. a program tesztelhető! Figyeljük meg.TopProperty. eredeti pozíciójából elmozgatva A nyers érintési adatok kezelése Ahogy láthattuk. if (e. 169 .X != 0) st.Scale.Y. Azonban ekkor nem férünk hozzá a részletekhez. Ha ki akarjuk kapcsolni. A TouchFrameEventArgs két olyan metódust biztosít.ScaleY *= e. Ekkor siet segítségünkre a Touch osztály. Az események csak annyit közölnek velünk. A GetTouchPoints az összes aktuális érintési pontot visszaadja.Scale.

amelyet kézzel írunk meg.FrameReported += new TouchFrameEventHandler(Touch_FrameReported). Ezt például a MainPage konstruktorában tehetjük meg: public MainPage() { InitializeComponent().0.GetTouchPoints(ContentPanel). Ezzel tudjuk megkülönböztetni. a Colors felsorolt típus tulajdonságainak megszámlálásával visszaadunk egy színt az integer értékből. majd ahogy mozgatja az ujját a kijelzőn. Emellett persze az egyazon ujjhoz tartozó körök mindig ugyanazzal a színnel jelennek meg. } Ezután menjünk végig az érintési pontokon! Először azokat kezeljük. hogy hol történt az esemény. kisebb köröket. A TouchDevice tulajdonság kicsit félrevezető nevű: nem az érintést kiváltó eszközt azonosítja (hiszen az mindig ugyanaz lenne).Count(). } Ezután hozzuk létre az eseménykezelő metódust. hogy mekkora a lenyomott felület. További telefonos funkciók használata Az előbbi metódusok visszatérési típusa TouchPoint. /// </summary> public static class IntColorConversion { static int colorscount = 0. hogy az egyes TouchPointok mely ujjhoz tartoznak.GetProperties(). A Windows Phone Application sablonnal létrehozott alkalmazás MainPage.0"></Canvas> A mögöttes kódban először is fel kell iratkoznunk a Touch osztály FrameReported eseményére. A Position tulajdonság megadja. hogy éppen milyen esemény történt az adott ponton.Windows. a Size pedig. de minden ujjé mással. } 170 . Touch. az ahhoz az ujjhoz tartozó köröket eltüntetjük. Ennek három értéke lehet: Down (érintés). illetve TouchPointCollection. Amikor a felhasználó megérinti a képernyőt. hanem az érintést kiváltó ujjat. de több érintést kezelő rajzprogram létrehozásához. mindezt egy bővítő függvénnyel: using System. Minimális Reflectionnel. és kérjük le benne az érintési pontokat a ContentPanel (a Canvasunk) bal felső sarkához képest! void Touch_FrameReported(object sender. Amikor egy ujját felengedi.Media. Rajzoljunk egy 50*50 képpont méretű kört a lenyomás helyén! A színt egy kis segédosztállyal választjuk ki.Linq. Move (elmozdulás) és Up (felengedés). A TouchPoint típusú objektumok Action tulajdonsága megadja.xaml fájljában cseréljük le a ContentPanel típusát Canvasra! A XAML-ben ezzel el is végeztük minden dolgunkat: <Canvas x:Name="ContentPanel" Grid. namespace LowLevelTouch { /// <summary> /// Integerek színné alakítása.Row="1" Margin="12. Ennyi alapozás után már csak egy kis logika kell egy faék egyszerűségű. using System.7.12. TouchFrameEventArgs e) { var pts = e. egy nagyobbacska kört jelenítünk meg az ujja alatt. amelyek újak. vagyis ahol éppen megérintették a képernyőt! Ezt az Action tulajdonság Down értéke jelzi. static IntColorConversion() { colorscount = typeof(Colors).

el.Add(el). Height = 20. hozzárendelni az elemhez. amikor szeretnénk valamilyen.GetTouchPoints(ContentPanel).Action == TouchAction.TopProperty. Fill = new SolidColorBrush(p.GetTouchPoints(ContentPanel).TouchDevice. } } } Ez után a kis kitérő után már meg tudjuk írni a kört létrehozó kódot.GetProperties()[id + 1 % colorscount] . Height = 50.Position.SetValue(Canvas. p. A Move Action értékkel rendelkező elemek pozíciójára egy-egy kisebb kört rajzolunk: void Touch_FrameReported(object sender. ContentPanel.Children. el.ToColor()) }. ContentPanel.Position. a vizuális elemhez kapcsolódó adatot.SetValue(Canvas.SetValue(Canvas.Add(el).Down) { Ellipse el = new Ellipse { Width = 50. foreach (TouchPoint p in pts) { if (p.Down) { Ellipse el = new Ellipse { Width = 50.Move) { Ellipse el = new Ellipse { Width = 20.SetValue(Canvas.Y .10).Position. null).GetValue(null.Add(el). Fill = new SolidColorBrush(p.25).25). Tag = p. objektumot eltárolni. Height = 50.TopProperty.Children. } } } 171 . p. el. p. ContentPanel.ToColor()) }.TouchDevice. TouchFrameEventArgs e) { var pts = e.TopProperty.Id. illetve ne felejtsük el megjeleníteni a kört azzal.TouchDevice.Action == TouchAction.ToColor()) }.Y .Position. Tag = p. p. Két apróságra ügyeljünk: tároljuk el az újonnan létrehozott kör Tag tulajdonságában a TouchDevice. } } } A Tag tulajdonság igazi funkcióval nem rendelkezik – pont olyan helyzetekre készült. } else if (p. Tag = p.TouchDevice.TouchDevice.Id. TouchFrameEventArgs e) { var pts = e. A már korábban a kijelzőn lévő ujjak további útjának kirajzolása hasonló elven történik.X .X .Id-t.Id.Position.Id.Id.Position. p.SetValue(Canvas.LeftProperty.LeftProperty.Action == TouchAction.TouchDevice. p.25). el.Y . el. Fill = new SolidColorBrush(p.Id.10).X . el.LeftProperty.Az érintőképernyő kezelése public static Color ToColor(this int id) { return (Color)typeof(Colors).Children. foreach (TouchPoint p in pts) { if (p.SetValue(Canvas. hogy hozzáadjuk a ContentPanel gyermekelemeihez! void Touch_FrameReported(object sender.25).

TouchFrameEventArgs e) { var pts = e.GetTouchPoints(ContentPanel). el.Id. p. akkor persze mindenképpen telefonon kell tesztelnünk (7-4 ábra). tesztelhető.ToColor()) }.Position.SetValue(Canvas. el.SetValue(Canvas.25).SetValue(Canvas.TouchDevice.Action == TouchAction.TouchDevice. További telefonos funkciók használata Az utolsó lépés. p. el.LeftProperty. hogy amikor egy Action az Up értéket vette fel. Fill = new SolidColorBrush(p. void Touch_FrameReported(object sender.Add(el). p. Ezért tároltuk el az Ellipse-ek Tag tulajdonságában a TouchDevice. } } } Az alkalmazás kész. Tag = p. ahol korábban megfordult.Y .Y . Height = 50. Tag = p.Remove(el).X .Action == TouchAction.Children. ContentPanel. Ha több színt is szeretnénk látni. és amelyiknek a Tag értéke megegyezik az aktuális Taggel.Children.Move) { Ellipse el = new Ellipse { Width = 20.Up) { var q = (from item in ContentPanel. Csupán annyi a dolgunk.ToColor()) }.Id.Action == TouchAction.TouchDevice.Down) { Ellipse el = new Ellipse { Width = 50.LeftProperty.Add(el).TopProperty. Fill = new SolidColorBrush(p. törlünk minden pontot.TouchDevice.10).Position.TouchDevice. p.Id. } else if (p. el.SetValue(Canvas. Height = 20.Children.Tag == p.X .25).10). ContentPanel.Children where item is Ellipse && (int)((Ellipse)item).ToList().Position. foreach (TouchPoint p in pts) { if (p. azt töröljük. } else if (p.7. végigszaladjunk a Canvasban lévő Ellipseeken.Id-t. foreach (Ellipse el in q) ContentPanel.Id.Id select item as Ellipse). 7-4 ábra – Nem Imagine Cup logó 172 .Position. hogy amikor egy ujjbegy elereszti a kijelzőt.TopProperty.

illetve több energiát fogyaszt. hiszen például a cellainformáció keresése csupán az amúgy is bekapcsolt állapotban lévő mobilrendszert veszi igénybe. Jó tudni: Ha a teljesítmény is szempont. Ez adja meg. Hacsak nem kér a program nagy pontosságú helymeghatározást. a telefon csak a legvégső esetben nyúl a GPS-hez. A GPS lassabban áll be.RowDefinitions> <Grid. méterben mért távolságra kerültünk az előző eseményben rögzített pozíciótól. mikor történt a mérés).com/enus/library/ff967560(v=VS.12. merre tart (Course) és milyen gyorsan halad ebbe az irányba (Speed).0"> <Grid. a körök elszakadhatnak egymástól! Ez azt mutatja. amikor a MovementThreshold tulajdonságban beállított.0. A helymeghatározás azonban ennél jóval többet jelent.aspx#BKMK_UserInput Az érintőképernyő felhasználási módjainak megismerése után hatoljunk be az eszközök belsejébe! Helymeghatározás A Windows Phone-telefonok alapfelszereltségének része egy Assisted GPS. valamint egy Location tulajdonságot. mely esemény-réteget használjuk fel. hogy ha nagyon gyorsan rajzolunk. ismert wifi-pontok alapján határozza meg a helyzetet. Ez a tulajdonság csak lekérdezhető. ha előzőleg meghívtuk a GeoCoordinateWatcher Start metódusát (és a Stopot még nem). és keveset fogyaszt. A PositionChanged eseményt akkor dobja fel egy GeoCoordinateWatcher objektum. Amikor a Windows Phone-on egy alkalmazás igénybe veszi a helymeghatározást. Fontos tulajdonság még a DesiredAccuracy. A GeoCoordinate egy példányából kinyerhetjük a helymeghatározás vízszintes és függőleges pontosságát (HorizontalAccuracy és VerticalAccuracy tulajdonságok).Helymeghatározás Vegyük észre. valamint természetesen a hosszúsági és szélességi értékeket (Longitude és Latitude tulajdonságok). Az esemény csak akkor kerül kiváltásra.microsoft. hogy igénybe veszi-e a GPS-t a telefon.92). hogy a tengerszinthez képest milyen magasságban van a telefon (Altitude tulajdonság). az operációs rendszer először a cellainformációk és az esetleg elérhető. hogy nem méterre pontos. mint ahogy a 60Hz frissítésű panel követni tudta volna. de általában elég – cserébe pedig gyors. A PositionChanged esemény második argumentuma GeoPositionChangedEventArgs<GeoCoordinate> típusú. mely egy Timestampet tartalmaz (egy DateTimeOffset. vagyis. Kicsit bonyolultabb algoritmusokkal (legutolsó érintési pontok eltárolása.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> 173 . Line-ok használata) ez is kiküszöbölhető. Ezenfelül pedig információt szolgáltat arról is. Ennek egyetlen tulajdonsága Position típusú. A GeoCoordinateWatcher osztályon keresztül nyerhetjük ki a szükséges információkat a telefonból. bár tény.RowDefinitions> <RowDefinition Height="80" /> <RowDefinition Height="80" /> <RowDefinition Height="80" /> <RowDefinition Height="80" /> </Grid. hogy gyorsabban húztuk végig ujjunkat a kijelzőn. érdemes elgondolkodnunk rajta. hogy mennyire pontos a helymeghatározás. ami megmondja. mely lehetővé teszi a Föld körül keringő GPS műholdak által a telefon pontos helyének meghatározását. hiszen meg kell találnia 3-4 műholdat. Hozzunk létre egy alkalmazást a Windows Phone Application sablonnal! A MainPage ContentPanel Gridjét töltsük fel néhány elemmel az alábbi módon: <Grid x:Name="ContentPanel" Grid. mely GeoCoordinate típusú. Ez.Row="1" Margin="12. A helymeghatározás használata nagyon egyszerű. de a GeoCoordinateWatcher konstruktorában be is állíthatjuk (két értéke: Default és High). A Microsoft ajánlása ezzel – és a telefon más teljesítményigényes alkalmazásainak helyes használatával – kapcsolatban az alábbi linken érhető el: http://msdn.

állítsuk le a figyelőt. és indítsuk el a figyelőt! Végül pedig állítsuk át a gomb szövegét! A null értéket tesztelő elágazás else ágában iratkozzunk le az eseményről. A MainPage-ben hozzunk létre egy GeoCoordinateWatcher referenciát! Ha a XAML-tervező nem hozta létre automatikusan. ezt adjuk hozzá a projekt referenciáihoz.High : GeoPositionAccuracy.Device. majd ezek után vegyük fel a System.Location névteret! using System. akkor írjuk meg az egyelőre üres Click-kezelő metódust is! public partial class MainPage : PhoneApplicationPage { GeoCoordinateWatcher gcw = null. ha még null értékű a gcw referenciánk.Default).Row="3" Grid. 174 . szükségünk lesz a System. public MainPage() { InitializeComponent().Column="1" /> <TextBlock Name="tbkTimeStamp" Grid. } private void btnGetCoordinates_Click(object sender. és írjuk vissza a gomb feliratát! public partial class MainPage : PhoneApplicationPage { GeoCoordinateWatcher gcw = null.Column="1" /> <Button Name="btnGetCoordinates" Content="Indítás" Click="btnGetCoordinates_Click" Grid. RoutedEventArgs e) { } } Ezután a gomb eseménykezelőjében.Device dll-re.7.Row="3" /> <CheckBox Name="cbHighAccuracy" Content="Nagy pontosság" Grid.ColumnDefinitions> <TextBlock Name="tbkLat" /> <TextBlock Name="tbkLong" Grid. hozzunk létre egy GeoCoordinateWatcher példányt.Row="1" /> <TextBlock Name="tbkVertAccu" Grid.Column="1" /> <TextBlock Name="tbkHorAccu" Grid.Column="1" /> </Grid> Ahhoz.Location. hogy a felhasználó bekattintotta-e az erre vonatkozó jelölőnégyzetet! Írjunk fel egy metódust a PositionChanged eseményre. public MainPage() { InitializeComponent().IsChecked ? GeoPositionAccuracy.Row="2" /> <TextBlock Name="tbkSpeed" Grid. További telefonos funkciók használata </Grid.Row="1" Grid.Device. } private void btnGetCoordinates_Click(object sender. szabadítsuk fel azt.Row="2" Grid. RoutedEventArgs e) { if (gcw == null) { gcw = new GeoCoordinateWatcher((bool)cbHighAccuracy. a pontosságot attól függően állítsuk be. hogy a Geolocation API-t felhasználhassuk.

hogy amikor a gcw feldobja az eseményt.DateTime.Text = e.Latitude.Text = e.PositionChanged -= gcw_PositionChanged.Text = e.Position.Position. gcw. tbkSpeed. megfelelően kezeljük: kiírjuk a kapott adatokat a képernyőre.VerticalAccuracy. } Az alkalmazást – ahogy minden érzékelőket használó alkalmazást – érdemes fizikai eszközön tesztelni. de ha épp nincs kedvünk vagy lehetőségünk rá. } } void gcw_PositionChanged(object sender. tbkTimeStamp.Text = e.Content = "Leállítás". majd itt.Location.Location. az emulátor is megfelelhet. tbkVertAccu.ToString() + " m". 175 . Az elindított emulátor mellett látható dupla nyílra (7-5 ábra) kattintás hatására megjelenő ablakban válasszuk a Location fület. } else { gcw.Position. void gcw_PositionChanged(object sender. gcw. amit az emulátornak végig kell járnia! 7-5 ábra – Az Additional Tools megnyitása Ha megvannak a pontok.Content = "Indítás". kapcsoljuk ki a fent látható „Live” gombot. btnGetCoordinates. GeoPositionChangedEventArgs<GeoCoordinate> e) { tbkLat.Position.Speed + " m/s".ToString().Location.Helymeghatározás gcw. és kattintsunk a lejátszásra! Ha az emulátorban elindítottuk a GeoCoordinateWatchert.Longitude.Location.Text = e.ToString(). GeoPositionChangedEventArgs<GeoCoordinate> e) { } } Már csak annyi dolgunk maradt.Timestamp. láthatjuk.Position.Dispose().Location.Start(). gcw.ToLongTimeString(). tbkHorAccu.PositionChanged += gcw_PositionChanged. a térképre kattintgatva jelöljük ki a pontokat.Position.Text = e. tbkLong. btnGetCoordinates.Stop().ToString() + " m". ahogy változnak a koordináták a szimuláció közben (7-6 ábra).HorizontalAccuracy.

hogy elérhető-e a gyorsulásmérő. Ez nemcsak a helymeghatározó. illetve egy Acceleration nevűt. közelségi szenzort. amelyben az X. További telefonos funkciók használata 7-6 ábra – A felvett útvonal lejátszása Ne felejtsük el leállítani az érzékelőket. Y és Z komponenseket érjük el. hogy éppen hogyan tartja és mozgatja a felhasználó – legalább olyan fontos információkkal szolgálhat. és ezt kell eltalálni egy célkereszttel. ha megváltozott az eszköz helyzete – de itt is a Start és a Stop metódusok hívása között történik csak figyelés. A CurrentValueChanged esemény második argumentuma SensorReadingEventArgs<AccelerometerReading> típusú. Ennek SensorReading tulajdonságában egy Timestamp nevű tulajdonságot találunk (DateTimeOffset. Adjunk egy célt és egy célkeresztet ábrázoló képet a projekthez. hanem a helyzetmeghatározó érzékelőkre is vonatkozik. A gyorsulásmérőt az Accelerometer osztályon keresztül érjük el. amelyek jelenítsék meg a képeket. de ezenkívül még lehet bennük iránytű (magnetometer). illetve giroszkóp. A Windows Phone 7-nel szerelt eszközöknek tartalmazniuk kell többek között egy gyorsulásmérőt (accelerometer). jelen könyvben azonban máshol mutatjuk be ezek használatát. melyet a gyorsulásmérő segítségével (vagyis a telefon forgatásával) mozgatunk. Egy kép „ugrál” a képernyőn. érdemes ennek ellenőrzésével kezdeni a munkát.7. hogy milyen irányban hat gyorsulás a telefonra. Helyzetmeghatározás Nem a GPS az egyetlen szenzor. Egy Accelerometer objektum létrehozása után a CurrentValueChanged eseményen keresztül kapunk értesítést arról. a vektor X. hogy mennyi idő telt el az előző mérés óta). majd a MainPage ContentPaneljét alakítsuk át Canvasszá! Helyezzünk el benne két Image vezérlőt. amit elérünk! Telefonunk helyzetének meghatározása – vagyis. amin majd a célba talált lövéseket számláljuk! Ezenfelül pedig iratkozzunk fel a ContentPanel Tap eseményére: 176 . A gyorsulásmérő használata A gyorsulásmérő megadja. Y és Z komponensei is változnak. Néha szokás a szenzorok közé sorolni a kamerát és a mikrofont. Nem mindegyik érhető el ezek közül. A szokásos Windows Phone Application sablonra építve egy egyszerű ügyességi alkalmazást hozunk létre. amikor nincs rájuk szükség! A tökéletes helyek erre az alkalmazás Deactivated és Closing eseményei. Ahogy forgatjuk a telefont. Ennek IsSupported nevű statikus tulajdonsága megmondja. Ez a tulajdonság egyébként a többi érzékelőosztályon is megtalálható. illetve a PhoneApplicationPage-ek OnNavigatedFrom eseménye. mint a helye. tehát alapesetben ez egy a Föld középpontja felé mutató vektor. illetve egy TextBlockot.

CurrentValueChanged += new accel_CurrentValueChanged. SensorReadingEventArgs<AccelerometerReading> e) { } 177 .IsSupported) { accel = new Accelerometer().Show("Nincs gyorsulásmérő. } void accel_CurrentValueChanged(object sender.. GestureEventArgs e) { } } Az Accelerometer a Microsoft.Framework nevű dll-t kell felvennünk a referenciák közé.0" Tap="ContentPanel_Tap"> <TextBlock Name="tbkHits" Text="0" /> <Image Name="target" Source="kenny. majd a usingok közé rakjuk be a hasonló nevű névteret!Ezenfelül még a Microsoft. 5000. int hits = 0. accel. Adjuk hozzá ezt a referenciákhoz. public MainPage() { InitializeComponent(). } else MessageBox. RoutedEventArgs e) { if (Accelerometer. shell:SystemTray. } private void ContentPanel_Tap(object sender.IsVisible="True" Loaded="PhoneApplicationPage_Loaded"> Az eseménykezelőben inicializáljuk az objektumokat. és indítsuk el a gyorsulásmérőt! public partial class MainPage : PhoneApplicationPage { .. 5000).0.MainPage" .Sensors dll -ben található.12. using Microsoft. Accelerometer accel = null.png" /> <Image Name="crosshair" Source="crosshair-red. private void PhoneApplicationPage_Loaded(object sender. Random rand = new Random().Start(). :(").png" /> </Canvas> A célpontot azonos időközönként szeretnénk véletlenszerűen elhelyezni.Helyzetmeghatározás <Canvas x:Name="ContentPanel" Grid.Devices.Xna.Devices.Row="1" Margin="12. tehát egy Timerre és egy Randomra lesz szükségünk – valamint természetesen egy Accelerometerre és egy integerre. accel.Sensors. public partial class MainPage : PhoneApplicationPage { Timer timer = null. amivel számlálunk. timer = new Timer(TimerEvent.. null.. Iratkozzunk fel az oldal Loaded eseményére! <phone:PhoneApplicationPage x:Class="AccelerometerHandling.

GetValue(Canvas.NextDouble() * 600).Acceleration. else if (newLeft > 450) newLeft = 450. double newTop = (double)crosshair. } Ezután ellenőrizzük le.GetValue(Canvas.NextDouble() * 430). ezt kell felszoroznunk a ContentPanel szélességével és magasságával.LeftProperty) + e.SensorReading. mozgassuk a célkeresztet! Mivel a gyorsulásmérő eseménye is háttérszálon fut le. Ha közvetlenül próbáljuk. és írjuk ki a képernyőre az aktuális értéket! private void ContentPanel_Tap(object sender.SetValue(Canvas.LeftProperty)) < 20 && Math.GetValue(Canvas. de mielőtt még ezt megtennénk. kivonva belőle a célkép szélességét és magasságát. SensorReadingEventArgs<AccelerometerReading> e) { Dispatcher. GestureEventArgs e) { } } A Timer eseményének kezelőjében helyezzük át a célképet egy véletlenszerű pozícióra! A Random osztály NextDouble metódusa egy 0 és 1 közötti értéket ad. hogy a jelenlegi X és Z tengelyen vett gyorsulással hány képponttal szükségeltetik arrébb tolni a célkeresztet. crosshair. a két kép fedi-e egymást. ezt a kódot is a Dispatcheren keresztül tudjuk csak úgy futtatni. egy InvalidOperationException lesz a jutalmunk.SensorReading.SetValue(Canvas. newLeft).GetValue(Canvas. target. hogy ezzel nem csúszna-e ki a célkereszt a ContentPanel valamelyik szélén: void accel_CurrentValueChanged(object sender.Abs((double)target.TopProperty)) < 20) { hits++.ToString().LeftProperty) (double)crosshair. private void TimerEvent(object o) { Dispatcher. vagyis a célkereszt a célkép felett van-e! Ha igen. if (newLeft < 0) newLeft = 0. }).BeginInvoke(() => { target. tbkHits. } } Már csak a lényeg maradt hátra: kezeljük le a gyorsulásmérő változását.Z * 10.TopProperty. növeljük meg a számláló értékét. if (newTop < 0) newTop = 0.Acceleration.BeginInvoke(() => { double newLeft = (double)crosshair.X * 10.Abs((double)target. rand. 178 .Text = hits. leellenőrizzük. Mivel az esemény nem a UI-szálon következik be. a Dispatcher objektumon keresztül tudjuk ezt megtenni. A kódban kiszámoljuk.GetValue(Canvas.GetValue(Canvas. hogy amikor a felhasználó megtapintja a kijelzőt. További telefonos funkciók használata private void TimerEvent(object o) { } private void ContentPanel_Tap(object sender. hogy probléma nélkül hozzáférjen a UI-szálhoz. rand. else if (newTop > 700) newTop = 700.TopProperty) (double)crosshair.7.SetValue(Canvas.TopProperty) + e.LeftProperty.LeftProperty. GestureEventArgs e) { if (Math.

hogy a felhasználó hogyan mozgatja térben a telefont. a giroszkóp segítségével megállapíthatjuk. Y és Z nevű. Másik tulajdonsága pedig a Vector3 típusú RotationRate.SetValue(Canvas. Példaalkalmazásunk most is a Windows Phone Application sablonra épül.0. Ezek között jelen esetben is van egy Timestamp nevű. ismét az Advanced Toolsra lesz szükségünk. ami működéséhez mással nem tudja pótolni ezt az érzékelőt. }). newTop). A CurrentValueChanged eseményére való feliratkozás és a Start metódus meghívása után egy háttérszálon kapjuk az eseményeket. ContentPaneljében pedig elhelyezünk egy kört: <Grid x:Name="ContentPanel" Grid. hogy irányítsuk a gyorsulásmérőt.Row="1" Margin="12. tesztelhető. Ennek SensorReading tulajdonsága az. de azért élvezhető A giroszkóp használata Míg a gyorsulásmérő a telefon helyzetét mérte.Helyzetmeghatározás crosshair.0"> <Ellipse Name="ellipse" Width="100" Height="100" Fill="{StaticResource PhoneAccentBrush}" /> </Grid> 179 . ezért ne építsünk rá olyan programot. és tárolja a számunkra hasznos információkat. melyek az egyes tengelyeken mért forgási sebességet adják meg radián per másodpercben. 7-7 ábra – Nem egy Korszerű Hadviselés 3.12. Ez a korábban már megismert X. float típusú mezőket tartalmazza. Ha nem akarjuk vagy tudjuk fizikai eszközön tesztelni. A mintavételezés a TimeBetweenUpdates tulajdonságban megadott intervallummal történik. ami GyroscopeReading típusú. } Az alkalmazás kész. A giroszkóp használata programozási szinten alig tér el valamiben a gyorsulásmérőétől! A giroszkópot a Gyroscope osztály egy példányán keresztül érjük el. a korábbiakkal azonos funkciójú DateTimeOffset.TopProperty. Mivel a giroszkóp nem tartozik a telefonok alapfelszereltségébe. A CurrentValueChanged esemény második argumentuma jelen esetben SensorReadingEventArgs<GyroscopeReading> típusú.

Devices. 0.X.. } Az alkalmazás kész.. ellipse. Az iránytűhöz tartozó objektum létrehozása és a kapcsolódó infrastrukturális kód a már megszokott.BeginInvoke(() => { ellipse. amikor előre-hátra döntik. 0.RotationRate. már csak egy olyan telefont kell találni. SensorReadingEventArgs<GyroscopeReading> e) { Dispatcher. és a usingok közé tegyük be a Microsoft.7. Az iránytűt a Compass 180 .Sensors névteret! using Microsoft.Devices. 0. gyro. Amikor oldalt forgatják a telefont. oldalirányban növeljük meg a korábban létrehozott kör méretét. akkor pedig függőlegesen: void g_CurrentValueChanged(object sender. }). amin tesztelni is tudjuk. SensorReadingEventArgs<GyroscopeReading> e) { } } Ezután már csak kezelni kell az eseményt.RoutedEventArgs e) { if (Gyroscope. és a Loaded eseménykezelőjében − ha van giroszkóp − hozzuk létre.Z.SensorReading.Start(). Az iránytű használata Az előzőektől eltérő működésű érzékelő a magnetométer.SensorReading.Height = 100 + 600 * e.Width = 100 + 350 * e. public MainPage() { InitializeComponent().RotationRate. iratkozzunk fel CurrentValueChanged eseményére.Show("Kevés a giroszkóp. További telefonos funkciók használata Emellett feliratkozunk az oldal betöltődését jelző eseményre: <phone:PhoneApplicationPage x:Class="GyroHandling. } void g_CurrentValueChanged(object sender.Sensors és a Microsoft.Devices.TimeBetweenUpdates = new TimeSpan(0. gyro.IsSupported) { gyro = new Gyroscope()."). leánykori nevén iránytű.MainPage" . System. Loaded="PhoneApplicationPage_Loaded"> Adjuk hozzá a projekthez a Microsoft. gyro. } else MessageBox. Adjunk hozzá egy Gyroscope referenciát az oldalhoz.Xna.CurrentValueChanged += g_CurrentValueChanged.Framework referenciákat.Sensors. és indítsuk el! public partial class MainPage : PhoneApplicationPage { Gyroscope gyro = null. } private void PhoneApplicationPage_Loaded(object sender. 50).Windows.

12. illetve iratkozzunk fel az oldal Loaded eseményére: <phone:PhoneApplicationPage x:Class="MagnetometerHandling. A CurrentValueChanged esemény második argumentuma SensorReadingEventArgs<CompassReading> típusú. Az Image és TextBlock elemeket adjuk hozzá a ContentPanelhez. mely fokokban mérve megmondja. hogy a telefon X.MainPage" . hogy amikor pontosan észak – pontosabban a mágneses északi sark – felé nézünk. Az utolsó tulajdonság pedig a HeadingAccuracy nevű double érték. akkor jelenjen meg teljes egészében.IsSupported) 181 . mely arról tájékoztat..0"> <Image Name="img" Source="magneto. SensorReading tulajdonságában ott van a jól ismert Timestamp tulajdonság.png" /> <TextBlock Name="tbkOpacity" Text="0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="56" /> </Grid> </Grid> </phone:PhoneApplicationPage> A szokásos módon. a usingok közé pedig az azonos nevű névteret! using Microsoft. egyre halványabb (átlátszóbb) legyen.Windows. Adjunk hozzá egy Compass mezőt az oldalhoz.. Ezenkívül pedig egy TextBlockban megjelenítjük a valódi északi sarkhoz viszonyított irányunkat.RoutedEventArgs e) { if (Compass. Statikus IsSupported tulajdonsága megadja. amikor pedig elfordulunk északtól. public MainPage() { InitializeComponent(). Emellett pedig három másik. System.0. amelyekből az irányt kaphatjuk meg. A TrueHeading ugyanezt teszi. <Grid x:Name="ContentPanel" Grid..Devices. Y és Z tengelyén mérve hány microtesla érzékelhető. hogy támogatott-e ez a szenzor az eszközön. leállítani az irány figyelését. hogy az operációs rendszer éppen kalibrálja az iránytűt. Sajnos az emulátor ezt sem támogatja… A példányosítás után itt is egy CurrentValueChanged nevű eseményre tudunk feliratkozni. } private void PhoneApplicationPage_Loaded(object sender. hogy feliratkozhatunk a Calibrate eseményre is.Devices. Végül a MagnetometerReading nevű.Helyzetmeghatározás osztály jelképezi. hogy fokokban mérve merre néz a telefon a mágneses északi sarkhoz képest.Sensors. illetve a Start és Stop metódusokkal elindítani. hogy mekkora a mérés pontatlansága. dél felé nézve teljesen tűnjön el. Érdemes még tudni.Row="1" Margin="12. Vector3 típusú tulajdonság megadja. a projekt referenciái közé vegyük fel a Microsoft. csak a geográfiai északi sarkkal. Akkor készítsük el a Magnetométert! A Windows Phone Application sablon ContentPaneljén jelenítsünk meg egy képet! Ennek átlátszóságát szeretnénk úgy beállítani.. Loaded="PhoneApplicationPage_Loaded"> <Grid x:Name="LayoutRoot" Background="Transparent"> .Sensors nevű dll-t. és indítsuk el azt – ha támogatott az iránytű: public partial class MainPage : PhoneApplicationPage { Compass compass = null. A MagneticHeading nevű lebegőpontos érték megadja. majd a Loaded eseménykezelőben állítsuk azt be! Iratkozzunk fel a CurrentValueChanged eseményére.

Show("Keress olyan mohát.MagneticHeading . if (e. } void compass_CurrentValueChanged(object sender. else maghead = (e.SensorReading. 7-8 ábra: Mérjük meg a mágneses erőket 182 . double maghead = 0.SensorReading. } else MessageBox. compass.SensorReading.180) / 180.TrueHeading. compass.MagneticHeading == 0) maghead = 1. tesztelhető – de csak telefonon. } Kész is a program.Text = e.SensorReading. így belsejében – szintén megszokott módon – a Dispatcher és némi matematika segítségével állítjuk be a kép Opacity és a TextBlock Text tulajdonságát: void compass_CurrentValueChanged(object sender.7. További telefonos funkciók használata { compass = new Compass(). SensorReadingEventArgs<CompassReading> e) { } } A CurrentValueChanged esemény a megszokott módon egy háttérszálon történik.Opacity = maghead.BeginInvoke(() => { tbkOpacity.MagneticHeading / 180).CurrentValueChanged += compass_CurrentValueChanged.Start(). else if (e.SensorReading. amelynek a déli oldala fás!"). SensorReadingEventArgs<CompassReading> e) { Dispatcher.ToString(). }).MagneticHeading < 180) maghead = 1 .(e. mivel az emulátoron nem támogatott az iránytű (7-8 ábra). img.

a Yaw pedig a Z-tengely mentén vett elfordulás. Készítsünk egy alkalmazást a Visual Studio Windows Phone Application sablonjának segítségével! Iratkozzunk fel a MainPage Loaded eseményére. minden ismerős lesz.5-ben beépített egy magasabb réteget is a helyzetérzékelők programozási felülete (vagyis az Accelerometer. de mindegyik csak egy-egy aspektusban tudja vizsgálni azt. Amennyiben nincs giroszkóp a telefonban. Ezek segítségével mindenféle további számítás nélkül megkapjuk a telefon helyzetét a Földhöz képest. Az előző érzékelő-esemény óta eltelt idő. <Grid x:Name="ContentPanel" Grid. Ahhoz. hanem a Motion API-n keresztül egyetlen tulajdonságból kiolvasható ez az adat.12.Helyzetmeghatározás Az érzékelők együttes használata a Motion API segítségével Az előzőekben leírt érzékelők hasznos információkkal szolgálnak a telefon helyzetét illetően. Ez a Motion API. a Roll az Y-tengely. mely a helyzetérzékelők adatait felhasználva könnyen kezelhető. a Roll és a Yaw. radiánban mérve. ahogy a telefon forog: <phone:PhoneApplicationPage x:Class="MotionApiHandling. Ezek az egyes tengelyek körül vett elfordulások. Az eszköz három tengelye körül vett forgási együtthatók. a DeviceRotationRate egy nullvektort tartalmaz. Loaded="PhoneApplicationPage_Loaded"> . releváns információkat ad. Ennek statikus IsSupported tulajdonságából tudhatjuk meg. Az eszköz gyorsulása – ez a gravitáció nélkül értendő.Row="1" Margin="12.0. tehát ha korábban már kezeltük a gyorsulásmérőt vagy társait. ezzel is időt spórolva meg a fejlesztőnek. A Pitch a telefon X-tengelye. hogy több érzékelő adatait is összevessük. Az igazi nóvum az Attitude. különválasztva a gravitáció irányát és a tényleges gyorsulást. A fejlesztők munkáját megkönnyítendő a Microsoft a Windows Phone 7. Ráadásul a Motion API használata teljesen megegyezik a korábban látott programozási interfészekével. pontosabban forgatni tengelyei körül úgy. a Gyroscope és a Compass osztályok) fölé. A Motion API-t a Motion osztályon keresztül érjük el.0"> <Image Name="img" Source="arrow..png" Height="550"></Image> </Grid> </Grid> </phone:PhoneApplicationPage> 183 . A Start és a Stop metódusainak meghívása között dobja fel a CurrentValueChanged eseményt. mennyire fordult el a telefon. hogy éppen merre. amire szükségünk van a helyzetmeghatározáshoz. a Vector3 típusú tulajdonságok tulajdonképpen a gyorsulásmérő és a giroszkóp adatait adják vissza – előbbit némileg módosított formában. gyakran sok matematikázásra van szükség. melynek SensorReading tulajdonsága a következő tulajdonságokat tartalmazza: 7-3 táblázat: A MotionReading osztály tulajdonságai Tulajdonság Attitude DeviceAcceleration DeviceRotationRate Gravity Timestamp Típus AttitudeReading Vector3 Vector3 Vector3 DateTimeOffset Szolgáltatott információ Az eszköz helyzetét adja meg. Ahogy látható. A gravitáció iránya. illetve arra.MainPage" . hogy az alkalmazás számára hasznos információkat nyerjünk ki az érzékelőktől érkező adatokból. Emellett megkapjuk a „nyers” adatokat is. Például nem szükséges a gyorsulás komponenseiből kiszámolnunk... tehát egyetlen objektumon keresztül elérhetünk mindent.. illetve a ContentPanelben helyezzünk el egy képet! Ez utóbbit szeretnénk a Motion API segítségével mozgatni. hogy támogatott-e a Motion API az eszközön. melynek három fontos tulajdonsága a Pitch.

ezt a RotateTransformmal állítjuk be.Show("Motion API not supported.RenderTransform> <Image.Framework.7.Row="1" <Image Name="img" Source="arrow.12. A másik két tengelyen való elforgatás ennél kicsit trükkösebb. és a Loaded eseménykezelőben. } else MessageBox.0"> Height="550"> /> /> A XAML rész kész. ha elérhető a Motion API. } private void PhoneApplicationPage_Loaded(object sender. 184 . SensorReadingEventArgs<MotionReading> e) { } } A CurrentValueChanged esemény kezelőmetódusában pedig – a megszokott módon. ezekkel azonos nevű névteret a usingok közé! using Microsoft.Projection> <PlaneProjection x:Name="pp" </Image. public MainPage() { InitializeComponent(). iratkozzunk fel CurrentValueChanged eseményére.Sensors és a Microsoft.Framework dll-ekre! A mögöttes kódban emeljük is be a két. példányosítsuk az objektumot. és indítsuk el a figyelést! public partial class MainPage : PhoneApplicationPage { Motion m = null. A Silverlight nem támogatja a tényleges háromdimenziós forgatást. A felhasználó felé néző Z-tengelyen vett elforgatást a Yaw adja meg.CurrentValueChanged += m_CurrentValueChanged. Adjunk hozzá a MainPage-hez egy Motion referenciát.Xna.Devices.Sensors. A vízszintes. adjunk hozzá a projekthez egy referenciát a Microsoft.png" <Image.RenderTransform> <RotateTransform x:Name="rt" </Image.IsSupported) { m = new Motion() { TimeBetweenUpdates = new TimeSpan(0. 0.Start(). a Dispatcher segítségével – a PlaneProjection és a RotateTransform megfelelő értékeit adjuk meg. X-tengelyen vett elforgatás a Pitch.0. :'(").Devices.Xna. az Y-tengelyen vett elforgatás pedig a Roll. } void m_CurrentValueChanged(object sender. 0. Helyezzünk el egy RotateTransformot és egy PlaneProjectiont az Image-ben! <Grid x:Name="ContentPanel" Grid. hiszen a képet itt háromdimenziós objektumként kellene kezelnünk. m. További telefonos funkciók használata A telefon megdöntését (amelyet a Yaw tulajdonsággal állítunk be) egy egyszerű RotateTransform segítségével kezelhetjük. térbelinek tűnő elforgatására.Projection> </Image> </Grid> Margin="12. using Microsoft. Ezeket rendre a PlaneProjection RotationX és RotationY értékéhez rendeljük hozzá. Ellenben a vizuális elemek Projection tulajdonsága segítségével lehetőségünk van az objektumok virtuális. 50) }. RoutedEventArgs e) { if (Motion. 0. m.

SensorReading. ha felhasználjuk a Microsoft. }).Roll). releváns információk formájában nyerhetjük ki az operációs rendszerből.ToDegrees(e. melynek statikus tagjai az ilyen és ehhez hasonló mindennapi transzformációk elvégzését könnyítik meg. de fokban kell megadni a PlaneProjection és a RotateTransform számára.Angle = MathHelper. mellyel hozzáférünk a kijelző által szolgáltatott nyers adatokhoz.RotationX = MathHelper.FrameReported eseményig. a telefon forgását mérő giroszkóp már opcionálisan beépíthető komponens. Ezeknek az eszközöknek a kezelése nagyon hasonló. Összefoglalás Ebben a fejezetben megismerkedhettünk a Windows Phone 7-nel szerelt eszközökbe kötelezően vagy opcionálisan beépített érzékelők használatával. ez egy radiánban vett értéket fogad. Az emulátor sajnos egyelőre nem támogatja a Motion API-t.5-ben megjelent Motion API révén pedig mindenezeket a nyers adatokat akkumulálva. 185 . void m_CurrentValueChanged(object sender.Attitude. helyzetmeghatározó érzékelők és programozási felületek állnak rendelkezésünkre. akkor indulhat a tesztelés. A telefonra ható erőket – így a gravitációt is – mérő gyorsulásmérő.Attitude. rt. SensorReadingEventArgs<MotionReading> e) { Dispatcher.SensorReading.RotationY = MathHelper. A Windows Phone 7.BeginInvoke(() => { pp.Pitch). } Ha van fizikai eszközünk. Végül pedig számba vettük.Összefoglalás Mivel az értékeket radiánban kapjuk.Yaw). át kell alakítanunk őket.Attitude. pp. Erre a legegyszerűbb módszer. Konkrétan a ToDegrees metódusra lesz szükségünk.ToDegrees(e. Ezután áttekintettük a telefon helyének megállapítását lehetővé tevő. és fokokban véve adja vissza.SensorReading. Először az érintőképernyő eseményeinek három rétegét tekintettük át a magas szintű Tap és társaitól a többérintéses kezelést lehetővé tevő Manipulation eseményeken keresztül a legalsó szinten lévő Touch. és az A-GPS-t a cellainformációkkal és ismert wifik alapján történő lokalizálással egyesítő GeoLocation API használatát a GeoLocationWatcher osztályon keresztül. hogy milyen egyéb. amire fel tudjuk tölteni az alkalmazást.Framework névtérben található MathHelper osztályt. valamint a mágneses erők irányát megadó magnetométer minden telefon alapfelszereltsége.Xna.ToDegrees(e.

.

csak és kizárólag az alkalmazásunk által használt Isolated Storage-ünket. ha tényleg szükséges! A fájlkezelés legyen transzparens a felhasználók számára! Ha átmeneti (Temp) fájlokat készítünk. és nincs is többé szükség rájuk! Bizonyos esetekben célszerű ezeket a fájlokat szinkronizálni vagy archiválni a felhőbe (Cloud). mindössze annyi a különbség. A Windows Phone SDK 7. amiket a Linq To SQL technológiával érhetünk el. mint a Silverlightnál. A Windows Phone 7 Isolated Storage megoldása nagyon hasonló a Silverlightos Isolated Storage megoldásához. vagyis itt egy alkalmazás korlátlanul gazdálkodhat a tárhellyel. valamint az általános fájlműveleteket is el tudja végezni. Minden alkalmazás csak a saját Isolated Storage-ében tud garázdálkodni. néhány szempontot célszerű szem előtt tartani:     Csak akkor használjuk a fájlrendszert. ezzel növelve a biztonságot és a fájlkárosodás elkerülését. Adatkezelés Minden nagyobb alkalmazásnál eljön az az idő.8. Minden alkalmazás kérhet magának egy-egy ilyen elkülönített tárhelyet. akkor csak az Isolated Storage áll a rendelkezésünkre. Files and Folders: Fájlokat és mappákat kezelhetünk a segítségével (IsolatedStorageFile). Relation Data: Relációs adatokat tárolhatunk egy lokális adatbázisban (SQL Server Compact Edition). Ebben a fejezetben megismerkedhetünk azzal. Ahogy a neve is mutatja. akkor lehetőleg azonnal töröljük azokat. így más alkalmazások semmilyen módon nem befolyásolhatják az alkalmazásunk működését. hogy itt nincs megszabva kvóta. Bár nincs méretkorlát az alkalmazások készítői számára. amint már nem használjuk. Settings: Kulcs/érték adatokat tárolhatunk benne (IsolatedStorageSettings). A fejezetben kitérünk a következő témakörökre:      IsolatedStorage megismerése ApplicationSettings használata Hogyan olvassunk és írjunk fájlokat IsolatedStorage Tool-ok megismerése Lokális adatbázisok használata Isolated Storage A Windows Phone 7-nél nem beszélhetünk klasszikus értelemben a fájlkezelésről: ha I/O műveleteket szeretnénk elvégezni a fájlrendszeren. ahol az alkalmazásunk képes írni. ott viszont úgy. akkor a megszokott környezetével találkozhat. illetve ha a felhasználó másik kliensen jelentkezik be. ez egy tárhely (Storage). amikor tárolni kell adatokat a készüléken. ahogy csak szeretné.1 verziója óta háromféle adatkezelési módszer létezik a készüléken (8-1 ábra):    187 . amit relációs adatbázisban tárolunk. legyen szó egyszerű beállításokról vagy összetett adatokról. olvasni. hogyan kezeljünk adatokat a Windows Phone 7 készülékünkön. így ha az alkalmazás törlésre kerül. a felhasználó adatai még megmaradnak. vagyis az alkalmazások nem férhetnek hozzá egymás tárhelyéhez. Közvetlen módon tehát nem érhetjük el a teljes fájlrendszert. Leginkább az alkalmazásunk beállításainak mentésére használjuk.

egyszerűbb eset egy kulcs/érték pár tárolási módszer.Data. a háttérben eltároljuk ezt a felhasználónevet. akkor a korábban megadott és eltárolt felhasználónévvel automatikusan ki lesz töltve az adott szövegdoboz.8. Ha később újra elindítja az alkalmazást. amely megvalósítja az IEnumerable<T> interfészt. Az ApplicationSettings tulajdonképpen egy szótár.IsoltedStorage) Fájlok és Mappák DataConentext (System. A következő fejezetekben megismerkedünk az összes módszerrel. akkor az ApplicationSettings kulcs/érték pár tárolási módszer a legcélravezetőbb megoldás.Linq) Lokális adatbázis 8-1 ábra: A Windows Phone 7 adatkezelési lehetőségei A Windows Phone első. Adatkezelés Alkalmazás IsolatedStorageSettings (System. ahol olvashatjuk és írhatjuk a fájl stream-et. Kérdés: Ha lenne két olyan WP7-es alkalmazás. de a Mango frissítéstől kezdve arra is van lehetőségünk. Application Settings A fájlrendszert kétféleképpen érhetjük el: az első. meg tudnám osztani valamilyen módon az IsolatedStorage-ot? Válasz: Nem. Ebben az esetben például egy webszolgáltatáson keresztül oldhatjuk meg a fájlok közös használatát. 7. a második pedig a tradicionális fájlkezelés. tehát minden olyan műveletet elvégezhetünk rajta. az Application Settings-et fogjuk megismerni. akkor a mobilon a munkát egyszerűbbé tehetjük számára azzal. hogy ha már egyszer beírta.IsoltedStorage) Isolated Storage Kulcs/érték Párok IsolatedStorageFile (System. amellyel adatokat kezelhetünk a Windows Phone készüléken. ami ugyanazt a fájl alapú adatforrást használja.IO.0 változatában csak a Settings és a Files and Folders adatkezelési módszer állt a rendelkezésünkre. Amikor csak egyszerű alkalmazás-beállításokat szeretnénk elmenteni vagy lekérdezni. 188 .IO. amint azt a 8-2 ábra is illusztrálja. hogy egy lokális adatbázisban relációs módon tároljunk adatokat. amit egy normál gyűjteményen is. Például: ha egy felhasználónak egy szolgáltatás bejelentkezéséhez egy szövegdobozba kell beírnia a felhasználói nevét. Ebben a részben az első módszert.

a System. a második paraméter pedig egy tetszőleges objektum lehet. object>. TValue> objektum.. object>>. } public ICollection Values { get.IO. Az alábbi példában egy egyszerű stringet láthatunk: // Felhasználónév hozzáadása – Új kulcs létrehozása IsolatedStorageSettings. } public int Count { get. Ha már létezik a kulcs. amely egy kulcs/érték párost tud tárolni.IsolatedStorage { public sealed class IsolatedStorageSettings : IDictionary<string. Save(). hogy az IsolatedStorage-et elérjük. IEnumerable { public static IsolatedStorageSettings ApplicationSettings { get. out T value). object>>. és ezeket az értékpárokat az adott alkalmazás IsolatedStorage-ébe menti el.IO névtérre lesz szükségünk. Az 189 . Remove(string key). ebben az esetben az első paraméter egy kulcs. Clear(). Mivel ez egy Dictionary. akkor egy System. Egy új kulcs/érték párt többféle módon hozhatunk létre: egyszerűen az Add metódus meghívásával.Application Settings 8-2 ábra: Bővítő metódusok egész sora áll a rendelkezésünkre Az ApplicationSettings egy speciális Dictionary<TKey. Ahhoz. így például egy indexer segítségével is hozzáadhatunk egy új kulcs/érték-párt (így tudjuk a már létező kulcsok értékét is módosítani). ICollection.ApplicationSettings. } public public public public public public } } void void bool bool void bool Add(string key. object value). IEnumerable<KeyValuePair<string.IsolatedStorage névtérre. } public ICollection Keys { get. a fájlművelethez pedig a System.IO.ArgumentException-t kaphatunk. set. TryGetValue<T>(string key. IDictionary. Az alábbi kódrészlet az IsolatedStorageSettings felépítését mutatja be: namespace System. aminek egyedinek kell lennie. } public object this[string key] { get. ezért a rá vonatkozó szabályok élnek. ICollection<KeyValuePair<string. Contains(string key). "Attila").Add("UserName".

} else { //Nem létezik MessageBox. // Felhasználónév mentése /vagy módosítása IsolatedStorageSettings.ApplicationSettings. ha az adott kulcs nem létezik.Show("Nincs ilyen kulcs!").ToString()). set. set. akkor a tartalmát felülírja a meghatározott értékkel. Adatkezelés indexeres megoldásnál. a tartalmát és irassuk ki MessageBox.ApplicationSettings["UserName"]. ha a kulcs nem található meg a szótárban. Ez a metódus true értékkel tér vissza. ezt az ApplicationSettings saját maga megoldja.Contains("UserName")) { //Létezik a UserName kulcs. Ebben az esetben nem kell törődnünk az adatsorosítással. Olvassuk ki pl.ApplicationSettings["UserNme"]. akkor az létrejön. ha már létezik a kulcs. valóban létezik-e a kulcs. Abban az esetben. out userValue). és azt tároljuk el. ha a kulcs nem létezik. } } . } public int Age { get. A másik lehetőség a TryGetValue metódus használata: string userValue. 190 .. A következő példában egy saját osztályt hozunk létre. majd olvassuk ki. abban az esetben. Az Indexeres módszer esetén.ApplicationSettings["UserName"] = "Attila". de természetesen komplex objektumokat is eltárolhatunk az ApplicationSettings-ben. public class Person { public string Name { get. akkor a userValue változó értéke üres (null) lesz. Ebben az esetben. A TryGetValue nagyon hasonlít a TryParse metódusokra. } Az előző példákban csak egy egyszerű string adatot tároltunk el. míg ha a TryGetValue metódust használjuk.Show(IsolatedStorageSettings.ApplicationSettings. IsolatedStorageSettings.TryGetValue<String>("Kulcs". if (IsolatedStorageSettings. Person myPerson = new Person() { Name = "Jhon". false értékkel.8. akkor true-val. nem kapunk hibát. ha nem. ha létezik az adott kulcs.ApplicationSettings["PersonData"] = myPerson.NET-es típusoknál használhatunk. egyébként false-szal. Ez is egy Boolean értékkel tér vissza: ha sikerült a kulcsot megtalálni és kiolvasni a tartalmát. a Contains metódust használhatjuk fel. Age = 32 }. akkor egy KeyNotFoundException-t fogunk kapni. amit a . ha meg akarunk győződni arról.. Az adott kulcsok értékét persze le is kérdezhetjük. ehhez is használhatunk két módszert: az egyik az itt bemutatott indexeres módszer: //Felhasználóné lekérdezése var userName = IsolatedStorageSettings. //Adat mentése IsolatedStorageSettings.

Az ApplicationSettings az alkalmazás bezárásakor elmenti az adatokat. és az ApplicationSettings elérését egyszerűsíteni és ésszerűsíteni. ezek az információk nem kerülnek elmentésre.Show(newPerson.ApplicationSettings["PersonData"] as Person. hogy az IsolatedStorage használata mennyire egyszerű.ApplicationSettings.Application Settings // Adat lekérdezése Person newPerson = IsolatedStorageSettings. Az előző rövid példákban látható volt. viszont ha az alkalmazás futása közben nem várt hiba történik. akkor az adott típus alapértelmezett értékével (ebben az esetben ez null) tér vissza.ApplicationSettings.Clear(). Ha az adott kulcs nem található meg a szótárban. ilyenkor a Remove metódust kell használnunk: IsolatedStorageSettings.Values) { // Feldolgozás } Egy alkalmazásnál sokszor használhatjuk az ApplicationSettings-et.Remove("UserName"). amely a paraméterében átadott kulcs értékét adja vissza. Eltávolíthatunk egy kulcsot. Ha biztosra szeretnénk menni.ApplicationSettings.Name). ezért ezt egyszerűbben az alábbi módon is megoldhatjuk – így több billentyű leütését is megspórolhatjuk: var settings = IsolatedStorageSettings. IsolatedStorageSettings. Ez az osztály egy általánosan használható RetriveSettings segédmetódust tartalmaz.Save(). public class Settings { private const string ApplicationTitleKey = "ApplicationTitle". MessageBox. viszont sokszor fordul elő.ApplicationSettings.Keys) { // Feldolgozás } foreach (var value in IsolatedStorageSettings. akkor ki kell kényszerítenünk a mentést az ApplicationSettings Save metódusával. A következő példában egy Settings osztályt hozunk létre. mind az értékeken végig tudunk haladni a foreach utasítással: foreach (var key in IsolatedStorageSettings. ezért mind a kulcsokon.ApplicationSettings. amiben általános és/vagy ellenőrző módon tudjuk elérni az általunk használt kulcs/érték párokat. string myValue = settings["Kulcs"]. A mentett adatokat persze el is távolíthatjuk az ApplicationSettings-ből.ToString(). Mivel az ApplicationSettings egy szótár. melynek folyamatos kiírása fáradságos lehet. és az alkalmazás leáll. ez pedig az adatkötés technikája! Az előzőekben csak explicit módon mentettünk el és olvastunk ki adatokat. private const string PersonKey = "Person". Egy dolgot azonban még tisztáznunk kell. 191 . hogy jó volna ezt centralizálni. settings["Kulcs"] = "Érték".ApplicationSettings. akkor a Clear metódust kell meghívnunk: IsolatedStorageSettings. Ha az összes értéket el akarjuk távolítani.

ApplicationSettings[ApplicationTitleKey] = value. } } public Person MyPerson { get { return RetriveSettings<Person>(PersonKey).xaml).xaml fájlban deklaratív módon példányosítani. hogy a Settings osztály miért nem lett static? Így sokkal egyszerűbb lenne elérni a tulajdonságok értékét.ApplicationSettings[PersonKey] = value. } public string ApplicationTitle { get { return RetriveSettings<string>(ApplicationTitleKey). out settingValue)) { return (T)settingValue. Felmerülhet bennünk a kérdés. és erre ezt követően az alkalmazásunkban bárhol hivatkozhatunk kódból és XAML-ből egyaránt: .Resources> <local:Settings x:Key="MySettings" /> </Application. nyissuk meg az egyik oldalt (jelen esetben a MainPage.8. és a PhoneApplicationPage DataContext-jének adjuk át a MySettings-et az alábbi módon! 192 . } set { IsolatedStorageSettings. if (IsolatedStorageSettings. ráadásul elkerüljük a szöveges értékű kulcsok elírását is. így könnyebb az alkalmazásunkban ezeket a beállításokat írni és olvasni. mint mindig példányosítani egy Settings-et! A válasz egyszerű: célravezetőbb ezt az osztályt az App. xmlns:local="clr-namespace:PhoneAppTest" > <Application. így a Settings osztályon keresztül az összes kulcsértéket el tudjuk érni.xaml-ben elkészítettük a példányt. } set { IsolatedStorageSettings. } } } Az osztályban minden kulcsnak különálló tulajdonságot készítünk.TryGetValue(settingKey.Resources> Miután az App... Adatkezelés private T RetriveSettings<T>(string settingKey) { object settingValue. így csak az alkalmazás indulásakor egyszer készítünk egy Settings példányt. } return default(T).ApplicationSettings. Mostantól tehát minden kulcsnak külön tulajdonságot fogunk készíteni.

. Ebben az esetben a Binding módja TwoWay. ekkor az alkalmazás háttérbe vonul! Az emulátoron újra indítsuk el az alkalmazást. amint azt a 8-3 ábrán láthatjuk. és a szövegdobozba beírunk valamit. majd kattintsunk a Start gombra az emulátoron. az a háttérben tárolásra fog kerülni.0.Application Settings <phone:PhoneApplicationPage x:Class="PhoneAppTest. azaz a kötés kétirányú.0. és a Text tulajdonságát kössük az ApplicationTitle-höz. <TextBox Text="{Binding ApplicationTitle.0" Name="textBox1" VerticalAlignment="Top" Width="460" /> A PageTitle Textblock Text tulajdonságához is kössük az ApplicationTitle-t: <TextBlock x:Name="PageTitle" Text="{Binding ApplicationTitle}" Margin="9. és mentsük el az értékét! 193 .-7. és láthatjuk.IsVisible="True" DataContext="{StaticResource MySettings}"> Ezt követően az oldalra helyezzünk el egy TextBox-ot. Ehhez készítsük el a felhasználói felületet. Írjunk oda egy tetszőleges szöveget. Mode=TwoWay}" Height="72" HorizontalAlignment="Left" Margin="6.6.MainPage" . SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.0" Style="{StaticResource PhoneTextTitle1Style}"/> Ha elindítjuk az alkalmazást (6-3 ábra).. hogy az oldal címe és a szövegdoboz tartalma az ApplicationSettings-ből kiolvasott érték lesz. 8-3 ábra: Application Settings demó alkalmazás Gyakorló feladat: A Settings osztályban van egy MyPerson tulajdonság is.

Az alábbi táblázatban az IsolatedStorageFile fontosabb metódusait találjuk: Metódus CopyFile(String. ez ebben az esetben egy IsolatedStorageFileStream. valamint egy StreamReader példányt használunk az olvasáshoz. Ebben a részben a tradicionális. akkor opcionálisan felülírhatjuk. A már foglalt terület nagysága. A fájlba egy StreamWriter példány segítségével írhatunk. hogy a FileMode ebben az esetben az Open értékét viseli. sw. } A GetUserStoreForApplication metódus egy IsolatedStorageFile példányt ad vissza. sw. majd a StreamWriter példány WriteLine metódusával írhatunk egy sort a fájlba.GetUserStoreForApplication(). olykor ez kevés lehet a számunkra. A fájlból olvasás hasonlóan egyszerű. stream-alapú fájlkezelést fogjuk közelebbről megismerni. Lekérdezhetjük. Adatkezelés IsolatedStorageFileStream Bár könnyű kulcs értékeket tárolni. isf)) { StreamWriter sw = new StreamWriter(myFileStream). az IsolatedStorageFileStream osztályra lesz szükségünk. FileMode. hogy egy új fájlt létrehozzunk.Open. using (IsolatedStorageFileStream myFileStream = new IsolatedStorageFileStream("data. using (IsolatedStorageFileStream myFileStream = new IsolatedStorageFileStream("data. IsolatedStorageFile isf = IsolatedStorageFile. sw. string text = sr. FileMode. Ha a cél útvonalon létezik a fájl.txt". mely a „Hello World” szöveget tartalmazza: IsolatedStorageFile isf = IsolatedStorageFile.Show(text). és annak elérési módját (FileMode enumeráció). Ahhoz. Boolean) CreateDirectory Leírás Egy létező fájl másolása.WriteLine("Hello World").ReadToEnd(). és hagyományos fájlok elérésére volna szükségünk a fájlrendszeren.GetUserStoreForApplication(). } Az alábbi táblázatban az IsolatedStorageFile tulajdonságait foglaljuk össze: Tulajdonság AvailableFreeSpace IsEnabled Quota UsedSize Leírás Az IsolatedStorage-ben rendelkezésre álló szabad terület mérete. valamint át kell adnunk egy IsolatedStorage példányt is. hogy az IsolatedStorage engedélyezve van-e.Close(). A maximálisan felhasználható szabad terület mérete. MessageBox. String) CopyFile(String. isf)) { StreamReader sr = new StreamReader(myFileStream). Egy létező fájl másolása. annyi a különbség. String. Ebben az egyszerű példában egy fájlt hozunk létre.8.Flush(). Ennek az osztálynak a példányosításakor kell meghatároznunk a fájl nevét.Create.txt". Ennek át kell adnunk egy Stream-et. Mappa készítése 194 .

Visszaadja a fájl vagy mappa készítési idejét. Egy könyvtár törlése is legalább ilyen egyszerű.GetUserStoreForApplication(). Visszaadja a fájlok neveit (Gyökérkönyvtárból kiindulva). Visszaadja a mappák neveit (Gyökérkönyvtárból kiindulva). A felhasználóhoz tartozó izolált tárhelyet kezelő IsolatedStorageFile példányt kérhetünk a segítségével. Megadhatunk összetett könyvtár útvonalat is: myISF. Mind a könyvtár létrehozásakor. FileAccess) Remove Nézzünk néhány gyakori felhasználási esetet! Könyvtár létrehozáshoz a CreateDirectory metódust használhatjuk fel. Visszaadja. hogy az adott könyvtár létezik-e: 195 . Visszaadja a fájlok neveit egy meghatározott minta alapján. mind a könyvtár törlésekor célszerű ellenőrizni. Az IsolatedStorage és tartalmának eltávolítása GetUserStoreForApplication MoveDirectory MoveFile OpenFile(String. hogy az adott fájl létezik-e. hogy a fájlhoz vagy mappához mikor fértek hozzá utoljára.és hozzáféréssel. ahol a metódusnak a könyvtár nevét adjuk át: IsolatedStorageFile myISF = IsolatedStorageFile.IsolatedStorageFileStream Metódus CreateFile DeleteDirectory DeleteFile DirectoryExist FileExist GetCreationTime GetDirectoryNames() GetDirectoryNames(String) GetFileNames() GetFileNames(String) GetLastAccessTime Leírás Új fájl készítése Mappa törlése Fájl törlése Megvizsgálhatjuk. FileMode.CreateDirectory("UjKonvtar").DeleteDirectory("UjKonvtar"). Mappa (és tartalmának) áthelyezése egy új útvonalra Fájl mozgatása egy új helyre. Visszaadja a mappák neveit egy meghatározott minta alapján. Fájl megnyitása egy meghatározott módon Fájl megnyitása egy meghatározott módon.CreateDirectory("Folder1/Folder2/Folder3/UjKonvtar"). FileMode) OpenFile(String. Megvizsgálhatjuk. myISF. ehhez a DeleteDirectory metódust használhatjuk fel: myISF. opcionálisan a fájl nevét is megváltoztathatjuk. hogy az adott mappa létezik-e.

GetUserStoreForApplication().DirectoryExists(directoryName_in)) myIsolatedStorage.IsNullOrEmpty(directoryName_in) && !myIsolatedStorage. Ráadásul.IsNullOrEmpty(directoryName_in) && myIsolatedStorage. akik korábban Silverlight alatt használták ezt a funkciót.CreateDirectory(directoryName_in). A projekt kiindulási anyagát a következő oldalról tölthetjük le: http://devportal.hu/wp7. Isolated Storage gyakorlat A következő gyakorlatban egyszerű jegyzetelő alkalmazást fogunk elkészíteni (8-4 ábra). Az alkalmazás felhasználói felülete előre el van készítve. Gyakorlottaknak és kezdőknek egyaránt könnyen és hatékonyan használható API áll a rendelkezésére.DirectoryExists(directoryName_in)) { myIsolatedStorage. if (!string. azok számára ez sok újdonságot nem is rejteget. 8-4 Az elkészített jegyzetelő alkalmazás 196 .8. hogy a Windows Phone 7 alatt a fájlkezelés rendkívül egyszerű és gyorsan elsajátítható.DeleteDirectory(directoryName_in). Adatkezelés public void CreateDirectory(string directoryName_in) { try { IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile. } } catch (Exception ex) { // Kivétel } } { Láthatjuk. } } catch (Exception ex) { // Kivétel } } public void DeleteDirectory(string directoryName_in){ try { IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication(). if(!string.

using (IsolatedStorageFileStream myFs = new IsolatedStorageFileStream(path. "Isolated Storage Demo". és . sem betölteni jegyzeteinket. c. az alábbi lépésekben: a.xaml. mySw.OK). itt fogjuk a jegyzeteink számára elkészíteni a „Notes” mappát.DirectoryExists("Notes")) { isf. Itt az ideje ezeket a funkciókat megvalósítani! Zárjuk be a futó alkalmazást. } d. if (!isf. e. FileAccess.Create. Ezt követően létrehozunk egy IsolatedStorageFileStream-et.cs fájlt.Text). Nyissuk meg az IsolatedStorageDemo.dat lesz a kiterjesztésük.CreateDirectory("Notes").WriteLine(txtDocument.IsolatedStorageFileStream A gyakorlatban csak az adattárolással kapcsolatos kódokat fogjuk közösen megírni.IsolatedStorage. és indítsuk el az alkalmazást! Egyszerű jegyzetelő felületet kapunk.ItemsSource = isf.Flush(). string path = "Notes\\" + txtTitle.IsolatedStorage névteret! (A feladatban a többi lapjához már hozzáadtuk ezeket a névtereket. myISFile)) { using (StreamWriter mySw = new StreamWriter(myFs)) { mySw. Nyissuk meg a MainPage. ugyanis itt fogjuk elmenteni a jegyzetünket a fájlrendszerbe. Itt az ideje megírni azt is. hogy a korábban elmentett jegyzeteinket vissza tudjuk tölteni. Az alkalmazás minden indulásakor megvizsgáljuk a DirectoryExist metódussal. IsolatedStorageFile myISFile = IsolatedStorageFile. és navigáljunk el a SavedItems konstruktorába: itt fogjuk kiolvasni a fájlrendszerről.Write. using System.IO és a System. MessageBoxButton.dat").IO. akkor egy MessageBox-ban ezt megüzenjük a felhasználónak. Fordítsuk le.Text tulajdonságának értékét..xaml. b.cs-ben navigáljunk el a btnSave_Click eseményhez. Ezt legegyszerűbben a StreamWriter-rel tudjuk írni. hogy jelenleg milyen jegyzeteink vannak mentve. Ehhez az IsolatedStorageFile példány GetFileNames metódusát fogjuk segítségül hívni az alábbi módon: IsolatedStorageFile isf = IsolatedStorageFile.Text + ". és térjünk vissza a projekthez! Nyissuk meg az App. A MainPage. Ha nem létezik (pl. első indulás).GetUserStoreForApplication().sln fájlt (Begin mappa)! Ha valamit a gyakorlat lépései során nem sikerülne pontosan követnünk. Most már elkészítettük az alkalmazásunk jegyzet (Notes) mappáját. f.IO.IO. és navigáljunk el az Application_Startup eseményhez.xaml. és el is tudjuk menteni a jegyzeteinket. } } MessageBox.xaml.cs fájlt. így a mySw példány WriteLine metódus paraméterének átadjuk a txtDocument. FileMode.Show("A jegyzetedet elmentettük!". és oldjuk fel a System. lstMyNotes. Először a path változóban létrehozunk egy útvonalat a jegyzeteink számára: azok a Notes mappába fognak kerülni.) using System. Ha minden sikeresen lezajlott. az End mappában megtalálható és kipróbálható az alkalmazás végleges formája. de jelenleg még nem tudjuk sem elmenteni.GetUserStoreForApplication().dat".GetUserStoreForApplication().GetFileNames("Notes\\*. hogy a Notes mappa létezik-e. Nyissuk meg a Pages/SavedItems.cs fájlt. akkor a CreateDirectory metódussal létrehozzuk: IsolatedStorageFile isf = IsolatedStorageFile. 197 .

QueryString.Relative)). ezt adjuk át a lstMyNotes listának. A fájl olvasása a fájlírás analógiájára történik. hogy elegánsabban jelenjen meg a fejléc: string fileName = string. out fileName)) { IsolatedStorageFile isf = IsolatedStorageFile. using (IsolatedStorageFileStream myFs = new IsolatedStorageFileStream("//Notes//" + fileName. FileMode. txtDocument. nézzük át újra a kódot és javítsuk azt! Ha minden rendben lezajlott. és a metódus törzsébe írjuk a következőt: string selectedItem = lstMyNotes. g. h.cs –hez.Navigate(new Uri("/MainPage. if (selectedItem != null) { NavigationService. UriKind. Adatkezelés A GetFileNames visszatérési értéke egy String tömb. A NavigationContext.GetUserStoreForApplication(). Természetesen.TryGetValue metódusával megpróbáljuk elérni az OpenFile paraméter értékét. ezt követően átadjuk a txtDocument-nek. Az előző pontnál megjelenítettük a jegyzeteink fájljait egy listában.xaml?OpenFile="+selectedItem.dat kiterjesztést.ReadToEnd(). isf)) { using (StreamReader sr = new StreamReader(myFs)) { txtTitle. Térjünk vissza a MainPage. ami majd megnyitja az adott jegyzetet. Ezzel elkészült az alkalmazásunk.dat". A txtTitle esetén a fileName szövegből eltüntetjük a . méghozzá a QueryString átadási mintát követve. és az átadott értéknek megfelelően megnyitni az adott fájlt.8. és navigáljunk el az OnNavigatedTo eseményhez. "").QueryString.Open. most pedig megírjuk azt az egyszerű funkciót. itt azonban az IsolatedStorageFileStream FileMode felsorolt típusából az Open értéket választjuk. } Itt egyszerűen a kiválasztott fájl nevét átadjuk a MainPage-nek. Fordítsuk le a forráskódot (Ctrl+Shift+B). akkor indítsuk el az alkalmazásunkat (F5)! Az megjelenik kezdőképernyőjén a jegyzeteink listájával.Text = sr.SelectedItem as string. és StreamWriter helyett StreamReader-t használunk. Navigáljunk el a lstMyNotes_SelectionChanged eseményhez. akkor azt le is kell kérdeznünk.Empty. } } } i. if (NavigationContext. A StreamReader ReadToEnd metódusának segítségével a fájl teljes tartalmát kiolvassuk.Replace(". amint azt a 8-5 ábra mutatja. ha átadtuk ezt a paramétert. és itt létrehozunk egy fileName nev string változót. amivel a kiválasztott fájlt átadjuk a MainPage-nek.TryGetValue("OpenFile". 198 .xaml. és ha valamilyen hibát tapasztalunk.Text = fileName.

xaml. Zárjuk be az alkalmazást. majd visszanavigálunk a MainPage oldalra.TryGetValue<int>("Foreground". out foregroundColorIndex). majd kattintsunk a mentés gombra! Készítsünk egy új jegyzetet (+).ApplicationSettings["Foreground"] = selectedItem. és el is van tárolva. és navigáljunk el az lpForeground_SelectionChanged metódushoz. j.xaml.Navigate(new Uri("/MainPage.cs fájlt. k. UriKind. ami kötés után a fekete színt reprezentálja). 199 . out currentIndex). Használhatnánk az indexeres formát is. és töltsük be a használt szín indexét: IsolatedStorageSettings. hogy a jegyzetek betűszíne milyen legyen. A következőkben a jegyzetelő alkalmazásunkat kiegészítjük egy olyan beállítással is. Természetesen a MainPage –nél is alkalmaznunk kell a kiválasztott színt: nyissuk meg a MainPage. Ha már kiválasztottunk egy színt.ApplicationSettings. melynek segítségével a felhasználó meghatározhatja. Válasszunk ki egy jegyzetet.TryGetValue metódusát használjuk.TryGetValue<int>("Foreground".Relative)).cs fájlt.ApplicationSettings Foreground kulcsához hozzáadjuk a kiválasztott szín kulcsának értékét. ezt követően kattintsunk a megnyitás gombra! A megjelenő ablakban a jegyzeteink lesznek láthatók.ApplicationSettings. l.xaml". NavigationService. a változó pedig az alapértelmezett értékét kapja (ebben az esetben a 0-t.IsolatedStorageFileStream 8-5 ábra: Jegyzetek megnyitása Az alkalmazás betöltése után írjunk egy jegyzetet. majd a feltételbe írjuk a következő kódsorokat: IsolatedStorageSettings. Itt az IsolatedStorageSettings. m. de a TryGetValue egyik nagy előnye az. akkor sem jelez hibát. és navigáljunk el az OnNavigatedTo eseményhez! Írjuk hozzá a következő kódsort: IsolatedStorageSettings. és térjünk vissza a Visual Studio-hoz! A fájlkezeléshez hozzátartozik a beállítások kezelése is. Itt az IsolatedStorageSettings.ApplicationSettings. akkor eddig a feladatot helyesen oldottuk meg. hogy ha az adott kulcs (esetünkben Foreground) még nem létezik. akkor azt a következő Settings page-re navigáláskor jelenítsük meg a felhasználó számára! Navigáljunk el a Settings konstruktorához.Key. Nyissuk meg a Pages/Settings. és a következő pillanatban már a főképernyőn láthatjuk a jegyzetünk tartalmát! Ha ezeket a lépéseket sikerült elvégeznünk.

hogy azok az általunk meghatározott útvonalon jöttek-e létre. itt is kiolvassuk a foreground tulajdonságot. legyünk kreatívak! Módosítsuk szabadon a UI-t. vagy vigyünk fel új menüpontokat! Rajtunk múlik a feladat. és ha valamilyen hibát tapasztalunk. akkor az alkalmazás rögtön visszanavigál a MainPage oldalra. akkor indítsuk el az alkalmazásunkat (F5)! o. n. Immár kész a teljes alkalmazás. Például: kilistázhatjuk a mappák tartalmát. amely segítségével műveleteket tudunk végezni a készülék vagy az emulátor Isolated Storage-án. Készítsük el az alkalmazást úgy. a minél leleményesebb megoldása a lényeg.exe <ts|rs|dir[:device-folder]> <xd|de> <Product GUID> [<desktop-path>] 200 . hogy mit és hogyan. de ebből a kontextusból nem tud kibújni. és javítsuk azt! Ha minden rendben lezajlott. A könnyebb használat érdekében a Mango frissítés fejesztőkészletének része lett az Isolated Storage Explorer Tool (ISETool. Minden alkalmazás rendelkezhet IsolatedStorage-dzsal. ahol sok a fájlművelet. ahol fájlműveleteket végezhet. másolhatunk. ahol láthatjuk. Önálló feladatok Fejlesszük tovább a jegyzetelő alkalmazást! Nincs megkötés arra. hogy a fájlkezelés rendkívül egyszerű a Windows Phone –on. majd mentsük el! Válasszuk ki a beállítások menüpontot. 8-6 ábra: Színválasztó lap Ezen a gyakorlaton keresztül is láthattuk. törölhetünk és minden alapvető fájlműveletet elvégezhetünk a segítségével. nézzük át újra a kódot. Tegyük megváltoztathatóvá jegyzetünk betűtípusát! IsolatedStorage – Tool Azoknál az alkalmazásoknál. Ezt a Toolt a $Program Files\Microsoft SDKs\Windows Phone\v7. hogy a jegyzetünk betűszíne megegyezik az általunk kiválasztott színnel. Ez egy parancssori eszköz. mint a Settings page-nél. majd alkalmazzuk a szövegdobozon. Készítsünk egy jegyzetet. és hogy tartalmuk helyes-e. hogy tudjunk jegyzetet törölni! 2.1\Tools\IsolatedStorageExplorerTool útvonal alatt találgató.exe). Az Isolated Storage Explorer Tool-t csak a regisztrált fejlesztői készülékeken lehet használni. hogy az alkalmazás használata során milyen fájlok keletkeztek. hasznos lenne látni.8. és a megjelenő ablakban válasszunk ki egy nekünk tetsző színt (8-6 ábra)! Ha kiválasztottunk egy új színt. Fordítsuk le a forráskódot (Ctrl+Shift+B). 1. A jegyzet megnyitásánál jelenítsük meg valamilyen formában a jegyzet készítésének dátumát! 3. Adatkezelés Csakúgy. Az Isolated Storage Explorer használatához a következő szintaxist lehet használnunk: ISETool.

) Ne felejtsük el átírni a saját ProductID-nkat! Az eredményt a 8-7 ábrán láthatjuk.xml fájlból: <App xmlns="" ProductID="{d25bf842-f28d-45ff-9a4d-6057e6614321}" Title="PhoneApp2" 3.xml) Egy könyvtár a számítógépünkön. Indítsuk el az alkalmazást az alábbi módon: ISETool. Nyissunk meg egy parancssort! 4. Készítsünk egy egyszerű Windows Phone 7 alkalmazást! 2.1\Tools\IsolatedStorageExplorerTool 5. például (8-8 ábra): 201 . hogyan másolhatunk fájlokat a telefonról a fájlrendszerünkre! Ezzel a funkcióval lementhetjük az alkalmazásunk mappáját. az „xd” helyett „de” kapcsolót kell használnunk.exe ts <xd|de> <Product GUID> <desktop-path>. ahová másolhatunk vagy írhatunk fájlokat az IsolatedStorage-ből. Ehhez mindösszesen a következő parancsot kell kiadnunk: ISETool.IsolatedStorage – Tool Parancs TS RS DIR Device-folder XD DE Product GUID Desktop-path Leírás Snapshot készítése Snapshot helyreállítása Mappák és fájlok listázása Mappa meghatározása Emulátoron történő használat Készüléken történő használat A termék ProductID-je (WPAppManifest. és a helyi gépünkön szabadon megvizsgálhatjuk azok tartalmát.exe dir xd d25bf842-f28d-45ff-9a4d-6057e6614321 (Amennyiben fizikai készülékről szeretnénk lekérdezni ezeket az információkat. Navigáljunk el a Windows Phone 7 SDK IsolatedStorageExplorer mappájába: $Program Files\Microsoft SDKs\Windows Phone\v7. Nézzük meg ezt az eszközt használat közben! 1. Keressük ki a ProductID-t a WPAppManifest. Listázni már tudunk. nézzük meg. 8-7 ábra: Mappák és fájlok listázása emulátoron 6.

hogy a gépünkről töltsünk fel adatokat a telefonon futó alkalmazásunk könyvtárába. mint az Isolated Storage esetén − nem oszthatjuk meg a többi alkalmazással! Linq To SQL A Linq To SQL egy ún.com/fcd19b08-f8bc-4397-84bc-c10cd44ca673?SRC=VSIDE 8-9 ábra: A Visual Studióba beépülő Isolated Storage Tool Lokális adatbázisok használata Windows Phone 7-en Lokális relációs adatbázis készítésére és használatára a Windows Phone 7 első (7.microsoft.NET Framework tartalmaz. illetve lehetőséget biztosít arra is. a Mango frissítéssel viszont az Isolated Storage-ben az alkalmazásunk elhelyezhet relációs adatbázist is. és azokat lefuttassuk az adott adatbázismotoron. Az SQL Servernél megszokott Transact SQL segítségével közvetlenül nem érhetjük el az adatbázist. Ezt a kiegészítőt a következő oldalról tölthetjük le: http://visualstudiogallery. amely szintén lehetőséget biztosít arra. ORM (Object Relational Mapping) keretrendszer. olyan eszköz is létezik. hogy adatokat töltsünk le a telefonunkról (vagy emulátorunkról a számítógépünkre). Az adatbázist csak saját alkalmazásunk írhatja és olvashatja.8. Ilyen eszköz például az Isolated Storage Tool (8-9 ábra). az 202 .exe TS xd d25bf842-f28d-45ff-9a4d-6057e6614321 "D:\IsolatedStorage” 8-8 ábra: Fájlok lementése emulátorról Ezen a parancssori eszközön kívül természetesen vannak grafikus modulok is. azt –ugyanúgy. amely egy fájl alapú. Ezt Microsoft SQL Server Compact Edition (CE) teszi lehetővé. amely a Visual Studio-ba épül be. Adatkezelés ISETool. Ahhoz. és így objektumorientált módon kezelhetjük adatainkat.msdn. az alkalmazásba beépülő módon működő relációs adatbázis-kezelő. hogy ez működjön. amelyet a . hogy kódunkban beágyazva fogalmazzunk meg lekérdezéseket. Ezt az adatbázist csak a Linq To SQL API segítségével érhetjük el. sőt.0 –ás) változatában nem volt beépített lehetőség. A Linq To SQL lehetőséget biztosít arra.

ugyanis az adatbázisoknál táblák vannak. amelyben a Countries táblát a Country osztálynak feleltetjük meg! Az itt leírt Country osztály az alkalmazás futtatásánál egy Countries nevű táblát hoz létre az adatbázisban: [Table(Name="Countries")] public class Country { } Ebben a példában a Country nevű adatbázis táblához a megegyező nevű osztály tulajdonságait rendeljük: [Table] public class Country { } 203 . A megfeleletésen kívül szükségünk lesz egy proxy objektumra is. Azon kívül. amely az adatbázist reprezentálja. Ezt a két világot meg kell feleltetni egymásnak. Ennek megértéséhez képzeljük el az alábbi példát: Van egy Users táblánk. hogy jelezzük. ezt DataContextnek nevezzük (8-10 ábra). ezek a tulajdonságok képzik az adatbázis oszlopait. Nézzünk egy példát. ezzel jelezve. Ha megadjuk. Az osztályt ellátjuk egy Table attribútummal. Ezekkel az attribútumokkal definiáljuk. ami megvalósítja a kapcsolatot az adatbázissal és az egyéb specifikus funkciókat is elvégzi. Minden entitás egy „Plain Old CLR Object” (azaz POCO). amelyekben sorok és oszlopok találhatók. hogy az adott objektum milyen módon reprezentálja az adatbázist. hogy ez az osztály tulajdonképpen az adatbázis egy táblájának reprezentációja lesz. akkor automatikusan az osztály neve lesz adatbázis táblájának a neve. tulajdonságainak leírásához. amely az adatbázis tábláit reprezentálja. hogy van egy ilyen osztályunk. amelyek pedig a táblák oszlopait írják le. melynek van egy Name és egy Age oszlopa. akkor az adatbázisban található tábla neve az lesz. míg egy objektumorientált programban entitások és tulajdonságok vannak. Ha nem adunk meg nevet. Az osztály tulajdonságait pedig a Column attribútummal látjuk el. azt speciális attribútumokkal kell ellátnunk az adatbázis speciális megkötéseinek. 8-10 ábra: Lokális adatbázisok DataContext A DataContext egy proxy objektum. amelyek speciális attribútumokkal van ellátva. Minden Table objektum entitásokból épül fel.Lokális adatbázisok használata Windows Phone 7-en adatbázisok világát közelebb kell hoznunk az objektumorientált világhoz. Mapping A mapping maga a megfeleltetés egy adattábla és az azt reprezentáló objektum között. A Table attribútumnál egy Name tulajdonságot is megadhatunk. A DataContext Table típusú objektumokat tartalmaz. Ezt a megfeleltetést nevezzük mappingnek. Egyszerű POCO (Plain Old CLR Object) objektumokat és tulajdonságaikat speciális jelzésekkel – attribútumokkal – jelölhetünk meg. amit megadtunk. amelynek két tulajdonsága van: a Name és az Age. hogy dolgozni tudjunk az adatokon. Ezt a táblát a DataContext-ben egy User osztály reprezentálja.

namespace PhoneDatabase { [Table(Name="Customers")] public class Customer { [Column(IsPrimaryKey=true)] 204 . Adatkezelés A táblákat és az üzleti objektumainkat már egymáshoz rendeltük. OtherKey="TargetEntityID")] Leírás Táblák megfeleltetésére szolgál.8. ehhez létrehozunk egy Customer osztályt. és ellátjuk a megfelelő attribútumokkal. A Name tulajdonságával meghatározhatjuk. amibe felveszünk néhány tulajdonságot. using System. Például ha szeretnénk létrehozni egy táblát az ügyfeleink nyilvántartására. set.Data.Linq névtérre. Adatbázis létrehozása Ahhoz. Az osztályban elhelyezhetünk saját tulajdonságokat. adatbázis állítja-e elő az adott oszlop értékét (Például: AutoIncrement –es ID mező). melyeket a Column attribútummal rendelünk az adatbázis oszlopaihoz. IsDbGenerated=true)] public int ID { get. Nézzünk egy konkrét példát az adatbázis leképezésére! Létrehozzuk a Customer osztályt. set.Linq. Ebben meghatározzuk. Ezek az osztályok lesznek felelősek a mappingért. viszont a táblák oszlopait még nem rendeltük tulajdonságokhoz! Ehhez a Column attribútumot hívjuk segítségül! Csak akkor láthatjuk el a tulajdonságainkat ezzel az attribútummal. hogy az adott nevű adattábla oszlop melyik tulajdonsághoz legyen rendelve: [Table] public class City { [Column(IsPrimaryKey=true. ennek megfelelően ezeket az objektumokat el kell látni a megfelelő attribútumokkal. ha az osztály el van látva a Table jelölővel. Oszlopok megfeleltetésére szolgál.Data. amelyet ellátunk egy Table attribútummal. hogy létrehozzunk egy adatbázist. Táblák közötti kapcsolat meghatározására szolgál (pl. IsUnique=true.Column2 DESC". hogy az adott érték lehet-e null: [Column(CanBeNull=true)] public string Name { get. Name="MultiColumnIndex")] [Association(Storage="ThisEntityRefName". A leképezéshez szükségünk lesz a System. A Column attribútumnál további lehetőségeink is vannak: meghatározhatjuk például. hogy ez az osztály a Customers táblához fog kapcsolódni. és képességeit írja le: Attribútum [Table] [Column] [Index(Columns="Column1. További indexek meghatározására szolgál. hogy készítünk egy egyszerű osztályt. idegen kulcs  elsődleges kulcs kapcsolat). } } A Column attribútumnál határozhatjuk meg azt is. minden index egy vagy több oszlopot fedhet le. Az adatbázist úgy tudjuk létrehozni.Mapping.Mapping. } Az alábbi táblázat a rendelkezésre álló attribútumokat sorolja fel. ThisKey="ThisEntityID". egy DataContext típust és legalább egy entitás osztályt létre kell hoznunk. hogy az adott oszlop elsődleges kulcsú-e.

} } Most már van egy adatbázisunk. public Table<Customer> Customers { get { return customers. és kész a DataContext is. ami ebben az esetben isostore:/Customer. hogy létrehozzuk. } [Column] public string City { get. A tulajdonságot a konstruktorban inicializáljuk. } } } Most már kész az entitás osztályunk.Linq.DatabaseExists()) { db. amiben van egy Customer tábla. Ennek a konstruktornak paraméterként átadjuk az adatbázis eléréséhez szükséges connectionString paramétert. Itt az ideje az adatbázist fizikailag is létrehozni! Ehhez a DataContext példány CreateDatabase metódusát kell meghívnunk.Lokális adatbázisok használata Windows Phone 7-en public int CustomerID { get.Linq névtérben található). set. set. azaz az Isolated Storage legfelső mappájában egy Customer.sdf fájlra hivatkozunk. Ahhoz. Nincs lehetőség valami kényelmesebb. 205 .sdf")) { if (!db. } } } A CustomerID tulajdonságot a tábla elsődleges kulcsaként jelöljük meg. set. hogy az adott adatbázis létezik-e. } } public CustomerDataContext(string connectionString) : base (connectionString) { customers = GetTable<Customer>(). amelyet átadunk a DataContext konstruktorának: using System. vagy lekérdezéseket fogalmazzunk meg ezen a táblán. namespace PhoneDatabase { public class CustomerDataContext : DataContext { private Table<Customer> customers. Ehhez létre kell hoznunk egy újabb osztályt − ezt nevezzük el mondjuk CustomerDataContext-nek! Ezt az osztályt a DataContext osztályból kell származtatnunk (a DataContext a System. } [Column] public string ContactName { get. Célszerű az adatbázis létrehozása előtt ellenőrizni.Data. using (CustomerDataContext db = new CustomerDataContext("isostore:/Customer. szükségünk lesz egy DataContext-re is. set. DataContext példányosításakor meg kell adnunk a connection stringet. } [Column] public string CompanyName { get.Data. megszokottabb módszerre? De van! A következő részben ezzel fogunk megismerkedni. de macerás munka ezt minden esetben manuálisan létrehozni.CreateDatabase(). Hozzuk létre a Customers tulajdonságot. amely legyen Table<Customer> típusú! Ez reprezentálja a Customers táblában lévő adatokat.sdf.

1. előállítsuk hozzá az entitás osztályokat és a DataContextet. 5. ebben a mappában fogja a MyMusic. hogy az adatbázisunk nem lesz levédve. majd a megjelenő helyi menüben válasszuk ki a New Table menüpontot! 206 . A fájl neve ebben az esetben a D meghajtó TestDb mappájára mutat.8. A Database file-nál válasszuk a <New Database…> menüpontot. Ezt követően visszaugrunk a Connect To Server ablakhoz. ha nagyon sok táblánk van. ekkor felugrik a Create New SQL Server Compact Database ablak (8-12 ábra). Ezt követően kattintsunk az OK gombra! Ugyan most kapunk egy figyelmeztetést. 4. Indítás után egy Login képernyő fogad. 8-12 ábra: Create New SQL Server Compact Database Most nem foglalkozunk a titkosítással. így az Encryption mode maradhat UNENCRYPTED. arra is van lehetőségünk. hogy már meglévő adatbázist (sdf) hozzáadjunk a projekthez és kezeljük azt. Nézzük meg ezt az esetet lépésről lépésre! A célunk tehát az. Itt a Server type-nál válasszuk az SQL Server Compact –ot (8-11 ábra)! 8-11 ábra: A Connect To SQL Server dialógus 3. ekkor az SQL Server Management Studio-ból kezelhetjük ezt az adatbázist. majd felhasználjuk egy WP7 alkalmazásban. mégis egy bonyolultabb adatbázis szerkezetének létrehozása sok munkával járhat.sdf adatbázist létrehozni a Management Studio. hogy létrehozzunk egy SQL Server CE adatbázist. különösen. Adatkezelés Adatbázis létrehozása II. akkor legegyszerűbben a Web Platform Installer-rel telepíthetjük fel)! 2. Indítsuk el az SQL Server Mangement Studio 2008 Express változatát (ha ez az alkalmazás nincs meg. de ezzel most ne törődjünk. és a táblák között kapcsolatok is vannak. itt kattintsunk a Connect gombra. és kattintsunk a Yes gombra! A későbbiek folyamán a titkosítással is fogunk foglalkozni. Bár elég egyszerű létrehozni adatbázist úgy. Az Object Explorer-ben kattintsunk a Tables elemre jobb egérgombbal. hogy van egy entitás osztályunk és egy DataContext példányunk. Nemcsak létre tudunk hozni adatbázist.

Az Artist és a Title mezők nvarchar típusúak. A forrásfájlban lesznek az entitásosztályaink. a Windows Phone 7 fejlesztés során mégis nagy hasznát tudjuk venni. ahol az adatbázist elkészítettük (Ez jelen esetben a D:\TestDb mappa). bezárhatjuk az SQL Server Management Studio-t. Az adatbázist Windows Phone alól viszont csak Linq To SQL-lel érhetjük el. a Rating mező int típusú. Ehhez létre kell hoznunk az entitásokat reprezentáló osztályokat. ahogyan azt a 8-13 ábra mutatja! 8-13 . hogy kézzel generáljuk az entitás osztályokat és a DataContextet. majd indítsuk el az SqlMetal. A megjelenő New Table ablakban definiáljuk a Musics adattáblát.cs fájlt (8-14 ábra). valamint a DataContext is. Ez a forrásfájl jelenleg az adatbázis mellett található.sdf-ből készítünk MyMusic. de van szerencsére egy SQLMetal nevezetű eszköz is. ami bár hivatalosan még mindig nem támogatott eszköz. A Command Prompt-ban az egyszerűség kedvéért navigáljunk el abba a mappába.Lokális adatbázisok használata Windows Phone 7-en 6. 8. Most már elkészült az adatbázisunk. 207 . Kattintsunk az OK gombra! 7. Indítsuk el a Visual Studio 2010 Command prompt-ot! 9. Persze itt is megtehetnénk. True értékre állított Identity tulajdonsággal és annak alapértelmezett értékeivel.sdf /code:MyMusic Ebben az esetben a MyMusic.A Musics adattábla definiálása Az ID oszlop egy int típusú elsődleges kulcs.exe alkalmazást az alábbi paraméterekkel: sqlmetal MyMusic.

} Ettől a ponttól kezdve már használatba vehetjük az adatbázist. mégis megkönnyíti a fejlesztést.Net fülre. mappingSource) { OnCreated(). A megjelenő ablakban kattintsunk a . és válasszuk ki a System. Ez azért van. az SqlMetal viszont legenerálta azt. és válasszuk ki a fentebb említett fájlokat! 12.Data' (are you missing an assembly reference?) 15.Data. és válasszuk ki az Add Reference menüpontot! 13.Linq.IDbConnection connection. Adjuk hozzá a projekthez a System. Ahhoz.Data. } public MyMusic(System. akkor a 8-15 ábrán láthatóhoz hasonló hibát kapnánk: MyMusic db = new MyMusic("isostore:/MyMusic. Adatkezelés 8-14 ábra: Az SqlMetal használat közben 10. a következő hibaüzenetet kapnánk: The type or namespace name 'IDbConnection' does not exist in the namespace 'System. de ha megpróbálnánk elérni azt. majd a megjelenő helyi menüben válasszuk ki az Add Existing Item menüpontot.MappingSource mappingSource) : base(connection.Linq névteret! 14. hogy ez a DataContext helyes legyen. Most már kész az adatbázisunk és a hozzá tartozó osztályok is elkészültek! Itt az ideje használatba venni ezeket: indítsuk el a Visual Studio-t. mappingSource) { OnCreated().Linq assembly-t is! Jobb egérgomb a References-re a Solution Explorerben.Data. Igen ám.8. hivatalosan nem is támogatott eszköz. az SqlMetal nem generál teljesen kompatibilis kódot a Windows Phone 7-tel. Ezt követően. Amint elkészült az alkalmazás sablonja. System.Mapping. 208 . ha megpróbálnánk lefordítani az alkalmazást.Data.sdf"). és készítsünk egy új Windows Phone Application projektet (legyen a neve DatabaseSample)! 11. adjuk hozzá az adatbázist és az SqlMetal által generált forrásfájlt! Ehhez a Solution Explorer-en kattintsunk jobb egér gombbal. Mint korábban is említettük.IDbConnection connection) : base(connection. mert a Windows Phone 7 System.Data.Data névterében valóban nem létezik IDbConnection. alakítsuk át a két konstruktort az alábbi módon: public MyMusic(System.

Amint módosítani szeretnénk. mégsem található az Isolated Storage-ban! Ahhoz. 17.Lokális adatbázisok használata Windows Phone 7-en 8-15 ábra: SqlException was unhandled. Ehhez használhatjuk például az alábbi segédmetódust: public class DatabaseHelper { public static void MoveReferenceDatabase() { IsolatedStorageFile iso = IsolatedStorageFile. Az adatbázist most már elérhetjük. azaz csak olvasható az adatbázis tartalma. using (Stream input = Application.CreateFile("MyMusic. egy speciális connection stringet kell megadnunk: MyMusic db = new MyMusic("Data Source = 'appdata:/MyMusic. azonnal egy Permission Denied hibaüzenetet kapnánk. 16.sdf'. Bár Contentre van állítva az adatbázis Build Action tulajdonsága.GetResourceStream(new Uri("MyMusic. de csak lekérdezéseket fogalmazhatunk meg rajta. (Az adatok módosításáról és hozzáadásáról a következő alfejezetben olvashatunk.sdf")) { byte[] readBuffer = new byte[4096]. az adatbázist át kell másolnunk az Isolated Storage-ba.) 8-16 ábra: Permission denied üzenet az adatbázis módosításakor 18. hogy ezt az adatbázist használjuk (Reference Database). UriKind.GetUserStoreForApplication(). Ezt a hibát azért kapjuk. hogy ezt elkerüljük. The Database file cannot be found.Stream) { using (IsolatedStorageFileStream output = iso. mert az IsolatedStorage-ban nem szerepel ez az adatbázis. amint azt a 8-16 ábra is mutatja. 209 . File Mode = read only").Relative)). és az XAP-ban is benne van ez az adatbázis. int bytesRead = -1. Ahhoz.sdf".

210 .Write(readBuffer. 0. A lekérdezések szintaktikája nagyon egyszerű: akár Linq szintakszis használatával. hogy példányosítjuk a megfelelő entitás osztályt. ----------------------------------------------------------------------------------------var result = db. módosítani az adatbázis tartalmát. CompanyName = "Livesoft".Customers.Length)) > 0) { output. ContactName = "Attila Turoczy". és a tulajdonságait feltöltjük a kívánt értékekkel. bytesRead). Ne felejtsük el. db. mint a T-SQL-nél! Egyszerűen csak annyi a dolgunk. Amint meghívjuk a MoveReferenceDatabase metódust. és ezek után a megszokott módon tudjuk lekérdezni.sdf"). amíg a SubmitChanges metódust meg nem hívjuk: Customer myCust = new Customer() { CustomerID = 1. Nézzünk néhány lekérdezést! A következőkben mindkét lekérdezési formát bemutatjuk.Customers select c. itt az ideje megismerkedni azzal. hogy már meglévő adatbázist használjunk fel a Windows Phone 7 készülékünkön. Adatok lekérdezése − SELECT Az adatok lekérdezéséhez is a Linq To SQL-t hívjuk segítségül. Ha csak olvasható adatbázist akarunk használni. City = "Budapest" }.Customers. Bár ez a módszer nem teljesen támogatott. Az összes adat lekérdezése: var result = from c in db. hogy milyen lépéseket kell megtennünk ahhoz. hogy hogyan töltsük fel az adatbázist adatokkal. akkor egyszerűen csak hozzáadjuk az adatbázist és az legenerál egy forrásfájlt a projektünkhöz. Az adatbázisban mindaddig nem kerül az új rekord letárolásra. Adatkezelés while ((bytesRead = input. majd ezt az osztálypéldányt átadjuk az InsertOnSubmit metódusnak. 0. mégis nagyon sokszor hasznos lehet.SubmitChanges(). Az adatbázisunk még üres. és hogy hogyan kérdezzük le azokat! Adatok felvitele − INSERT A Linq To SQL használata során nem kell INSERT SQL Scriptet írnunk. ha azonban módosítani is szeretnénk. az átmásolja az adatbázist az Isolated Storage-ba.8. db.Read(readBuffer. Láthattuk. akkor egy segédmetódust is definiálnunk kell az adatbázist mozgatásához.Select(s => s). hogy ebben az esetben a connection stringet a hagyományost isostore értékre kell visszaállítanunk: MyMusic db = new MyMusic("isostore:/MyMusic. readBuffer.InsertOnSubmit(myCust). akár bővítő metódusokkal le tudjuk kérdezni az adatainkat. } } } } } 19.

foreach (var item in result) { item. hogy a szintaktika logikusan felépített. Sorbarendezés: var result = from c in db.Select(s => s. Ha az eredményhalmazt szűkíteni szeretnénk. majd minden ügyfelünk városát átírjuk Seattle-re. hogy a lekérdezett adatok tulajdonságát átírjuk a megfelelő értékre.City select c. használata nagyon egyszerű. 211 . mint korábban. mindössze annyi a dolgunk.SubmitChanges().City == "Budapest"). akkor is nagyon egyszerű dolgunk van: csakúgy. amit törölni szeretnénk.Customers. majd meghívjuk a SubmitChanges metódust. db. adjuk át paraméteréül a DeletOnSubmit metódusnak.City == "Budapest" select c. Adatok módosítása − UPDATE Ha frissíteni szeretnénk az adatbázis tartalmát.City = "Seattle".Customers.First().CustomerID == 1 select c). ----------------------------------------------------------------------------------------var result = db. Az alábbi példában lekérdezzük az összes ügyfelünket. Látható. és a végén meghívjuk a SubmitChanges metódust: var result = from c in db. ----------------------------------------------------------------------------------------var result = db. Válasszuk ki azt az rekordot (objektumot).Customers.Customers select c.DeleteOnSubmit(selectedItem).Lokális adatbázisok használata Windows Phone 7-en Egy oszlop lekérdezése: var result = from c in db.Where(s => s.OrderBy(s => s. akkor egy where feltételt kell meghatároznunk: var result = from c in db. és hívjuk meg a SubmitChanges-t! var selectedItem = (from c in db.Customers. } db.CompanyName). Adatok törlése − DELETE Ha az adatbázisunkból szeretnénk törölni adatokat.Customers orderby c. db.SubmitChanges().CompanyName.Customers where c.Customers select c. itt sem kell SQL Script-eket írnunk. az is rendkívül egyszerűen kivitelezhető. ----------------------------------------------------------------------------------------var result = db.Customers where c.City).

Nyissuk meg a ShopItem. IsDbGenerated=true)] public int Id { get.Linq. set. Ha az adatbázis titkosított. nekünk csak az adatbázist kell megterveznünk. Adatkezelés Az adatbázis biztonsága A lokális adatbázis lehetőséget biztosít arra. } Adatbázis kezelés gyakorlat A következő gyakorlatban egy mini bevásárlólista alkalmazást fogunk elkészíteni. } 212 . illetve a lekérdezéseket megírni. } [Column] public string Title { get. hogy milyen oszlopokkal szeretnénk dolgozni. Az alábbi példában látható. és azt csak jelszóval tudjuk elérni.CreateDatabase(). A kiinduló projektet a http://devportal.Mapping. majd oldjuk fel a System.DatabaseExists()) { db. A ShopItem osztály definícióját lássuk el a [Table] attribútummal! [Table] public class ShopItem { 4.sln fájlt! 2. Indítsuk el a Visual Studio 2010-et és töltsük be a LocalDatabaseDemo.Password='Pa$$word1'"). set. Ezt a jelszót a connection string-ben kell átadnunk! Az adatbázis titkosításához AES-128. A ShopItem törzsét a következő módon alakítsuk ki: [Column(IsPrimaryKey=true. csak jelszóval érhetjük el.sdf'. míg a jelszóhoz az SHA-256 titkosítási eljárást használja a rendszer. 3.Linq.hu/wp7 oldalról tölthetjük le.Data.8.cs fájlt az Entities mappán belül. 8-17 ábra: A bevásárló alkalmazás egy képernyője 1.Mapping névteret! using System. hogy az adatbázis tartalma titkosítva legyen. Az alkalmazás felhasználó felülete már előre el van készítve (8-17 ábra). if (!db. hogyan hozzunk létre egy biztonságos adatbázist: CustomerDataContext db = new CustomerDataContext("Data Source='isostore:/Customer. Meg kell határoznunk.Data.

és az Application_Startup metódusban hozzuk létre az adatbázisunkat a CreateDatabase metódus segítségével! Abban az esetben. public Table<ShopItem> ShopItem { get { return shopItem. Nyissuk meg az App. set. Látható.Text) }. Price = Convert. majd oldjuk fel a System. de még üres. és navigáljunk el a save_Click eseményhez. hogy az adott terméket megvettük-e már.Lokális adatbázisok használata Windows Phone 7-en [Column] public int Price { get. } 8.cs fájlt. Speciális eset az Id tulajdonság. nem történik semmi. a Price tulajdonságban a termék hozzávetőleges árát. hanem azt is.xaml.Data. Létre kell hoznunk egy DataContextet is. ha már létezik az adatbázis.Linq névteret! using System. set.Data. Már elkészült az adatbázisunk. amely értékét az adatbázis fogja előállítani.DatabaseExists()) { db. A ShopDataContext kódját pedig a következőképpen írjuk meg: private Table<ShopItem> shopItem.xaml.sdf"). A ShopDataContext osztályt származtassuk le a DataContext osztályból! public class ShopDataContext : DataContext { 7.shopItem = GetTable<ShopItem>(). } } public ShopDataContext(string connectionString) : base(connectionString) { this. hogy az adatbázishoz tudjunk kapcsolódni. míg az IsBought azt mutatja.sdf"). ShopItem shopItem = new ShopItem() { Title = txtTitle. hogy a tulajdonságok mindegyikét egy [Column] attribútummal láttuk el. Nyissuk meg a ShopDataContext. } A Title tulajdonságban tároljuk el a vásárolni kívánt termék nevét. } [Column] public bool IsBought { get. ugyanis nemcsak azt jelöljük. Ezzel kész az entitásosztály definíciója. hogy ez egyúttal egy olyan elsődleges kulcs.CreateDatabase(). 213 . } 9.cs fájlját. majd adjuk hozzá az alábbi kódsorokat: try { ShopDataContext db = new ShopDataContext("isostore:/shop. hogy ez egy oszlop.Text.cs fájlt. 6. if (!db.ToInt32(txtPrice.Linq. ShopDataContext db = new ShopDataContext("isostore:/shop. 5. Töltsük fel adatokkal! Nyissuk meg a Pages mappa NewShopItem.

Adatkezelés db. hogy a kiválasztott termékeknek mennyi a teljes ára: if (db.ToInt32((e. aminek megadunk egy connection string-et (ezt globálisan is megtehetnénk).ShopItem.Content.Count() > 0) { txtSum. 10.FirstOrDefault(). } Itt egy ShopDataContext-et példányosítunk. így az alapértelmezett értéke a false lesz. 11. db.Navigate(new Uri("/MainPage. "Hiba!". Azért. UriKind. hogy mennyivel tud többet a Linq. hogy lássuk. db.8. hogy ha vásárolunk valamit a listáról. majd a SubmitChanges metódussal eltároljuk az adatbázisba.Show("Hiba: " + ex. akkor megvizsgáljuk azt is.Id == selectedIndex select c). amiket még nem vettünk meg! lstShopItems. amit nem vettünk még meg! Ha ennek az értéke nagyobb.InsertOnSubmit(shopItem).ShopItem.Where(s => s.Text = "0 Ft".DataContext = from c in db.OriginalSource as Button). akkor kihúzzuk azokat a termékeket. Ezt követően egy ShopItem példányt hozunk létre.ShopItem where c. 12. } catch (Exception ex) { MessageBox.IsBought == false select c.sdf"). 214 . amely tulajdonságainak az értékeit a felhasználói felületi hozzá tartozó elemei határozzák meg. var selectedItem = (from c in db.Relative)).IsBought == false). és kérdezzük le azokat a termékeket az adatbázisból. hogy hány darab olyan termékünk van.ShopItem . Ehhez navigáljunk el a btnCheck_Click eseményhez és írjuk be a következőt: int selectedIndex = Convert.ToString()).Where(s => s. fejlesszük tovább a GetData metódust: egy feltételben vizsgáljuk meg. mégpedig az.SubmitChanges(). A konstruktor előtt most hozzunk létre egy ShopDataContext példányt! (Task – 9) ShopDataContext db = new ShopDataContext("isostore:/shop. MessageBoxButton. Nem töltöttük ki az IsBought tulajdonság értékét.Message.Sum(s => s.IsBought == false). meghívjuk az InsertOnSubmit metódust. Navigáljunk el a GetData metódusba.ShopItem where c.Text = String. } else { txtSum.xaml". amelyeket már betettünk a kosárba.OK). Itt az ideje megjeleníteni az adatainkat. azaz még nem vásároltuk meg az adott terméket. } 13. mint nulla. Már csak egy lépés maradt hátra. NavigationService.Price)).Format("{0} Ft". Ezt követően visszanavigálunk az eredeti oldalra. Ha ez megvan.

Ezután lekérdezzük az adott azonosítójú terméket az adatbázisból. 215 . db. de a háttérben bele van írva az adott termék azonosítója (Id tulajdonság). akkor az objektum alapértelmezett értékével tér vissza. hogy hogyan működik! Kattintsunk az új ( + ) gombra. Abban az esetben. hogy a Windows Phone 7 készülékeken is a .NET-ben megszokott. letisztult megoldásokat kapjuk.SubmitChanges(). akkor az adatokat elmentjük az adatbázisba. amely az első elemet veszi ki a visszaadott eredmény gyűjteményből. } GetData(). Ha ez az érték nem null. ahol az előzőleg felvitt termékek láthatóak. Abban az esetben. majd meghívjuk a SubmitChanges metódust. Az egyszerűség kedvéért ezt követően meghívjuk a GetData metódust. valamint hogyan lehet az adatokat egy relációs adatbázisban eltárolni. ha nincs ilyen azonosítójú elem. 14. Első lépésben lekérdezzük a terméket reprezentáló gomb tartalmát. és nézzük meg. akkor az IsBought tulajdonságot true értékre állítjuk. Az ugyan nem jelenik meg a felhasználói felületen. nézzük át újra a lépéseket. itt elérhető a Linq To SQL technológia.Összefoglalás if (selectedItem != null) { selectedItem. Ahogyan Silverlight alatt is van Isolated Storage. majd kattintsunk a termékek neve melletti pipára! Miután rányomtunk. A Linq kifejezés végén egy FirstOrDefault bővítő metódus áll. Indítsuk el. beállításokat eltárolni. hogy hogyan is kell a Windows Phone 7 alkalmazásokban adatot kezelni: hogyan kell adatokat lementeni. amivel újra lekérdezzük az összes nem megvásárolt terméket és az ezekhez tartozó összeget. és a hibákat javítsuk! Összefoglalás Ebben a fejezetben megnéztük. és az összesen értéke is a kipipált elem értékével csökken. ha ez a folyamat mégse így történne. Ezt követően a főképernyőn találjuk magunkat. és adjunk hozzá egy új terméket! Amikor a mentés gombra kattintunk. Láthattuk. Elkészült az alkalmazásunk. az adott elem kikerül a listából. Vigyünk fel még néhány elemet.IsBought = true.

.

5 (Mango) már tartalmaz közvetlenül a telefonon futó SQL adatbázist. A felhő segítségével percek alatt. aminek legjobb módja. és utána biztonsági szempontból    217 . így az adott hírforrást szabványos módon olvashatjuk – miközben a hírportál honlapja természetesen lehet bármilyen egyedi. Adatbázis-elérés: a Windows Phone 7. Webszolgáltatások segítségével természetesen írhatunk saját hitelesítési mechanizmust. hiszen a többi telefonon futó alkalmazáspéldány nem fér hozzá. de ezzel nem kell fáradnunk. akkor óhatatlanul felmerül a felhasználó bejelentkeztetésének kérdése. legyen szó RSS feedekről. Így a webszolgáltatásokat könnyen alkalmazhatjuk. mert sokat kell kódolnunk. Ez egy széles körben elterjedt formátum. rugalmasan juthatunk számítási kapacitáshoz. A platform ehhez gazdag támogatást nyújt. hogy minden Windows Phone operációs rendszert futtató készüléknek legalább 256 megabájt memóriával és 1 GHz körüli processzorral kell rendelkeznie. Ilyen esetekben egy központi szerveren futó adatbázist célszerű igénybe venni. Windows Phone alkalmazásaink bármilyen internetes tartalmat letölthetnek. a telefonalkalmazásunkban lévő műveletről lenne szó. Ezek mindegyikéhez csatlakozhatunk telefonalkalmazásainkból. és nem alkalmas egy komolyabb alkalmazás (mondjuk egy raktárkezelő) központi adatbázisának. A fejezetben ennek különféle lehetőségeit ismerjük meg. a SharePoint. tárhelyhez vagy épp adatbázishoz. feldolgozhatnak. hogy a számításigényesebb feladatokat kiszervezzük – célszerűen szerveroldalra. Az OData szabvány segítségével rengeteg adatforrást tudunk manipulálni a fejlesztő számára egyszerű módon.9. Fontos tehát. paramétereit és visszatérési értékét (pl. Ennek elérését megoldhatnánk egy sor egyénileg fejlesztett webszolgáltatással (írás. Kommunikáció szerverrel A telefonok hardvere robbanásszerűen fejlődik. Egy sor szabványos technológia segítségével kliensünk (ez esetben a telefon) ezt a metódust ugyanúgy hívhatja meg. olvasás. HTML oldalakról vagy bármilyen más fájlról. Felhasználó-hitelesítés: Ha internetre csatlakozó alkalmazást írunk. központi adatbázissal való kapcsolat lehetőségét. a felhasználók elvárják a többi felhasználóval. Ennek kapacitása természetesen szűkös. Legyen szó szinte bármilyen alkalmazásról. Ezenfelül épp napjainkban lehetünk tanúi a számítási felhő térhódításának. Webes tartalom közvetlen elérése: Az internet tartalmának túlnyomó része HTML. Ez azt jelenti. mint egy netbook. törlés minden egyes táblára). string GetName(int userId)). olcsón. A webszolgáltatások segítségével szerverünk kiajánlhat egy műveletet. és fájlok képében érhető el. mintha egy helyben. Ezért nagyon fontos spórolnunk az akkumulátor kapacitásával. A legsúlyosabb korlátozást viszont nem is a számítási kapacitás adja. amelynek megadja a nevét. hogy Windows Phone alkalmazásunk kommunikálhasson külső szerverekkel. Remek példa erre az RSS feed. hogy egy rendszeresen használt okostelefon 1-2 napnál tovább bírja újratöltés nélkül. A kommunikáció módjai A legfontosabb kommunikációs módszerek egy alkalmazás fejlesztése során:  Webszolgáltatások: A webfejlesztés világában régóta bevett technológia. Az SQL Server. A Microsoft kötelezően előírta. Egy másik ilyen lényeges trend a közösségi média rohamos terjedése. amivel időben gyorsan változó híreket írhatunk le. hanem az akkumulátor: ritka. de ez nekünk és felhasználóinknak is kényelmetlen. valamint számos további Microsoft és külső fejlesztők által készített program és webes alkalmazás is használható OData kiszolgálóként. hogy a telefonok nagyságrendileg olyan erősek. és a távoli szervert alkalmazásunk szerves részeként használhatjuk. Nekünk azért.

 Webszolgáltatások használata A webszolgáltatások működése Amint a bevezetőben már volt róla szó. és befogadja a szervertől kapott választ. Ha valamelyiket meghívjuk. Ezek fordítják le az internet felől beérkező kérést a metódust futtató programnyelv számára értelmezhető formára. Ilyen lehet például a felhasználó által feltöltött fényképalbum. Ha a proxy osztály szinkron működésű. Ennek működéséhez persze egy sor technológia kell. fejezetben van bővebben szó. a webszolgáltatás meghívásakor a háttérben valójában két művelet történik: a proxy osztály egyrészt elküld egy kérést. egy webszolgáltatás nem más. Amint láttuk. Ez programozói szempontból egyszerű. az épp megnézett terület a Bing Maps szolgáltatásból töltődik le. amit az interneten keresztül is meghívhatunk. és ezek küldik aztán vissza a metódus futási eredményét a kérőnek. melyek szerveroldalról is frissíthetők anélkül. mint egy szerveren lévő metódus. Egy osztálykönyvtár segítségével közvetlenül a telefonról írhatjuk és olvashatjuk a Windows Azure tárhelyszolgáltatását. Google. de minden más szerveroldali technológia is ad lehetőséget webszolgáltatások készítésére. akkor a két háttérműveletet egy egységként kezeli. Ilyenkor többnyire (a használt technológiától függően) egy XML formátumú leíró fájl jön létre. Természetesen nem tárolódik a teljes világtérkép a telefon memóriájában. A Windows Phone platform ezenkívül néhány egyedi telefon-szerver kommunikációs funkciót is biztosít. Ennél van jobb megoldás is: a Windows Azure egyik szolgáltatását kihasználva például felhasználóink meglévő Live ID. Kommunikáció szerverrel kritikus infrastruktúrát kell üzemeltetnünk. hogy a webszolgáltatások komplex internetes kódjával egyáltalán nem kell bajlódnunk – az oda-vissza fordítást (az angol plumbing szó magyar fordításával„vízvezeték-szerelést”) elvégzi helyettünk a fejlesztőkörnyezet. A felhasználóinknak pedig azért. fejezetben található részletes leírás. Saját szerverrel és webszolgáltatással természetesen ez is megoldható. A fentiek segítségével szinte bármilyen kommunikációs igénynek meg tudunk felelni. videó vagy dokumentum. kódunk addig nem is halad tovább. A fejlesztés során a programozó először meghatározza. Mindez azt jelenti. Push Notifications: A Windows Phone platform kulcsfontosságú elemét alkotják a telefon kezdőképernyőjén látható lapkák. és tartalmazza a leírófájlban található összes metódust.NET-világban erre a Windows Communication Foundation-t (WCF) használjuk. hogy milyen metódusokat szeretne kiajánlani. mert még egy név/jelszó párost kell megjegyezniük. A fejlesztőkörnyezet ebből egy úgynevezett proxy osztályt generál. hogy alkalmazásunknak futnia kellene.  Adattárolás: Az OData segítségével könnyedén tárolhatunk adatsorokat. amíg a háttérben történő műveletek be nem fejeződtek. Kódunk szemszögéből mindez tűnhet szinkron vagy aszinkron műveletnek. Ezekről a 10. de a rekordok mellett gyakran fájlokat is el kell mentenünk. Ezután a kliensoldalon az ottani fejlesztőkörnyezet számára megadjuk ezt a leíró fájlt. C#-ban) készül. Ezekről a speciális funkciókról a könyv további fejezeteiben lehet olvasni:  Maps: Telefonalkalmazásunkba beépíthetünk térkép-vezérlőt. Facebook vagy Yahoo fiókjukkal jelentkezhetnek be alkalmazásunkba. Az ebben közzétett információ tartalmazza a metódus visszatérési értékét. nevét és elvárt paramétereit (a bevezetőben látott példa: string GetName(int userId)). Ez az osztály már a kliensoldalon használt programnyelvben (pl. A kliensoldali programkódunkból ezeket a metódusokat tudjuk használni. A . azaz miután meghívtuk a proxy osztály valamelyik metódusát.9. A fejezet során a fentiek közül mindegyiket részletesen megismerjük. majd elkészíti a szolgáltatást. akkor a proxy osztály generált kódja elküldi kérésünket az interneten keresztül. A Maps vezérlőelemről és képességeiről a 4. de a platform erre is nyújt kész megoldást. másrészt megvárja és lefordítja a választ. ám a felhasználói élményt 218 .

svc. Ha viszont a Visual Studio valamelyik fizetős verzióját használjuk.cs kódfájl. 9-1 ábra: A webszolgáltatás hozzáadása A szolgáltatás hozzáadása után három elem is létrejön projektünkben: az ISampleService. Mi a WCF-et használjuk majd. ezen sorok írásakor fejlesztés alatt álló verziójában szerepelni fog az async kulcsszó. Webszolgáltatás egy mintaalkalmazásban Írjunk egy Windows Phone alkalmazást.NET Empty Web Application típusú új projektet. de futásidőben ezt a fájlt kell majd meghívni kívülről 219 . de a felhasználói élménynek nagyon jót tesz. és így tudjuk folytatni programunk működését. Az ISampleService.Webszolgáltatások használata ronthatja. Ezt elkerülendő a Windows Phone által generált proxy osztályok csak aszinkron működésűek lehetnek. és nevezzük ezt el WebServiceServerSample-nek! A projekt létrejöttekor üres.svc leírófájl és az ehhez tartozó SampleService.cs állományban kell definiálnunk a kiajánlani kívánt metódusokat. Amikor meghívjuk a proxy valamelyik metódusát. akkor szükségünk lesz az ingyenes Visual Web Developer Express változatra is. A SampleService. Ez egy ASMX kiterjesztésű fájlt hoz létre. és az alkalmazásunk ezalatt „lefagyottnak” tűnhet. és ma már egy előző generációs technológiát képvisel. A válasz megérkezésekor az általunk megadott eseménykezelő fut majd le. Mindhárom elemnek fontos szerepe van a webszolgáltatás létrehozásában. ami egy webszolgáltatást hív meg! Kezdjük a webszolgáltatással! Ehhez kell majd egy webfejlesztésre alkalmas Visual Studio verzió. a SampleService. Jó hír. akkor az alkalmas lesz mindkét típusú fejlesztésre. akár az internetkapcsolat lassúsága miatt) néha másodpercek is eltelhetnek. azaz a kérés elküldését és a válasz megérkezését különválasztják. Hozzunk létre benne egy új webszolgáltatást! Ehhez vegyünk fel a projektbe egy WCF Service típusú elemet SampleService néven! A listában (lásd 9-1 ábra) láthatunk egy Web Service-nek keresztelt elemet is. Mivel kódunkat emiatt szét kell darabolnunk. A webszolgáltatás meghívása és válasza között (akár a szerver terheltsége. ez csak egy interfészt ad majd.NET Frameworkön belül.cs kódfájl. fejlesztői szempontból ez kicsit kényelmetlenebb. Hozzunk létre egy ASP.svc jelenleg egy sorból áll. hogy a C# nyelv 5-ös. ami az aktuális webszolgáltatás-fejlesztő eszköz a . Ha a Visual C# Express van a gépünkön a Windows Phone fejlesztéshez. fel kell iratkoznunk a válaszra. ami nagyon megkönnyíti majd az aszinkron műveletekkel való programozást. a tényleges kód nem ide kerül.

hogy webszolgáltatásunk sikeresen lefordult. hogy a metódust meg szabad hívni az internet felől is (azaz ki kell kerülnie a leírófájlba). hogy megírhassuk. de itt nem tárgyalt WCF konfigurációs okok miatt célszerű használni. A fájlt megnyitva láthatjuk. 220 . ami egy [OperationContract] attribútummal van ellátva.svc. kifejezetten fejlesztésre való webszerver. meghívható. mi pedig visszaküldjük azt angolul.cs fájlt! Itt szintén látjuk majd a DoWork() metódust (ezúttal már attribútum nélkül). egyszerű.cs-be kerül az ISampleService. és a 9-2 ábrához hasonló weboldal tárul elénk. e fájl nélkül is működhet a szolgáltatás. hogy egy void DoWork() nevű metódus már létezik. Bemutató alkalmazásról lévén szó. Nevezzük át ezt a metódust az általunk kívántra! [OperationContract] string Translate(string input). és egy string változót is ad vissza. ez tudatja a futtatókörnyezettel.NET Development Server (Cassini) lesz.cs interfészben. Az ehhez szükséges metódus egy string változót vár.cs-ben deklarált metódusok tényleges kódja. } } Ezzel a szerveroldallal gyakorlatilag el is készültünk.svc.cs nem létfontosságú. Kommunikáció szerverrel a szolgáltatás eléréséhez.) Egy egyszerű fordítási szolgáltatást készítünk: a telefonalkalmazás felküld egy szót. Most írjuk meg a metódushoz tartozó kódot! Ehhez nyissuk meg a SampleService. mert ezen a néven generálja majd a futtatókörnyezet a korábban már tárgyalt leírófájlt. } else { return "(ismeretlen)". vagy az IIS Express. Az attribútum nagyon fontos. } else if (input == "szilva") { return "plum". először deklarálnunk kell az ISampleService. Töröljük ki. Beállítástól függően ez vagy az ASP. Néhány másodpercen belül megnyílik az alapértelmezett böngészőnk. Ahhoz. (Az ISampleService. Végül a SampleService.9. Teszteljük működését! Az F5-tel indítsuk el alkalmazásunkat! Ennek hatására elindul egy helyi gépünkön futó. és helyettesítsük az alábbi kóddal! public string Translate(string input) { if (input == "alma") { return "apple". Ez igazolja. „szótárunk” mindössze két szót tartalmaz majd.

és minden gépen más lesz. neve pedig WebServiceClientSample! A projekt létrehozását követően a Visual Studio megkérdezi majd. és készíti el a bevezetőben említett proxy osztályt. E művelet során olvassa majd be a Visual Studio a szerverünk által publikált leíró állományt. Adjunk egy nevet a referenciának (SampleServiceReference). Most térjünk át a kliensoldalra. később még szükség lesz rá! A fent leírtak gyakorlatilag változtatás nélkül működnek akkor is. fel kell rá vennünk egy referenciát. A /SampleService. és kattintsunk az OK gombra! 221 .svc elérési útnak viszont szerepelnie kell. és írjuk meg a szervert meghívó Windows Phone alkalmazást! Ehhez nyissunk egy új Visual Studio projektet. amely legyen Windows Phone Application típusú. ha nincs ott. hogy használhassuk a webszolgáltatást. és válasszuk az Add Service Reference menüpontot! A megjelenő párbeszédpanel tetejére írjuk be a korábban kimásolt URL-t. majd a párbeszédpanel közepén található területen megjeleníti az általa támogatott metódusokat (lásd 9-3 ábra). ha a szerveroldalon Windows Azure-t használunk. Referencia felvételéhez kattintsunk jobb gombbal a projekt nevére (WebServiceClientSample) a Solution Explorer ablakban. kézzel írjuk be! Az URL-t jegyezzük meg. Válasszuk a Windows Phone OS 7.Webszolgáltatások használata 9-2 ábra: A fejlesztői szerverből kiszolgált webszolgáltatás Ha egy üres oldalt vagy valamilyen hibaüzenetet látunk. majd kattintsunk a Go gombra! (Fontos.1 (vagy valamelyik újabb) változatot! Ahhoz. hogy webes projektünknek még futnia kell!) A Visual Studio letölti és feldolgozza a megcélzott webszolgáltatás adatait. akkor ellenőrizzük az URL-t! A localhost nevet követő portszám véletlenszerűen generált. hogy a telefon melyik verziójához készítjük a projektet. Jelenleg egy ilyet tartalmaz a webszolgáltatásunk: az imént megírt Translate() metódust.

ClientConfig néven találjuk meg projektünkben.SampleServiceClient client = new SampleServiceReference. ezért kézzel kell hozzáadnunk alkalmazásunk XAML kódjához. client. Ezt ServiceReferences. ami a Windows Phone „mozgó pontjait” generálja. Ha alkalmazásunkat élesben szeretnénk felhasználni. Most kattintsunk duplán a gombra. Hozzuk létre programunk felhasználói felületét! Ehhez helyezzünk ki egy szövegdobozt és egy gombot a tervezőfelületre! A szövegdoboz neve legyen MessageTextBox. bekapcsoljuk a ProgressBar-t: private void TranslateButton_Click(object sender. ami a kérés befejezését jelzi majd.TranslateCompletedEventArgs>( client_TranslateCompleted). Ezenfelül. elég csak ki-be kapcsolnunk). hogy épp hány százalékon áll. de amint korábban már szó volt róla. amely MainProgressBar névre hallgat és alapértelmezésként nem látható. hogy a felhasználó felé jelezhessük a háttérben zajló munkát. Keressük meg a XAML kódban a gombunkat leíró sort (<Button>). 222 . amikor a telefon dolgozik valamin)! A ProgressBar nem látható az eszköztáron. és ez alá szúrjuk be az alábbi kódot: <ProgressBar Name="MainProgressBar" IsIndeterminate="True" Visibility="Collapsed"></ProgressBar> Ezzel létrehoztunk egy határozatlan futású ProgressBart (azaz nem kell megadnunk. akkor ebben az állományban kell átírni a webszolgáltatás URL-jét a végleges címre.9. Kommunikáció szerverrel 9-3 ábra: A Service Reference-hozzáadó ablak A Visual Studio legenerálja a proxy osztályt. RoutedEventArgs e) { SampleServiceReference. a webszolgáltatás aszinkron.TranslateCompleted += new EventHandler<SampleServiceReference. hogy belépjünk a Click eseménykezelőjébe! Kódunknak meg kell hívnia a webszolgáltatást. Ezért meghívásához először feliratkozunk arra az eseményre.SampleServiceClient(). aztán ténylegesen elküldjük a kérést. és tulajdonságait elhelyezi egy új fájlban. a gomb neve pedig legyen TranslateButton! Az igazán elegáns megoldás érdekében ezután helyezzünk el egy ProgressBart is (ez az a vezérlőelem.

Error. annak gazdag Windows Communication Foundation irodalom áll a rendelkezésére. Ez mindössze annyit tesz. hogy az átküldeni kívánt objektumnak sorosíthatónak kell lennie.Visibility = Visibility. } else { MessageBox. Ha ez később változik. akkor a proxy osztályt is frissítenünk kell. Az itt leírtak már elegendőek egyszerű kliens-szerver kommunikáció létrehozásához.Show(e. A legtöbb . hogy megjeleníti a webszolgáltatástól kapott választ. 223 . hanem kezeljük a hibát. melynek most csak a felszínét karcolgattuk.TranslateAsync(MessageTextBox.ToString()). és megjelenítjük azt a felhasználó számára.Text). SampleServiceReference.Error != null) { MessageBox. Ehhez kattintsunk jobb gombbal a létrejött referenciára. Lényeg. megjeleníti a ProgressBar-t.Collapsed. a saját osztályainkat pedig mindössze el kell látnunk a [Serializable] attribútummal. majd kisvártatva megkapja és megjeleníti a választ (lásd pl 9-4 ábra). Mivel a szolgáltatás meghívása az interneten keresztül történik.Result). fel kell készülnünk az esetleges hibákra! Ha hiba történik. hanem komplex változók is használhatók a kommunikáció során.Visible. Ez a technológia egy óriási témakör. } A kérés befejezésekor lefut az eseménykezelő.NET adattípus ilyen.Show(e. Ilyen például egy generikus lista (List<string>). 9-4 ábra: A végrehajtott webszolgáltatás-hívás eredménye Ezzel megismertük egy új webszolgáltatás létrehozását. egy saját magunk által létrehozott adattípus (Employee) vagy szinte bármi más. } } Ezzel elkészültünk a mintaalkalmazással. Aki ennél jobban szeretne elmélyedni a webszolgáltatások használatában. if (e.TranslateCompletedEventArgs e) { MainProgressBar. Nemcsak a primitív adattípusok. hogy alkalmazásunk elindítja a kérést.Webszolgáltatások használata client. és válasszuk az Update Service Reference menüpontot! A webszolgáltatások segítségével lényegében tetszőleges kommunikációt lebonyolíthatunk telefonunk és egy szerver között. hogy a webalkalmazás még mindig fut-e)! Írjunk be egy magyar szót (legyen „alma” vagy „szilva”)! Látni fogjuk. void client_TranslateCompleted(object sender.Visibility = Visibility. MainProgressBar. Teszteljük le! Indítsuk be a telefonalkalmazást (és győződjünk meg róla. egy tömb (int[]). akkor nem hagyjuk programunkat lefagyni.

amit átadtunk a callback metódusnak.com"). A Stream változó string változóba olvasásához szükségünk lesz a System. ezt az objektumot a meghívott callback függvény is megkapja. request). mert ettől a példánytól tudjuk majd elkérni a beérkezett HTTP választ. Ezeket az interneten használt HTTP protokoll segítségével tudjuk elérni. Utána ezen a példányon meghívjuk az EndGetResponse() metódust. ha a válasz beérkezett. A létrehozott HttpWebRequest példánynak mindenképpen szerepelnie kell benne. Gyakran előfordul azonban. itt is kizárólag aszinkron metódusokat használhatunk.1 vagy újabb verzióval! Vegyünk fel a felületére egy HttpButton nevű gombot. } Most készítsük el a RequestCallback nevű metódust. amely egy HttpWebResponse példányt hoz létre. Alapvetően két. Ez tartalmazza a beérkezett HTTP választ. Hozzunk létre egy Windows Phone Application típusú projektet HttpSample néven.NET-es tapasztalatainkból már ismerősek lehetnek.example. így egyéb . ezért helyezzük az alábbi sort a kódfájl legtetejére: 224 . mert talán ez a legjobb módja a használható technikák megismerésének. A konkrét kód azonban kissé másképpen néz ki. hogy szükségünk lenne a HTTP válaszra. mint a webszolgáltatások esetében. ha pedig pontosabb irányításra van szükségünk. Írjuk meg a gomb Click eseménykezelőjét az alábbiaknak megfelelően: private void HttpButton_Click(object sender.com weboldalt fogjuk majd letölteni és megjeleníteni. request. Az előző alfejezethez hasonlóan most is egy példaalkalmazást készítünk. Ennek oka is hasonló: egy letöltés több másodpercet is igénybe vehet.9. az alkalmazásnak ez idő alatt nem szabad lefagyottnak tűnnie. amit egy eseménykezelővel kaptunk el. egy HTML oldal vagy valamilyen fájl.Create("http://www. mint egy absztrakciós réteg a HttpWebRequest/HttpWebResponse felett. vagyis azt bármilyen állapot-információ átadására is használhatjuk. Először is „kicsomagoljuk” a HttpWebRequest példányt.BeginGetResponse(RequestCallback. majd dupla kattintással lépjünk be a Click eseménykezelőbe! Ahogy a webszolgáltatásoknál. Kezdjük működésük megismerését az alacsonyabb szintű HttpWebRequest/HttpWebResponse párossal! Ezek segítségével az example. Miután ezzel elkészültünk. hanem egy Stream-ként. Ilyen lehet például egy kép. A HttpWebRequest-nél ezzel szemben először létrehozunk egy HttpWebRequest típusú osztályt.IO névtérre. Egyszerűbb feladatokra érdemes a WebClient-et használni. Kommunikáció szerverrel Webes tartalom letöltése A webszolgáltatások kiváló eszközt nyújtanak a saját szerverünkkel való kommunikációra. hogy nem a saját szerverünktől szeretnénk lekérni valamit. így ezt az adatfolyamot még ki kell olvasnunk egy string változóba. hanem az interneten keresztül akarunk letölteni egy állományt. Ezen metódushívásban átadunk egy úgynevezett callback függvényt – ezt hívja majd meg a futtatókörnyezet. illetve a WebClient osztály. amire hivatkoztunk! A logika kissé nyakatekert. HTTP kommunikációra kitalált osztály létezik a Windows Phone platformban: a HttpWebRequest/HttpWebResponse páros. A WebClient gyakorlatilag nem más. RoutedEventArgs e) { HttpWebRequest request = (HttpWebRequest)HttpWebRequest. „HttpWebRequest” felirattal. Ezek az osztályok nem telefonspecifikusak. Ott feliratkoztunk a művelet befejezésének eseményére. Azonban a HttpWebResponse példányban nem stringként szerepel a megkapott weboldal. Windows Phone OS 7. Emellett egy másik paraméterben egy tetszőleges objektumot adhatunk meg. alkalmazhatjuk a HttpWebRequest/HttpWebResponse osztályokat. a megkapott válasz első 50 karakterét kiíratjuk a felhasználó számára egy üzenetdobozban. Ebben az alfejezetben az erre alkalmas módszereket ismerjük meg. majd egy metódushívással közöljük.

HttpWebResponse response = (HttpWebResponse)request.Webes tartalom letöltése using System. Ennek használatát az előző fejezetrészben láthattuk.AsyncState. string responseString = new StreamReader(response. majd kiíratja az első 50 karakterét (9-5 ábra). Dispatcher.IO. programunk ezt beolvassa memóriába.example. a HttpWebRequest/HttpWebResponse osztályok használata meglehetősen nyakatekert. hogy a program épp dolgozik. most az egyszerűség kedvéért nem alkalmaztuk. Ehhez az alábbi kódra van szükségünk: private void WebClientButton_Click(object sender.BeginInvoke(() => { 225 .DownloadStringAsync(new Uri("http://www. client. }).Show(responseString. de segítségükkel alacsony szinten hozzáférünk a kommunikáció részleteihez. majd az eseménykezelő paraméterei között készen megkapjuk a letöltött HTML oldalt egy string változó formájában.com")).GetResponseStream()).EndGetResponse(ar). Éles alkalmazásban célszerű lenne egy ProgressBar vezérlőelem segítségével tájékoztatni erről. elindítjuk a kérést. Lássuk. 50)). majd kattintsunk a „HttpWebRequest” gombra! Néhány másodperc elteltével beérkezik a HTTP válasz. RoutedEventArgs e) { WebClient client = new WebClient(). de ennek modellje megegyezik a webszolgáltatásoknál már látottal. A WebClient osztály alkalmazása ennél lényegesen egyszerűbb. Egyszerűen feliratkozunk a kérés befejeződését jelző eseményre. hogy működik! Bővítsük ki alkalmazásunkat egy újabb gombbal! Ennek neve legyen WebClientButton. } Elkészültünk. client. 9-5 ábra: A beérkezett HTTP válasz első 50 karaktere A felhasználó nem értesült arról.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted). Az alábbiakat pedig gépeljük be a Click eseménykezelő alá: private void RequestCallback(IAsyncResult ar) { HttpWebRequest request = (HttpWebRequest)ar. felirata pedig „WebClient”. DownloadStringCompletedEventArgs e) { Dispatcher.Substring(0.ReadToEnd(). Dupla kattintással nyissuk meg Click eseménykezelőjét! A WebClient osztály használata szintén aszinkron történik. Amint láthattuk. } void client_DownloadStringCompleted(object sender. Teszteljük alkalmazásunkat! Egyszerűen indítsuk el az F5 gomb segítségével.BeginInvoke(() => { MessageBox.

Ezeket hívják CRUD műveleteknek. A HttpWebRequest már eleve egy Stream-et ad vissza. Ha a helyi SQL Serverünket akartuk megcímezni. Ha valamiért finoman hangolni szeretnénk a kimenő HTTP kéréseket (például szükségünk van a HTTP fejlécekre is). ha adatokat szeretnének lekérdezni – legyen szó akár adatbázisról. de kicsit máshogy kell kiadnunk a kéréseket. Ez az információt fogyasztók számára teljesen lényegtelen.Substring(0..com-ról a megvásárolható termékek katalógusát.> . az adatokon alapvetően négy műveletet tudunk végrehajtani: létrehozás (Create). <link rel="edit" title="Category" href="Categories(1)" /> . hanem az OpenReadAsync() metódust. a Netflix online filmnéző portálról a filmek listáját tölthetjük le. akkor alkalmazzuk a HttpWebRequest/HttpWebResponse párost! Adatelérés az OData protokollon keresztül Az interneten vagy vállalatoknál számos olyan szoftver található. nem változnak a rajta elvégezhető műveletek. akkor az alábbi kéréssel kérdezhetjük le tőle a Categories nevű gyűjtemény tartalmát: http://localhost:8080/owind. frissítés (Update). Az egyszerűbb. }). akár egy vállalati projektről. amellyel szintén egy Stream-et kapunk vissza! Ezzel megismertük az internetről való letöltés módszereit. Az OData definiál egy interfészt. Az adatbázis-motoroktól például a bennük tárolt táblák sorait. ahol az URL tartalmazza az elvégezni kívánt műveletet. Legyen szó bármilyen adatforrásról. akár internetes boltról. A fenti két példában szöveges információt töltöttünk le a webről. hogy legyen szó bármilyen adatforrásról. amitől adatrekordokat kérhetünk le. míg ha az eBay katalógusra voltunk kíváncsiak.Show(e. hogy a gyűjtemény teljesen általános fogalom. Az OData előírásai szerint az adatforrásnak HTTP kéréseket kell fogadnia. 50)). Állhat mögötte egy SQL tábla. Így a fejlesztőknek nem kell más és más technológiával kísérletezniük.Result. ugyanis a válasz szabványos XML-ben érkezik majd: <feed xml:base="http://localhost:8080/owind. sokáig más és más módon tudtunk csak hozzáférni az egyes adatforrásokhoz alkalmazásainkból..NET-et használtunk.svc/" . olvasás (Read). } Teszteljük ezt is! Ismét indítsuk be az alkalmazást.. Ha egy RSS feed-et vagy egy HTML oldalt szeretnénk lekérni telefonalkalmazásunkból. Hiába adott azonban az elvégezhető műveletek köre... <content type="application/xml"> 226 .. kattintsunk a WebClient gombra! Néhány másodperc elteltével megjelenik a válasz első 50 karaktere. Kommunikáció szerverrel MessageBox. és így tovább. Ha egy képet vagy valamilyen más fájlformátumot szeretnénk letölteni.. A WebClient-nél pedig ne a DownloadStringAsync() metódust használjuk. <entry> . vagy akár el is menthetjük a telefon Isolated Storage tárhelyére. ezt tetszésünk szerinti objektumra konvertálhatjuk a memóriában. az adatelérés ugyanazon a szabványos módon működhet. annak adatait bármilyen platformról egységes módon lehet olvasni.svc. akkor ahhoz ADO. a Categories gyűjtemény fizikailag bármi lehet. a vállalati SharePoint-tól a különféle dokumentumokat. magától értetődő WebClient használata az esetek többségében megfelelő. törlés (Delete).9. azt is megtehetjük.. amit az adatforrások gazdái implementálhatnak. Aki ezt megteszi. akkor valamilyen RSS feed-et próbáltunk letölteni. az eBay. a SharePoint-hoz különféle osztálykönyvtárakkal fértünk hozzá. egy XML fájl vagy akár egy szöveges fájl. Az OData protokoll arra a gondolatra épül. ezt a módszert kell használnunk.svc/Categories Fontos észrevenni. Ha az OData szolgáltatás címe például http://localhost:8080/owind.

hanem adatszolgáltatás (lásd a panel jobb oldala)..net/. hogy felveszünk egy referenciát az OData végpontra. az OData fogyasztók pedig ezeket használhatják. Amint láthattuk. 9-6 ábra: Referencia felvétele az OData végpontra 227 . a Namespace mezőben pedig nevezzük el a referenciát Ebay-nek! Amint a 9-6 ábrán is látható. Ahogy a fejezetben már többször. and ales</d:Description> <d:Picture m:type="Edm. kódunkból tudjuk manipulálni az adatforrást. az URL részeként kiadható parancsokat. Az OData szolgáltatóknak ezeket kell megvalósítaniuk.</d:Picture> </m:properties> </content> </entry> .Binary">FRwvAAI. és támogassa a Windows Phone OS 7. az OData adatforrásokat egyszerű HTTP kérésekkel tudjuk lekérdezni. akár az előző fejezetrészben megismert HttpWebRequest osztállyal kiadhatunk nyers HTTP kéréseket. hogy akár egy böngésző segítségével. coffees. beers. (És ez adja egyben az OData platformfüggetlenségét – HTTP kéréseket gyakorlatilag bármilyen platformról indíthatunk.. </feed> Minden CRUD művelethez definiáltak a fentihez hasonló. Mac vagy akármilyen egyéb eszköz. Így számos platformra. Az OData megismeréséhez egy mintaalkalmazást készítünk. hogy ez nem hagyományos webszolgáltatás. amely az OData osztálykönyvtár igénybevételével beolvassa az eBay. Ehhez (a korábban már látott webszolgáltatásokhoz hasonlóan) kattintsunk a projekt nevére a Visual Studióban. legyen az Windows.Adatelérés az OData protokollon keresztül <m:properties> <d:CategoryID m:type="Edm. Linux. Az osztálykönyvtár segítségével nem kell a nyers HTTP kérésekkel bajlódnunk... nyissunk egy új Windows Phone Application típusú projektet! Legyen ennek neve ODataSample. többek között a Windows Phone-ra is készült OData kliensoldali osztálykönyvtár.1 vagy újabb verzióját! Az első lépésünk. melyekre az OData adatforrás válaszolni fog. a rekordokat pedig C# osztályok képében kapjuk meg.Int32">1</d:CategoryID> <d:CategoryName>Beverages</d:CategoryName> <d:Description>Soft drinks. és válasszuk az Add Service Reference parancsot! A cím mezőbe írjuk be az eBay OData végpontjának címét: http://ebayodata.cloudapp.) Ez azonban kényelmetlen. objektumorientált módon.com aktuális akcióit. teas. Ez azt jelenti. a Visual Studio felismeri.

programunk futása során ezt fogjuk feltölteni a szerveroldalról lekérdezett rekordokkal. deals = new DataServiceCollection<Ebay. majd létrehozunk egy példányt a korábban deklarált Deal típusú objektumokat tartalmazó gyűjteményből is. public MainPage() { InitializeComponent().net/")).xaml. A LINQ eszköztára bővebb.cloudapp. valamint egy EBayData nevű kontextusosztály is generálódik.Deal> nevű változó pedig egy Deal típusú objektumokat tartalmazó gyűjteményt képvisel. az összes Deal típusú objektumot lekéri. A feltöltést közvetlenül az alkalmazás indulásakor elkezdjük. var query = from deal in context.Deals select deal. hogy egy érvényes LINQ lekérdezés futásidejű hibát dob. A generált osztályok ezeket a feladatokat végzik el helyettünk. Deals) készül egy-egy osztály.Data. így tudja majd. Az EBayData típusú változó biztosítja a szolgáltatás megszólításához szükséges metódusokat. melyeket az OData könyvtár fordít le az OData által elvárt URL-szintaxisra. Az OData végpont megszólításához elsőként létrehozunk egy példányt az EBayData nevű osztályból. Ez a kontextusosztály rendelkezik majd azokkal a műveletekkel. A következő feladatunk a deals gyűjtemény feltöltése az OData végpontról lekérdezett objektumokkal. hogy honnan kell az adatokat lekérnie.Deal> deals. A feladat elvégzéséhez két fontos változót kell deklarálnunk. Az eBay által kínált minden objektumtípushoz (pl. Most készítsük el a szolgáltatás megszólításához szükséges kódot! Ehhez szükségünk lesz egy névtérre.EBayData context.Client. Az ismétlés kedvéért: ezek a generált objektumok kizárólag a fejlesztő kényelmét szolgálják. majd kiadjuk az utasítást a deals gyűjtemény feltöltésére az általunk megadott LINQ lekérdezés szerint. Ennek a példánynak a kontextusra (az EBayData típusú változó példányára) adunk át egy referenciát. Bidders. Ha akarnánk. Ezután létrehozunk egy LINQ lekérdezést. amelyekkel a kódból megszólíthatjuk az OData szolgáltatást.Services. DataServiceCollection<Ebay. így a kódot közvetlenül a public MainPage() konstruktorban helyezzük el.cs kódfájl tetején helyezzünk el! using System. 228 . A két változót több metódusból is szeretnénk majd használni. Ennek a példánynak létrejöttekor átadjuk a megcímzendő szolgáltatás URL-jét. context = new Ebay. Items. amellyel megadjuk. Kommunikáció szerverrel Az OK gomb megnyomása után a Visual Studióhoz készült OData könyvtár legenerálja a végpont eléréséhez szükséges osztályokat. így előfordulhat.Deal>(context). hogy a deals gyűjteménybe mit szeretnénk betölteni a szerveroldalról. Végül a korábban már látott módon feliratkozunk a lekérdezés befejezését jelző eseményre. Ez a gyűjtemény kezdetben üres. A DataServiceCollection<Ebay. így deklarációjukat közvetlenül a public partial class MainPage : PhoneApplicationPage sor (és az azt követő nyitó kapcsos zárójel) után helyezzük el: Ebay. melyet a MainPage. mint az OData által támogatott műveletek halmaza. rendezéseket. nyers HTTP kérésekkel és a visszaérkező XML válaszok feldolgozásával is kommunikálhatnánk a végponttal.9.EBayData(new Uri("http://ebayodata. A LINQ eszközeivel definiálhatunk különféle szűrőfeltételeket. Az általunk megadott LINQ lekérdezés nem tartalmaz szűrőfeltételt.

amíg minden objektum meg nem érkezik a szerverről. ezért ha kódunk azt érzékeli.Continuation != null) { deals. 229 .NewLine.Adatelérés az OData protokollon keresztül deals. Így ha a lekérdezés sok eredményt adna vissza.Show(message).com/ honlapot megnyitva láthatjuk. ami több megabájtnyi XML-be férne csak bele). így lekérdezésünk addig fut. LoadCompletedEventArgs e) { if (e.Error != null) { if (deals.Error. A fent említett mechanizmus miatt azonban előfordulhat.ebay.ToString()). amíg a teljes adathalmaz megérkezik (ez sok ezer rekordot is jelenthet. } Az OData protokollt felkészítették a nagyméretű adathalmazokra. Teszteljük alkalmazásunkat! Indítsuk el az F5-tel. hogy valóban az épp elérhető akciókat kérdeztük le (9-7 ábra). A http://deals. Ehhez nem kell új eseménykezelőt felvennünk. és a visszaadott objektumok betöltődnek a deals gyűjteménybe. majd a válaszban jelzi. akkor a LoadNextPartialSetAsync() hívással az eredményhalmaz következő szeletét is letölti.Title + Environment. hogy még van további része is az eredményhalmaznak. A deals_LoadCompleted eseménykezelő meghívásakor lekérdezésünk lefut. Ha úgy találjuk. Hozzuk létre a deals_LoadCompleted metódust az alábbi kóddal: void deals_LoadCompleted(object sender. hogy minden objektum megérkezett. deals. foreach (var deal in deals) message += deal. MessageBox. programunknak nem kell megvárnia. mert ez a metódus is a deals_LoadCompleted eseménykezelőt hívja meg. } } else { MessageBox. Ehelyett a protokoll ilyenkor az első néhány rekordot adja át.Show(e. Az eBay honlapján ellenőrizhetjük is. } } Ezzel elkészültünk.LoadNextPartialSetAsync(). hogy a lekérdezés még folytatható. } else { string message = "". akkor egy üzenetdobozban kiíratjuk az aktuális eBay akciók címeit. hogy még vannak betöltetlen rekordok az adatforrásban. hogy a megfelelőket töltöttük-e le.LoadAsync(query).LoadCompleted += new EventHandler<LoadCompletedEventArgs>(deals_LoadCompleted). Valamennyi rekordot szeretnénk lekérdezni. Az esetleges hibát pedig természetesen kezeljük. és kisvártatva megjelennek az aktuális eBay akciók.

létrehozhatunk benne aszinkron kommunikációra alkalmas várakozási sorokat (Queue Service). melyre alkalmazásunk egy webszolgáltatáson keresztül tölti fel az anyagokat. Érdemes megismerkedni a protokollal.odata. professzionális alkalmazások kiszolgálására is. illetve feltölthetünk egyszerű táblajellegű információkat. Így elmondhatjuk. az látogasson el a http://www. Aki szeretné jobban megismerni az OData protokollt. egymástól több száz kilométerre lévő adatközpontba is szétmásolja. valamint a protokollal kapcsolatos részletes információk és a fórum. Ebben a részben a Windows Azure tárhelyszolgáltatásának elemeit és ezek használatát ismerjük meg − egy Windows Phone alkalmazásból. mint pl. így a véletlen adatvesztés gyakorlatilag kizárt. Ennél azonban sokkal egyszerűbb és olcsóbb megoldást is alkalmazhatunk: a Windows Azure tárhelyszolgáltatását kihasználva néhány száz forintért tárolhatunk gigabájtokat.9. Az itt megtanultak alapján már tudunk egy ODatafogyasztásra képes alkalmazást készíteni. Az Azure Storage háromféle szolgáltatást nyújt: tárolhatunk benne fájlokat (Blob Storage). hogy az Azure a feltöltött adatokat három példányban tárolja. hogy mindhárom tárhelyszolgáltatás alkalmas komoly. Mindhárom szolgáltatásra igaz. a SharePoint.org weboldalra. Ez utóbbi nem váltja ki az SQL szervert. Kommunikáció szerverrel 9-7 ábra: Az OData-n keresztül letöltött objektumok és az eBay honlapja Ezzel megismertük az OData használatának alapjait. a Netflix és még sokan mások. Az Azure emellett komoly kötelezettségeket vállal a szolgáltatás rendelkezésre állására is. A webszolgáltatásokhoz hasonlóan az OData is rendkívül széles témakör. ráadásul egyszerű objektumorientált API-n keresztül. amint később azt látni fogjuk. Ezeket az igényeket természetesen megoldhatjuk egy saját szerverrel. az eBay. Adattárolás Windows Azure-ban Internetre kapcsolt telefonalkalmazásunknak gyakran szüksége lehet saját fájlok és egyéb adatok tárolására. mert rengeteg Microsoft-termék és számos külső gyártó már most támogatja! Ilyen például az SQL Azure. ráadásul két. egy telefonkönyv (Table Service). ahol megtalálható az OData-szolgáltatók és a különféle platformokra elérhető OData kliensek folyamatosan bővülő listája. Ismerjük meg ezeket részletesebben! 230 .

Storage Accounts & CDN fülre.com). Most készítsük el mintaalkalmazásunkat! 231 . A feltöltött fájlokat később URL-jük alapján a telefonról vagy az internetről is elérhetjük. A New Storage Account gomb segítségével hozzuk létre tárhelyünket! Ennek során kell megadnunk a tárhely nevét. Ehhez szükség van egy Azure előfizetésre. majd válasszuk a Storage Accounts listaelemet (9-8 ábra)! Ekkor megjelennek az előfizetéshez tartozó Azure Storage tárhelyek. a jobb felső sarokban találjuk a Primary access key sort. Miután létrejött. Az előfizetésünkön belül hozzunk létre egy Azure Storage tárhelyet! Ehhez látogassunk el az Azure portálra (http://windows. benne tárhelyeinkkel A tárhely nevét és egyik jelszavát tároljuk el. A fejezetben megszokott módon egy mintaalkalmazáson keresztül ismerjük meg az Azure Storage használatát. A konténerekbe pedig tetszőleges mennyiségű fájlt feltölthetünk. Erre kattintva tekinthetjük meg a tárhelyhez tartozó két automatikusan generált jelszót. akár mappákba rendezve is.azure. de ez az emulátor csak PC-n futtatható. Azure előfizetésünkhöz úgynevezett konténereket hozhatunk létre. így telefonalkalmazásunkból egy valódi. A fájlok méretének felső korlátja egy terabájt (1 TB).microsoft. mint egy merevlemez egy partíciójára. majd jelentkezzünk be az előfizetéskor megadott Live ID azonosítónkkal! A bal alsó sarokban kattintsunk a Hosted Services. és mellette a View gombot. Az Azure kínál ugyan egy emulátort. 9-8 ábra: Az Azure menedzsment portál.com/windowsazure/offers/ oldalon juthatunk hozzá − gyakran van ingyenes kipróbálási lehetőség is.Adattárolás Windows Azure-ban Fájlok (blob-ok) A Blob Storage gyakorlatilag egy fájlszerver a felhőben. a felhőben lévő tárhelyet kell megcímeznünk. Ilyen előfizetéshez a http://www. ezekre lesz majd szükségünk a tárhely programozásához. Mindegyik konténerre úgy gondolhatunk.

A TÁRHELYNÉV helyére írjuk a tárhely nevét (amit létrehozáskor megadtunk). Microsoft.WindowsPhoneCloud. Ilyen konténerből tetszőleges számúval rendelkezhetünk. egyszer megtenni.WindowsPhoneCloud.StorageClient. A két másik változó pedig a Blob storage használatához kell. Kattintsunk duplán a BlobButton gombra. credentials nevű változóban tároljuk el a tárhely megcímzéséhez használt nevet és jelszót. A szükséges névterek importálásához helyezzük el a következő sorokat a MainPage. Windows Phone OS 7. Alkalmazásunk első lépése. Miután ezzel elkészültünk. Helyezzük a következő sorokat a public partial class MainPage : PhoneApplicationPage sor (és az azt követő kapcsos zárójel) alá: StorageCredentialsAccountAndKey credentials. alkalmazásunk felületére vegyünk fel egy gombot. Töltsük ezt le a CodePlex-ről. így különböző alkalmazásaink. hanem a program törzsében. hogy belépjünk Click eseménykezelőjébe! A korábban említett REST-es API-t egy sor osztály fedi le. Így itt először is példányosítunk egy CloudBlobContainer típusú osztályt.StorageClient. 232 .1 vagy újabb operációs rendszer verziót használva! A Toolkit osztályainak használatához vegyünk fel egy referenciát a WindowsPhoneCloud.dll könyvtárra! Ezt a Toolkit mappája alatt a Binaries mappában találjuk. így a gombra kattintva a kérés csak elindul. a háttérben zajló HTTP kéréseket az osztályok eltakarják előlünk. mert később szükségünk lesz majd rá! A szerveroldali programozáshoz készült Windows Azure SDK természetesen szintén tartalmaz kész osztályokat az Azure Storage eléréséhez. System. mert később még többször szükségünk lesz rá. BlobButton néven. a http://watwp.com/ URL-en érhető el! Telepítése során a fájlokat egy általunk meghatározott mappába helyezi. Ez az osztálykönyvtár a Windows Azure Toolkit for Windows Phone része.Credentials. A Toolkit telepítése után készítsünk egy új Windows Phone Application projektet AzureStorageSample néven. System.Text. így készült hozzá egy osztálykönyvtár.codeplex. Az első. a Blob Storage használatának előfeltétele. Az Azure osztályok – a fejezet korábbi részeiben tárgyalt okokból – aszinkron működésűek. Most adjunk értéket a credentials változónak! Ezt célszerű a program indulásakor. Kommunikáció szerverrel Az Azure tárhely rendelkezik egy REST-es menedzsment felülettel. Amint korábban volt róla szó.Samples. CloudBlobClient blobClient. Az itt tárgyalt Windows Phone alapú osztályok hasonlítanak ezekre. „Blob feltöltése” felirattal! Erre a gombra kattintva alkalmazásunk feltölt majd a felhőbe egy példafájlt.Samples. CloudBlobContainer container. "JELSZÓ"). Ez szolgál majd a konténerek létrehozására.xaml. ám némileg más logikát alkalmaznak.cs kódfájl legtetejére: using using using using Microsoft. hogy egyszerű HTTP kérésekkel parancsokat tudunk kiadni. Az értékadáshoz írjuk az alábbiakat a public MainPage() konstruktor InitializeComponent() sora alá: credentials = new StorageCredentialsAccountAndKey("TÁRHELYNÉV". vagy alkalmazásunkon belül különböző felhasználóink is kaphatnak külön-külön konténert.StorageClient. befejezni csak egy másik metódusból fogjuk. nekünk csak ezek metódusait kell hívni. Ez azonban kényelmetlen. Ezért a használt változóinkat nem a metóduson belül deklaráljuk. Ez azt jelenti. a JELSZÓ helyére pedig a tárhely jelszavát (amit lementettünk az Azure menedzsment portálról). Ennek a mappának a helyét szintén jegyezzük meg. hogy létrehozzunk benne fájljaink számára egy konténert. hogy létrehozzon magának egy konténert (ha ezt korábban még nem tette meg).9.IO.

Adattárolás Windows Azure-ban A menedzsment API hívásához osztályainknak rendelkezniük kell a szükséges hitelesítési adatokkal. valamint átadjuk neki a hitelesítési információkat. ha még nincs ott.Upload("test. így befejeződése után valahogy folytatnunk kell kódunk futtatását. credentials).blob. ezért létrehozunk egy MemoryStreamet. Ha igen. blobClient = new CloudBlobClient( "https://TÁRHELYNÉV. hogy létezik-e már az adott konténer. így éles alkalmazásban egy képet. másrészt egy kötelező elemet (blob. 233 . } }). A Stream egy általános célú változótípus.txt". harmadrészt a konténer elvárt nevét. hogy tájékoztassa a felhasználót a feltöltés kimenetéről (sikeres vagy sikertelen).BeginInvoke(() => { if (returnValue.core. Ennek egyrészt tartalmaznia kell tárhelyünk nevét.core. Ezúttal nem egy eseményre iratkozunk fel. blobClient. a felhasználó által az internetről letöltött állományt vagy bármi mást is fel tudunk tölteni Blob Storage-ba. } else { MessageBox. Ennek már mindössze annyi feladata van. hogy az melyik konténerrel dolgozzon (a fenti URL-t kell itt is használnunk). Paraméterként át kell adnunk a kívánt konténer URL-jét.Seek(0. hanem a metódushívásban átadunk paraméterként egy callback függvényt. streamWriter. Következő feladatunk a callback függvény megírása.windows. BlobUploadedCallback). akkor erről értesítjük a felhasználót. Ha nem. Ez a callback függvény a fent látható CloudBlobContainerCreated. a konténer neve pedig legyen phonetest1! container = new CloudBlobContainer(credentials). A függvényben megvizsgáljuk. és csak akkor próbálkozik meg létrehozásával.Begin). memoryStream.net).Flush(). container. hogy történt-e hiba a végrehajtás során.net/phonetest1". így a most létrehozott CloudBlobContainer példánynak egyszerűen csak ezt kell átadnunk.CreateContainerIfNotExist(new Uri("https://TÁRHELYNÉV. Ezeket az adatokat már eltároltuk a credentials nevű osztályba. Írjuk az alábbi kódot a gomb Click eseménykezelője alá: private void CloudBlobContainerCreated(CloudOperationResponse<bool> returnValue) { this. SeekOrigin.Dispatcher. A feltöltendő adatot egy Stream típusú változóban várja az osztály. így egy második callback függvényt is készítenünk kell.blob. A használt metódus intelligens. Tárhelyünk nevét helyettesítsük be.Show(returnValue. streamWriter. memoryStream.WriteLine("Hello!").core. Ehhez egy CloudBlobClient nevű objektumot használunk.ToString()). CloudBlobContainerCreated). melyet a metódus majd meghív befejezésekor. akkor folytatjuk feladatunkat: feltöltünk egy blob-ot.Exception == null) { MemoryStream memoryStream = new MemoryStream().net/phonetest1").Exception.windows. A CloudBlobContainer példány létrehozása után egy metódus segítségével megindítjuk az alkalmazásunk által használni kívánt konténer létrehozását. így megvizsgálja. Utána pedig egy metódushívással elvégezzük a feltöltést. amelybe beleírunk néhány betűt.windows. Aszinkron metódust hívtunk. Ennek létrehozásakor megadjuk. StreamWriter streamWriter = new StreamWriter(memoryStream). } A blob feltöltése is egy aszinkron művelet.

Ellenőrizzük ennek megtörténtét! Ehhez valamilyen eszközzel rá kell csatlakoznunk a Blob Storage-ra. } Teszteljük alkalmazásunkat! Az F5 gombbal futtassuk.Exception.Dispatcher. 9-9 ábra: A létrehozott konténer és blob Ezzel megismertük a Blob Storage használatának alapjait. 234 . A myazurestorage.ToString()). Kommunikáció szerverrel private void BlobUploadedCallback(CloudOperationResponse<bool> returnValue) { this.myazurestorage. Itt meg kell adnunk tárhelyünk nevét és jelszavát.Show(returnValue.com honlap használata.Exception == null) { MessageBox. A Blob Storage nyújtotta lehetőségekről és a Windows Phone által támogatott API-ról bővebben olvashatunk az Azure és a Windows Azure Toolkit for Windows Phone honlapjain.txt fájlunk valóban létrejött-e (9-9 ábra). de ennek alapján már el tudunk készíteni egyszerű alkalmazásokat.com weboldalt a Microsoft fejlesztette. Természetesen a szolgáltatás képességeinek és a használható API-nak csak egy nagyon kis részét láttuk. majd egy webes felületen böngészhetjük a Blob Storage tartalmát. így megbízhatunk benne. Várakozási sorok (queue-k) Következő Storage elemünk a várakozási sor. nem kell jelszavunk ellopásától tartanunk. } }). majd nyomjuk meg a „Blob feltöltése” gombot! Alkalmazásunk a háttérben létrehozza a konténert és feltölti a tesztfájlt. hogy test.Show("Blob feltöltve!").9. vagyis a Queue Service. amit kibontva ellenőrizhetjük. } else { MessageBox. Talán a legegyszerűbb a http://www. hogy tetszőleges számú egyszerre működő termelővel és fogyasztóval megbirkózik.BeginInvoke(() => { if (returnValue. Előnye. kapacitása pedig gyakorlatilag korlátlan. Az Azure várakozási sor kisméretű (maximum 64 kilobájtos) üzenetek megbízható kezelésére alkalmas. A BLOBs fülre kattintva megtaláljuk a phonetest1 konténert.

hogy törölje az üzenetet. } else MessageBox. Az üzenetek méretére vonatkozó korlát szándékos: a várakozási sorban csak a feladatok leírását kell tárolnunk (pl. A meghívott metódus aszinkron. ezért létrehozunk egy szöveget.windows.Adattárolás Windows Azure-ban Egy ügyes mechanizmussal gondoskodik arról. mellyel egy sort hozunk létre. Helyezzük az alábbi sorokat a MainPage osztály tetejére: CloudQueueClient queueClient.queue. felirata pedig „Queue üzenet létrehozása”. ezért az kis idő elteltével újra megjelenik. Véglegesen törölni csak egy külön utasítással lehet. } 235 .Show(returnValue. Ha ügyelünk arra. valamint a korábban eltárolt hitelesítési adatainkat. mint ellenőrizni. Mivel a hibás egység sosem jutott el odáig.net".ToString()). majd elhelyezünk benne egy üzenetet. amint bájttömbbé konvertálva helyezünk el egy üzenetben: private void CloudQueueCreatedCallback(CloudOperationResponse<bool> returnValue) { this. akár szöveges. illetve akár egy bájttömb is.CreateIfNotExist(CloudQueueCreatedCallback).Exception == null) { CloudQueueMessage message = new CloudQueueMessage() { AsBytes = Encoding. CloudQueue queue. Ennek átadjuk a Queue szolgáltatás URL-jét. queue = (CloudQueue)queueClient.UTF8. és mindegyik sorba külön-külön pakolhatunk üzeneteket. A sorban lévő üzeneteket ugyanis először csak kivesszük. A Windows Phone-hoz készült API csak bájttömb beírását teszi lehetővé. } A callback függvényben nincs más dolgunk. akkor egy hibára futó feldolgozóegységnél az üzenet nem vész el.GetBytes("Hello") }. queue. nagyméretű fájlokat és egyéb adatokat máshová célszerű helyeznünk (pl. és ha nem. queue. de ez az időtartam feljebb is vehető). „videót kell konvertálni”). így kódunk egy callback függvényben folytatódik majd. Utána ettől az objektumpéldánytól kérünk egy referenciát egy phonetest1 nevű sorra.AddMessage(message. A Blob Storage-hoz készült példaalkalmazásunkat kiegészítjük egy újabb gombbal. }). amíg azok sikeresen feldolgozásra nem kerültek. ha még nem létezik.Dispatcher. Ehhez egy CloudQueueClient objektumot készítünk. hogy az üzeneteket csak sikeres feldolgozásuk után töröljük. A feladatok végrehajtásához szükséges. ezekre az üzeneten belülről egy URLlel hivatkozhatunk.core. akkor beírni egy üzenetet a sorba. Blob Storage-ba).GetQueueReference("phonetest1"). egyedileg elnevezett sort hozhatunk létre. és egy másik egység újra megpróbálkozhat a feldolgozásával.BeginInvoke(() => { if (returnValue. credentials). private void QueueButton_Click(object sender. Ehhez szükségünk lesz néhány osztályszintű változóra. RoutedEventArgs e) { queueClient = new CloudQueueClient("https://TÁRHELYNÉV. hogy a sorba kerülő üzenetek addig ne törlődjenek. hogy történt-e hiba. Az üzenetek tartalma tetszőleges formátumú lehet. A Queue szolgáltatás felépítése hasonlít a Blob Storage felépítéséhez: Azure tárhelyünk alá tetszőleges számú. Dupla kattintással lépjünk be Click eseménykezelőjébe! Első dolgunk a sor létrehozása lesz. A kivett üzenetek bizonyos időre virtuálisan eltűnnek a sorból (alapértelmezésként 10 percre.Exception. amit egy metódushívással létrehozunk. CloudQueueMessageAddedCallback). Most hozzuk létre a gombot! Annak neve legyen QueueButton.

9. vagyis több mezőből álló adatsorokat tárolhatunk.Dispatcher. 9-10 ábra: A létrehozott várakozási sor és üzenet Táblák (table-k) Az Azure Storage harmadik eleme az Azure Table Service. private void CloudQueueMessageAddedCallback(CloudOperationResponse<bool> returnValue) { this. táblaszerű információt. Ezeket nem kell kézzel beraknunk azokba az 236 . Vagyis ha egy Dog típusú objektumot helyezünk egy táblába. Itt mindössze értesítjük a felhasználót a művelet eredményéről. ezért feladatunkat egy újabb callback függvényben fejezzük be. és minden tábla felveszi a belerakott objektumok sémáját.ToString()). Ne lepődjünk meg.Show("Üzenet létrehozva!"). Kommunikáció szerverrel Az üzenet létrehozása természetesen szintén aszinkron. dátum típusú mezőt. } Teszteljük alkalmazásunkat: indítsuk el. Itt strukturált. egyedileg elnevezett táblát hozhatunk létre. mint a magyar idő –a weboldal az Azure adatközpont helyi idejét jeleníti meg.BeginInvoke(() => { if (returnValue. } }). és a Dog objektumnak Name és Age tulajdonsága van. de a táblában minden objektum minden tulajdonságához létrejön egy-egy oszlop. Objektumokat helyezhetünk beléjük.Exception.Exception == null) { MessageBox. } else { MessageBox. Ismét látogassunk el az oldalra! A Queues fülön megtaláljuk a phonetest1 várakozási sort és benne az imént létrehozott üzenetünket (9-10 ábra). és nyomjuk meg a QueueButton gombot! A Blob Storage példához hasonlóan most is a myazurestorage. hogy üzenetünk valóban létrejött-e. így ezt inkább kerüljük! A táblába helyezett objektumoknak tartalmazniuk kell egy PartitionKey és egy RowKey nevű szöveges mezőt és egy Timestamp nevű. A táblákhoz nem kell sémát rendelnünk – azaz nem kell őket megterveznünk.Show(returnValue. ami érdekes ütközéseket és hibajelenségeket okozhat. Egy táblába többféle objektumot is beletehetünk. Tárhelyünk alatt tetszőleges számú.com segítségével ellenőrizhetjük. ha az üzenet időbélyegzője néhány órával korábbi vagy későbbi. akkor a táblában automatikusan létrejön egy Name és egy Age típusú oszlop.

A későbbiekben leírt árazásból láthatjuk majd. azt az Azure kezeli.NET alaptípusok lehetnek (pl. azaz képességei lényegesen szerényebbek. A táblába helyezett objektumokat entitásoknak nevezzük. Double. Ha programunknak egy High Score listát kell nyilvántartania. A PartitionKey és a RowKey azonban fontos! A táblákban mindössze ezen a két mezőn van index (a többire nem is rakhatunk). hanem a Browse fül segítségével tallózzuk ki a Toolkit mappája alatt található Binaries mappából! Ez azért szükséges. amiket táblában szeretnénk tárolni – elég leszármaztatni osztályainkat a TableServiceEntity ősosztályból. A Table Service előnye. Másik előnye. Az osztály tetejére írjuk a következő sort: using Microsoft. Így a kettő együtt garantáltan egyedi (sőt a RowKey akár önmagában is).dll fájlra.Adattárolás Windows Azure-ban osztályokba. A PartitionKey értékét a skálázásban használja az Azure. de egyszerű adatsort kell tárolnia. tárolt eljárásokat. A RowKey nem hordoz ilyen jelentést. akkor ezt a feladatot néhány forintért ellátja a Table Service. így a logikailag összetartozó adatokat érdemes azonos PartitionKey értékkel ellátni. táblánként több millió adatsort is eltárolhatunk. idegen kulcsokat.Client. Boolean. Ezek típusai alapvetően a . mint egy SQL szerveré. le kell származtatnunk azt a TableServiceEntity ősosztályból. és a .Services.WindowsPhoneCloud. Egy entitás teljes mérete 1 megabájt lehet. hogy néhány száz forintból hatalmas adatbázisokat tarthatunk fenn! Hátránya viszont. A fenti korlátozások jelen sorok írásakor aktuálisak voltak. másféle feladatkörökre érdemes alkalmazni őket. míg a Browse fülön a 2.NET füléről válasszuk ki. a Float adattípust nem). Vegyünk fel egy referenciát a System. majd fel kell vennünk bele néhány tulajdonságot. az azonos PartitionKey értékkel rendelkező entitásokat fizikailag egymáshoz közel tárolja. mert nekünk a DLL 4.0 verziót találnánk. Egy bonyolult adatstruktúrát alkalmazó programnál. Komplex vagy saját típusokat (azaz listákat.Data. és az Add almenüből válasszuk a Class menüpontot! Új osztályunkat nevezzük SampleData-nak! Miután létrejött. mint pl. A Timestamp mezővel semmi dolgunk. általunk definiált osztályokat) nem használhatunk. Int32. A kettőnek együttesen egyedinek kell lennie. akkor nagyon gyorsan tudunk haladni. ám az Azure többi szolgáltatásához hasonlóan a Table Service is folyamatosan fejlődik. A jellemzők legfrissebb listája mindig az MSDN-en olvasható. minden objektumnak lehet különböző PartitionKey értéke is. hogy óriási táblaméreteket támogat. A Table Service és a SQL Azure tehát nem versenytársak. de ne az Add Reference dialógus . egy CMS rendszernél vagy egy banki alkalmazásnál viszont egyértelműen a SQL Azure a megfelelő választás. a RowKey értéke pedig az illető személyi száma. A táblába rakott entitásoknak a három kötelező mezőn kívül maximum 252 általunk megadott mezője lehet.StorageClient. Egy népszámlálás adatsorainál a PartitionKey érték lehet például az illető városa. Az osztály tartalma pedig legyen a következő: 237 . Hozzunk létre egy erre szánt osztályt! Jobb gombbal kattintsunk a projekt nevére a Solution Explorer ablakban. Guid vagy String). Amint korábban láttuk.NET alaptípusok közül sem mindet (pl. Ha ezzel nem akarunk bajlódni. és így tovább. hogy rendkívül olcsó.0-s verziója kell. azaz tábláinkra nem vehetünk fel plusz indexeket. és ha város alapján keresünk vissza entitásokat. Egészítsük ki példaprogramunkat Azure Table Service támogatással! Térjünk vissza a Visual Studióba és hozzunk létre egy új gombot az alkalmazás felületén! A neve legyen TableButton. vagy éppenséggel sok millió. az Azure Table Service-be osztályok példányait tudjuk feltölteni.Samples. felirata pedig „Table sor hozzáadása”! A Table Service használatához szükségünk van továbbá még egy DLL fájlra. hogy nem relációs.

Ügyelünk arra.Name = "Demo". TableCreatedCallback). Ekkor történik meg a tényleges kommunikáció a szerverrel. private void TableCreatedCallback(CloudOperationResponse<bool> returnValue) { this. a többi változódeklaráció alá! CloudTableClient tableClient. Majd (az Entity Frameworkhöz és a LINQ to SQLhez hasonló módon) felvesszük az entitást a táblába.CreateTableIfNotExist("phonetest1". Kommunikáció szerverrel public class SampleData : TableServiceEntity { public string Name { get. ITableServiceContext tableContext. sampleData.Dispatcher. credentials).PartitionKey = Guid. } public int Age { get. tableClient. sampleData). } else { MessageBox. } A callback metódusban létrehozunk egy példányt a SampleData osztályunkból. A művelet befejezése után értesítjük a felhasználót: private void TableContextSaved(IAsyncResult result) { try { var response = tableContext.windows. null).EndSaveChanges(result).NewGuid().net".BeginInvoke(() => MessageBox. this.Exception. ezeket vegyük fel a kódfájl tetejére.table. } A táblamentés természetesen aszinkron történik. és elmentjük a változásokat. tableClient = new CloudTableClient(tableContext). set. sampleData.ToString().ToString()). 238 . Ezután dupla kattintással lépjünk be a TableButton gomb Click eseménykezelőjébe! Az előző mintapéldákban látottakhoz hasonlóan először létrehozunk egy TableServiceContext osztályt a megfelelő hitelesítési adatokkal.AddObject("phonetest1".cs fájlhoz! Szükségünk lesz néhány újabb osztályszintű változóra.xaml. tableContext.Show(returnValue.Exception == null) { SampleData sampleData = new SampleData(). private void TableButton_Click(object sender.9.Show("Táblasor hozzáadva!")). RoutedEventArgs e) { tableContext = new TableServiceContext("https://TÁRHELYNÉV. } }).RowKey = Guid. majd ezzel aszinkron módon létrehozatunk egy táblát.Dispatcher.BeginInvoke(() => { if (returnValue.NewGuid(). tableContext.core. sampleData. sampleData.BeginSaveChanges(TableContextSaved. } } Most térjünk vissza a MainPage. hogy a PartitionKey és a RowKey értékek egyediek legyenek.Age = 10.ToString(). set.

com oldalt! A Tables fülön megtaláljuk majd a phonetest1 táblát. és jellemzően egyre olcsóbb lesz. hogy szolgáltatásait önállóan is igénybe vehetjük. A Table Service segítségével költséghatékony. a teljes API az Azure és a Toolkit honlapjain ismerhető meg.Adattárolás Windows Azure-ban } catch (Exception ex) { this. Jelen sorok írásakor a tárhelyszolgáltatás árai a következők:  A feltöltés ingyenes. amit használunk.  10 ezer elemi írási/olvasási művelet: 1 dollárcent. A Queue és Blob szolgáltatáshoz hasonlóan a Table Service képességeinek is csak egy töredékét fedtük le. tábla vagy fájl) egy hónapig: 14 dollárcent. 239 . Így ha használni szeretnénk valamelyik tárhelyszolgáltatást.Show(ex. rendkívül skálázható módon tárolhatunk táblajellegű információkat. majd a már látott módon nyissuk meg a myazurestorage.  Egy gigabájt adat tárolása (legyen az sor. semmiféle belépési költséggel vagy járulékos összeggel nem kell számolnunk – kizárólag azt kell fizetnünk.com/windowsazure/pricing/.  Egy gigabájt adat letöltése: 15 dollárcent. és azon belül az elmentett entitásunkat (9-11 ábra).ToString())). Árazás A Windows Azure platform fontos jellemzője.BeginInvoke(() => MessageBox. A fenti adatok kizárólag tájékozató jellegűek! Az Azure aktuális árazását a következő honlapon találjuk: http://www. benne egy partíciót (amit egyetlen feltöltött entitásunk PartitionKey értékéből számolt az oldal). kattintsunk rá a „Table sor hozzáadása” gombra. Az Azure árazása folyamatosan változik. } } Teszteljük az alkalmazást! Indítsuk el. 9-11 ábra: Entitásunk a Table Service-ben Ezzel megismertük az Azure Storage harmadik szolgáltatását is.Dispatcher.microsoft.

garantált rendelkezésre állás és adatbiztonság mellett. És ami a legrosszabb: szolgáltatásunk használata előtt felhasználónknak át kell esnie a regisztrációs procedúrán. mindkét fél számára előnyös módon.NET Membership). A lenti lépések végrehajtásához szükségünk lesz a Toolkitre és egy élő Azure előfizetésre. hitelesítése. de erre gyakran nem adnak közvetlen támogatást. Ezt a bejelentkezési módszert hívjuk federált hitelesítésnek. hogy az Azure táblák és várakozási sorok árazása megegyezik a fájlok árazásával – ebből a havi pár száz forintból egy több gigabájtos adatbázist vagy várakozási sort is fenntarthatunk a Table Service és Queue Service használatával. Még itt is igaz azonban. használ Messengert vagy van XBOX Live előfizetése). amely köztes félként működik. de mégis hitelesítsük a felhasználót! Egyszerűen használjuk valamelyik már meglévő regisztrációját! Az internet polgárainak túlnyomó többsége már tagja a Facebooknak. Alkalmazásunk értesül a bejelentkezés tényéről. Az előző. Vegyük észre. Amint látni fogjuk. Ez pedig gyakran túl sok: talán az Olvasóval is előfordult már. hogy ez csak néhány mező kitöltését és egy gyors e-mailes hitelesítést igényel. hanem külső gyártótól származó. Ebben a fejezetrészben a Windows Azure Toolkit for Windows Phone kihasználásával készítünk egy Access Control alapú hitelesítésre alkalmas alkalmazást. így a hitelesítési munkát teljes egészében megspóroltuk. amelynek a Cloud kategóriában kell lennie (9-12 ábra). Felhasználó-hitelesítés szerveroldalról Ha alkalmazásunk internetes erőforrásokat is használ. Indítsunk egy új Visual Studio projektet! A megszokottól eltérően ne a Windows Phone Application típust. és kap egy egyedi azonosítót a felhasználóhoz. A klasszikus megoldás erre egy saját hitelesítő mechanizmus használata. hogy ezt elkerüljük. de így is elvesz pár percet a felhasználó idejéből. Előnye. Így elfedi előlünk az egyes szolgáltatók meghívásának bonyolultságát. Kommunikáció szerverrel Amint láthattuk. néhány száz forintért sok gigabájt adatot tárolhatunk a felhőben. vagy rendelkezik Live ID azonosítóval (például van Hotmail fiókja. biztonsági szempontból alaposan átgondolt és tesztelt hitelesítési réteget vetünk be (ilyen például az ASP. így fejlesztői szempontból nehéz a feladat. hogy telefonalkalmazásunkból nagyon könnyen használható.9. az itt ismertetett lépésektől kis eltéréssel az ASP. hogy az adatbázist nekünk kell tárolni. A szolgáltatás neve Access Control. Szerencsére van arra módunk.NET Membershipet is használhatnánk. Windows Phone alkalmazásunk közvetlenül e szolgáltatások valamelyikébe küldheti el a felhasználót bejelentkezni. akkor ellenőrizzük. A Microsoft Windows Azure felhőplatformja azonban kínál egy szolgáltatást. Ha kicsit óvatosabbak vagyunk. és továbbítja kérésünket a megfelelő hitelesítésszolgáltató felé. Ha nem találjuk. nekünk kell kezelni a felhasználók problémáit (például jelszó-változtatás). esetleg Gmail-es e-mail címe van. hogy a Windows Azure Toolkit for Windows Phone-t jól raktuk-e fel! 240 . Lehet. hogy telefonalkalmazásunkról közvetlenül szólítjuk meg a hitelesítés-szolgáltatókat. hogy egy regisztrációs űrlapot meglátva rögtön visszafordult és másik szolgáltatást keresett. Emberünknek csak egy már létező nevet és jelszót kell beírnia. Azure Storage használatáról szóló fejezetrész után már mindkettővel rendelkezünk. Megtehetnénk. hanem a Windows Phone 7 Cloud Application típust válasszuk. természetes igényként jelentkezik a felhasználók kezelése. akkor ezt nem mi magunk írjuk meg.

Ezúttal dolgozhatunk az Azure Storage emulátorral is.azure. majd kattintsunk a Next gombra! A következő párbeszédablakban kell megadnunk a használni kívánt hitelesítési mechanizmust.Felhasználó-hitelesítés szerveroldalról 9-12 ábra: A Windows Phone 7 Cloud Application projekttípus Ez a projekttípus nem egy üres alkalmazást. amiket be is kérdez tőlünk.NET Membership-et. de a példa kedvéért használjuk az Access Control Service-t. Ha még nincs egy sem. Most mindössze annyi dolgunk van. valamint hogy milyen Push Notification típusokat szeretnénk használni. és várjuk meg. A bal felső sarokban válasszuk az Access Control elemet! Megjelennek a már létrehozott Access Control névtereink. jelöljük ki névterünket. és a szalagon kattintsunk rá az Access Control Service gombra (9-13 ábra)! Megnyílik egy újabb webes interfész. ahová az ACS hitelesítési adatainkat kell beírnunk. 241 . ahol szolgáltatásunkat konfigurálhatjuk. Az első képernyőn azt kell megadnunk. hanem egy kész sablont generál. úgyhogy nyissuk meg a portált a http://windows. hogy leszedjük a portálról az ACS konfigurálásához szükséges hitelesítési adatokat. akkor a New gomb segítségével hozzunk egyet létre. Válasszuk tehát az Use the Windows Azure Access Control Service lehetőséget! Megjelenik két szövegmező. Itt bejelölhetnénk az ASP.com címen! A portál bal alsó sarkában kattintsunk a Service Bus. Ezeket az Azure menedzsment portálról tudjuk leszedni. Access Control & Caching kategórianévre! Megnyílik a kategória. Ehhez bizonyos alapinformációkra van szüksége. hogy hol akarjuk tárolni fájljainkat (azaz egy Azure Storage account-ot). amíg státusza Activating-ról Active-ra vált! Ez néhány percig is eltarthat! Miután a fentiekkel elkészültünk. Ezt nagyrészt elvégzi majd helyettünk a varázsló. így pipáljuk be az Use Storage Emulator jelölőnégyzetet.

9. és másoljuk ki az ott megjelenített értéket (9-14 ábra)! 9-14 ábra: Access Control szolgáltatásunk menedzsment-jelszava 242 . Kommunikáció szerverrel 9-13 ábra: Az Access Control a Windows Azure portálon Az Access Control webes interfészének bal oldalán kattintsunk a Management service elemre. majd válasszuk a Management Client elemet a Management Service Accounts listából! Megjelennek az Access Control szolgáltatásunk menedzseléséhez használható hitelesítési adatok. Kattintsunk a Password elemre.

vagy a készülék képességeinél sokkal nagyobb erőforrásigényű feladatokat is elvégezhet. Ha ez megtörténik. Az eddig megismert témakörökhöz hasonlóan az Access Control szolgáltatásból is csak a legszükségesebbeket láttuk. és közösségi szolgáltatásokat nyújthat. majd kattintsunk az OK gombra! A varázsló létrehozza az alkalmazássablont. hogy az ACS (az Azure többi szolgáltatásához hasonlóan) önállóan is igénybe vehető. így egy ideig eltarthat. hogy alkalmazásfejlesztés közben milyen lehetőségeink vannak az interneten keresztül történő kommunikációra. Mellette külön indítsuk el a Windows Phone alkalmazást is: jobb gombbal kattintsunk az AcsSample. Indítsuk el az F5 gombbal! Ennek hatására beindul a szerveroldali komponens az Azure emulátorban. Érdemes utánaolvasni a Toolkit honlapján és az Azure dokumentumaiban.Összefoglalás Access Control szolgáltatásunk nevét és az imént kimásolt jelszót illesszük be a Visual Studio párbeszédpanelbe. hogy projektünket újra be kell tölteni. Vegyük figyelembe. a Reload gombra kattintva hagyjuk jóvá a műveletet! Alkalmazásunk rögtön kész is a tesztelésre. Egy hálózati képességekkel felruházott alkalmazás túllép a telefon korlátain. Érdemes élni a platform által nyújtott lehetőségekkel! 243 .Phone projekt nevére. és a Debug almenüből válasszuk a Start new instance menüpontot! A telefonalkalmazás megnyílik. Ez egy komplex műveletsor. és bejelentkezhetünk az általunk választott hitelesítés-szolgáltató segítségével. így érdemes elgondolkodnunk alkalmazásán! Összefoglalás A fejezetben megismertük. mert a kódgeneráláson felül Access Control szolgáltatásunk konfigurációja is megtörténik a háttérben. Az alkalmazás teljes forráskódját pedig megtekinthetjük a Visual Studióban. A kód létrehozása után kaphatunk egy Visual Studio figyelmeztetést. ráadásul használata meglehetősen olcsó.

.

A telefon kezdőlapja nem élettelen ikonokból áll. Ezért lehetőségünk van felugró üzenetet (toast notification) is küldeni – ilyen például az SMS érkezésekor látható sáv. hanem nagyméretű lapkákból. 10-1 ábra: Windows Phone lapkák A lapkákon képeket. A fejezetben részletesen megismerkedünk a lapkák és a további értesítési szolgáltatások képességeivel. Lapkák és értesítések A Windows Phone egyedi lehetőséget biztosít a felhasználóval való kapcsolattartásra – ez pedig a live tile (magyarul élő lapkának fordíthatjuk). programozásával. akkor sokkal gazdagabb élményt kínálhatunk. Alkalmazásunkhoz akár több lapka is tartozhat. szöveget vagy számot jeleníthetünk meg. az alkalmazás futása nélkül is. amelyeket esetleg egy szám megjelenítésével dinamikussá lehet tenni.10. Ezek az üzenetek a felhasználó aktuális tevékenységétől függetlenül mindig megjelennek. mintha 245 . melyek tartalmát a fejlesztő szabadon változtathatja – ahogyan azt a 10-1 ábra mutatja. A lapkák a telefon kezdőképernyőjén kapnak helyet. így ha más módon nem tudnánk üzenni a felhasználónak. A lapkákhoz –mint értesítési felülethez – szorosan kapcsolódnak a Windows Phone által kínált további értesítési szolgáltatások. fontos eseményekről maradna le. Frissíthetjük őket az alkalmazás futtatása közben. hanem a telefonon futó alkalmazásunknak akarunk üzenni. de akár szerveroldalról. 10-2 ábra: Felugró üzenet Végül az is lehet. A platform eszközeivel erre is lehetőségünk van. például minden folyamatban lévő játszmához egy-egy. Ha ezeket jól tudjuk használni. ahogyan azt a 10-2 ábra illusztrálja. hogy egy külső eseményről nem a felhasználót szeretnénk tájékoztatni.

Egy légitársaság alkalmazása felugró üzenettel értesítheti a felhasználót. ha bármi változás történt – így az alkalmazás mindig a legfrissebb információ birtokában van. hogy a felhasználó kitűzi majd kezdőlapjára alkalmazásunkat. és valós időben értesíthetjük a számára fontos eseményekről. Méret A Windows Phone kétféle méretű lapkát támogat: négyzet alakút. 10-3 ábra: A kétféle méretű Windows Phone lapka 246 . Ízléses képek használatával szinte biztosra vehetjük. mely nagyjából két négyzet szélességének megfelelő.10. A felhasználót már a kezdőképernyőről folyamatos információkkal láthatjuk el. hogy később hatékonyan tudjuk őket felhasználni. hogy újra és újra visszatér majd alkalmazásunkhoz. másrészt pedig késztetést érez majd az alkalmazás megnyitására. viszonylag kevés információt közöl a felhasználóval – legyen az névnap-előrejelző. ám valójában rengeteg jellemzővel és képességgel ruházták fel őket a Windows Phone fejlesztői. sportfogadó-alkalmazásunkban a szerver üzenhet az alkalmazásnak. ha járatával bármi történik – így a felhasználó a weboldal folyamatos nézegetése nélkül is állandóan naprakész lehet. egyszínű négyzeteknek tűnnek. Hasonlóképp érdemes lapkákat használni minden olyan alkalmazásban. Ha az ellenfél megtette lépését. A következőkben megismerkedünk ezekkel a jellemzőkkel. hogy rendszeres időközönként kérdezgetnénk (és így feleslegesen terhelnénk) a szervert. felesleges adatforgalom nélkül. Ahelyett. így sokkal valószínűbb. Sakk-alkalmazásunkban minden egyes folyamatban lévő játszmához tartozhat egy lapka. ami gyakran változó. A 10-3 ábra felső részében a négyzet alakú. és széleset. Lapkák és értesítések alkalmazásunk csak bezárásáig működne. melyekből kettő fér egymás mellé. Így a felhasználó egyrészt nyomon követheti a történéseket. alsó részében pedig a szélesebb lapkát láthatjuk.     A lapkák tulajdonságai A lapkák egyszerű. Időjárás-előrejelző alkalmazásunkban a lapkát rendszeresen frissíthetjük a várható időjárással. Néhány példa a lapkák és értesítések használatára  Közösségi oldalunkhoz tartozó alkalmazásunk számmal jelenítheti meg a felhasználó olvasatlan üzeneteinek számát. részvényárfolyam-letöltő vagy focipontszám-nyilvántartó. ő pedig arra nyomva egyből a megfelelő játszmában találhatja magát. szöveggel pedig kiírhatja a legújabb üzenetet. ezt a lapkán keresztül közölhetjük a felhasználóval.

a széles lapkák számunkra nem használhatók. Ám alapértelmezésként ezek a lapkák mindössze az alkalmazás ikonjából és nevéből állnak. arra kizárólag a felhasználónak van joga. Azonban lapka kitűzését kódból még kezdeményezni sem tudjuk. Minden tulajdonság pontosan meghatározott módon változtatja meg a 247 . ha alkalmazásunk lapkája is megjelenik ott. a tartalmát a program frissíti A lapkák felépítése A lapkák megjelenítését egy sor előre definiált tulajdonsággal szabályozhatjuk (ezek kódból történő felhasználását később tárgyaljuk). Az ilyen képességekkel felruházott lapkákat nevezzük dinamikusnak. Ez csak az alkalmazás elsődleges lapkájára érvényes. és törölhetjük is őket a kezdőképernyőről. a részleteket lásd később. a négyzet alakú lapkák 173 pixel szélesek és magasak. A pontosság kedvéért: a Windows Phone teljes kijelzője 480 pixel széles és 800 pixel magas.A lapkák tulajdonságai Széles lapkája mindössze néhány beépített Windows Phone alkalmazásnak van – ilyenek pl. A frissen feltelepített alkalmazások alapértelmezésként nem kerülnek ki a kezdőképernyőre. ezért nagyon jó. 10-5 ábra: Dinamikus lapka. az külön programozói erőfeszítés nélkül is kitűzhető lesz a kezdőképernyőre. Statikus és dinamikus lapkák Ha egy alkalmazást fejlesztünk. fejlesztők kizárólag négyzet alakú lapkával rendelkező alkalmazásokat tudunk fejleszteni. hogy egy telefon felhasználójaként tetszésünknek megfelelően rendezhetjük el őket – megváltoztathatjuk sorrendjüket. ahogyan azt a 10-4 ábra illusztrálja. megnyomáskor az alkalmazás kezdőlapjára visznek – vagyis ezek a statikus lapkák. Mi. Kiszögezés és elrendezés A lapkák fontos jellemzője. azaz rendelkezik majd lapkával. Egy ilyen dinamikus lapkára mutat példát a 10-5 ábra. animálhatjuk. a Calendar és a Pictures. Mivel a kezdőképernyőt a felhasználó a telefon minden bekapcsolásakor látja. 10-4 ábra: Statikus lapka az alkalmazás nevével és ikonjával A később megismert technikákkal a lapka tartalmát frissíthetjük. a másodlagos lapkák tárgyalásánál. és a lapka törlésével a hozzá tartozó alkalmazás nem kerül eltávolításra.

minden Windows Phone alkalmazás rendelkezik legalább egy lapkával. Ennek angol neve: application tile. Tartalom – nagyobb betűkkel. ahogyan azt a 10-6 ábra mutatja. ugyanazzal a betűtípussal jelenik meg. akkor csak a háttérképet használjuk. másodlagos lapkák (angolul: secondary tile) létrehozására is. Például a cím mindig a bal alsó sarokban. a lapka felső részében megjelenő felirat. hogy azt is mutassa. Másodlagos lapkák Amint korábban láttuk. Fejlesztőként lehetőségünk van további. Cím – kis betűkkel. mint az elülső felület képe. Minden lapka két felülettel rendelkezik: egy elülsővel és egy hátsóval. a bal alsó sorban megjelenő felirat. A másodlagos lapkák létrehozására kicsit eltérő szabályok vonatkoznak. maximum 99 lehet (0 esetén nem jelenik meg). ha a hátsónak is adunk valamilyen tartalmat. Alapértelmezésként csak az elülső felület látható. 10-6 ábra: Lapka címmel és számlálóval A hátsó felület lehetséges tulajdonságai:    Háttérkép – a teljes lapkát kitöltő kép. amint azt a 10-7 ábra mutatja. Lapkák és értesítések lapka megjelenését. Értéke minimum 1. ám ehhez az alábbi feltételeknek kell teljesülniük: 248 . Az elülső felület lehetséges tulajdonságai:    Háttérkép – a teljes lapkát kitöltő kép (emlékeztetőül: a lapkák 173 pixel szélesek és magasak). Például ha egy játékszoftvert írunk. és ez más lehet. Ha valamiért teljesen egyedi formatervet szeretnénk. Másodlagos lapkát már létrehozhatunk kódból. akkor a lapka időnként megfordul a tengelye körül. a bal alsó sorban megjelenő felirat. mint az elsődlegesekére. Cím – kis betűkkel.10. amire aztán tetszésünk szerint bármit rajzolhatunk. Számláló – a jobb felső sarokban. Nem kötelező minden tulajdonságot beállítanunk. 10-7 ábra: Egy lapka hátsó felülete címmel és tartalommal Ezeket a tulajdonságokat használva a többi Windows Phone alkalmazással konzisztens lapkákat hozhatunk létre. amely szintén különbözhet az elülső felület címétől. kör közepére írt szám. akkor minden egyes folyamatban lévő játékhoz tartozhat egy másodlagos lapka.

1 (vagy újabb) verziójú projektet hozzunk létre. a másodlagos lapkái még megmaradnak. amivel már alkalmazásunk kódjából is tudjuk manipulálni lapkáinkat. Ha a felhasználó törli az alkalmazás elsődleges lapkáját. azok pontosan hogyan is indítsák el alkalmazásunkat. hogy megadhatjuk. akkor erre a később ismertetett lehetőségeket használhatjuk. hogy a másodlagos lapka kitűzését követően programunkat leállítja a telefon. hiszen minden egyes másodlagos lapka létrehozását a felhasználónak kell kezdeményeznie.5-ös. 7. hogy minden másodlagos lapkának különböző linkkel kell rendelkeznie. Lapkák létrehozása és frissítése alkalmazásunkból A ShellTile API A Windows Phone első. 249 . Lapka frissítése Elsőként nézzük. A kód nagyon egyszerű. Fontos. Azaz rendelkeznünk kell egy „Lapka hozzáadása” gombbal vagy jelölőnégyzettel. neve LocalTileApiSample! Fontos. A szabályokat betartva tetszőleges számú másodlagos lapkát hozhatunk létre – ez nem jelent biztonsági problémát. és a kezdőképernyőre visszaugorva megmutatja a felhasználónak a frissen kitűzött lapkát. azt egy példaalkalmazáson keresztül ismerhetjük meg: Hozzunk létre egy új Visual Studio projektet! A projekt típusa legyen az alapértelmezett Windows Phone Application. Mango kiadásban megjelent a ShellTile API. hogy egy véletlenül feltelepített rosszindulatú (vagy csak hanyagul megírt) alkalmazás teleszemetelje gondosan kialakított kezdőképernyőjét. hogy a projekt létrehozása után megjelenő párbeszédpanelen Windows Phone OS 7. másrészt ennek a képernyőnek (XAML fájlnak) paramétereket is át tudunk adni. futásidejű hibát (InvalidOperationException) kapunk. hogyan lehet egy már létező lapka adatait frissíteni! A módszer ugyanaz elsődleges lapkák és másodlagos lapkák esetén is.xaml?id=3 Webprogramozóknak ez a felépítés ismerős lehet – az interneten is ugyanígy tudunk paramétereket átadni egy webalkalmazásnak. Ez egyrészt tartalmazza.0-ás kiadásában a lapkákat kizárólag egy külső szerver igénybevételével lehetett frissíteni. amint azt a 10-8 ábra mutatja. Deep Linking A másodlagos lapkák nagy előnye. Ha egy már létező linket megpróbálunk újra felhasználni. Ezt a korlátozást az alkalmazás piactérbe (Marketplace) való feltöltésekor ellenőrzik le – ha nem tettünk neki eleget. Egy ilyen URL lehet például az alábbi: /MainPage. Figyelembe kell vennünk. alkalmazásunkat visszautasítják. például valamilyen időzítés szerint vagy külső esemény hatására szeretnénk lapkáinkat frissíteni.  Ezek a szabályok a felhasználó biztonságát szolgálják. A 7. és a már létező lapkák tulajdonságainak frissítésére. A ShellTile API egyaránt alkalmas másodlagos lapkák létrehozására. A másodlagos lapkák létrehozásakor ugyanis be kell állítanunk egy alkalmazásunkra mutató URL-t is. Ez esetenként jelentős pluszmunkát és pluszköltséget jelenthetett. Senki sem szeretné. hogy alkalmazásunk mely képernyőjét (XAML fájlját) nyissa meg a lapka.Lapkák létrehozása és frissítése alkalmazásunkból  A másodlagos lapka kitűzését végző kód csak egy egyértelműen erre a célra szolgáló vezérlőelem hatására futhat le. Ha az alkalmazás futásán kívül. Segítségével az alkalmazás futása alatt tudunk műveleteket végezni.

//Számláló az elülső oldalon 250 . egyiket sem kötelező használni – saját alkalmazásunkban majd csak azokat állítsuk be.Shell. A ShellTile objektumot alapértelmezésként nem ismeri fel a Visual Studio. „elsődleges lapka frissítése” felirattal! Nevezzük el ezt UpdateAppTileButton-nak! A nyomógomb a szerkesztőfelületen úgy jelenik meg. ezzel belépünk a gombhoz tartozó eseménykezelő kódba. amely a megadni kívánt új adatokat tartalmazza. amelyekre szükségünk van! Kezdjük a lapka elülső oldalán található címmel és számlálóval! tileData. ha a lapka még nincs kitűzve a telefon kezdőképernyőjére. A lapka frissítéséhez létre kell hoznunk egy adatszerkezetet. StandardTileData tileData = new StandardTileData(). Az első kódsorból látható. Lapkák és értesítések 10-8 ábra: Windows Phone OS 7. Ez az elem minden esetben az alkalmazás elsődleges lapkáját tartalmazza.ActiveTiles. //Cím az elülső oldalon tileData.Phone.First(). akkor régi SDK-t használunk – frissítsünk a legújabb verzióra! A projekt létrejötte után helyezzünk el az alkalmazás felületén egy új gombot. ahogyan azt a 10-9 ábra mutatja.1 változat használata Ha ez a kérdés nem jelenik meg. 10-9 ábra: Az új nyomógomb a szerkesztőfelületen A szerkesztőfelületen kattintsunk duplán a gombra. Most állítsuk be a lapka tulajdonságainak új értékeit! Amint korábban láttuk. Így begépelése után írjuk a következő sort a kódfájl legtetejére: using Microsoft.Title = "Elülső cím".Count = 15. és akkor is létezik (azaz nem null).10. Szerezzünk egy referenciát az alkalmazásunkhoz tartozó elsődleges lapkára! Ehhez írjuk be az alábbi sort: var appTile = ShellTile. hogy az ActiveTiles gyűjtemény legfelső elemét kérjük el a platformtól.

Mentsük el a képet PNG vagy JPG formátumban. majd a Properties ablakban állítsuk Build Action tulajdonságát Content értékűre! 10-11 ábra: Képfájl felvétele az alkalmazásba tartalomként Miután ezzel elkészültünk. de ha eltérő méretűt hozunk létre. tileData..Lapkák létrehozása és frissítése alkalmazásunkból Adjunk meg egy háttérképet is! Egy lapkára előre elkészített. statikus képet is helyezhetünk. Kezdjük most egy előre gyártott képpel! Kedvenc képszerkesztő alkalmazásunkban hozzunk létre egy képet! Érdemes 173×173 pixelesre gyártani. már nincs más dolgunk. A sor végén található UriKind. AppTileBackground néven! Térjünk vissza a Visual Studióba. és szúrjuk be alkalmazásunkba! 10-10 ábra: Az Add Existing Item funkció kiválasztása Most közölnünk kell a Visual Studióval. Ez adja meg. Ha ezt nem írjuk be.Relative).Relative paraméter nagyon fontos. A Solution Explorer-ben jelöljük ki a frissen beszúrt fájlt. akkor a telefon azt átméretezi majd nekünk.BackgroundImage = new Uri("/AppTileBackground. a program hibára fut. hogy a frissen megadott fájlt tartalomként akarjuk használni – ezután tudunk majd kódból hozzáférni. UriKind. 251 . és a Solution Explorer ablakban kattintsunk jobb gombbal a projekt nevére (LocalTileApiSample). mint beírni a tileData adatstruktúrába az így létrehozott kép URL-jét. majd az Add menüből válasszuk az Existing Item. hogy az URL relatívként értelmezendő. menüpontot (10-10 ábra)! Tallózzuk ki az imént létrehozott képet.. vagy akár egy képfájlra mutató internetes URL-t is megadhatunk.png".

amint azt a 10-12 ábra is mutatja. Futtassuk programunkat az F5 megnyomásával! Az emulátorban tűzzük ki a programot a telefon kezdőképernyőjére.BackContent = "Tartalom". A megírt teljes metódus törzse az alábbi: 252 . és nyomjuk meg az „Elsődleges lapka frissítése” gombot! Ha ezután visszatérünk a kezdőképernyőre. amint azt a 10-13 ábra mutatja: 10-13 ábra: A lapka hátoldala Ezzel a lapkák valamennyi tulajdonságának beállítását és használatát láttuk.BackTitle = "Hátulsó cím". amely egy szöveges értéket vár. majd vágjuk ki ennek URL-jét a böngészőből! (A kép ne legyen túl nagy. Lapkák és értesítések Ezzel elkészültünk a lapka első oldalának beállításával.10. mit alkottunk! Az elkészült beállítások életbeléptetéséhez az alábbi sort kell beírnunk. és állítsuk be a lapka hátsó felületének tulajdonságait is! A következő kódrészleteket az appTile. nekünk nincs beleszólásunk) a lapka megfordul majd. Háttérképnek most ne egy helyi. helyette Content van.Update(tileData). hogy a lapka tulajdonságai tényleg megváltoztak.BackBackgroundImage = new Uri("http://IKON_AZ_INTERNETROL"). látni fogjuk. és láthatjuk a beállításaink eredményét. Újra futtassuk le az alkalmazásunkat! Nyomjuk meg az „Elsődleges lapka frissítése” gombot. kisméretű ikont. Alkalmazzuk az idáig elkészült beállításokat. 10-12 ábra: A lapka megjelenése a kezdőképernyőn Térjünk vissza a Visual Studióhoz.Update(tileData). sor fölé írjuk be! A hátoldalon szintén van Title tulajdonság. számláló viszont nincs. majd lépjünk be abba. és nézzük meg. majd a telefon Windows gombjával lépjünk ki a kezdőképernyőre! Néhány másodperc elteltével (amit kizárólag a telefon határoz meg. mert a nagyon elhúzódó letöltéseket a telefon megszakítja!) tileData. tileData. hanem egy internetes képet válasszunk! Kedvenc képkereső szolgáltatásunkkal keressünk egy szimpatikus. appTile. tileData.

ActiveTiles. UriKind. így ezeket feldolgozva egyből programunk „belsejébe” (pl.) vihetjük a felhasználót.xaml?color=blue". tileData. tileData. hogy eljussunk a kódnézetbe! Másodlagos lapka létrehozásához ugyanarra a StandardTileData adatszerkezetre lesz szükségünk. hogy nem kell minden tulajdonságot megadnunk.Title = "Kék". Készítésükkor pedig paramétereket építhetünk beléjük. hogy a gomb feliratát és paraméterét átírjuk „Piros”-ra és red-re)! Most állítsuk be. A gombok nevei legyenek BlueButton és RedButton! Létrehozásuk után kattintsunk duplán a „Kék” feliratú gombra.First(). appTile.Relative). tileData. Miután ezzel megvagyunk. másrészt egy paramétert is átadunk (neve: color. hogy a felhasználó melyik lapka segítségével indította el. A „Kék” gomb hatására létrehozott másodlagos lapka kék háttérszínnel. Kihasználva. RoutedEventArgs e) { var appTile = ShellTile. értéke: blue). a megfelelő játszmába. UriKind.xaml). hogy két részből áll: egyrészt megadjuk a megnyitandó Silverlight nézetet (MainPage. Hozzunk létre programunk felületén két gombot. és gépeljük be: override onnavigatedto 253 . StandardTileData tileData = new StandardTileData(). Nézzük meg figyelmesen a lapka beágyazott URI-ját! Láthatjuk.BackgroundImage = new Uri("/AppTileBackground. tileData. Alkalmazásunk e paraméter alapján tudja ellenőrizni majd. } Másodlagos lapka létrehozása Amint korábban már láttuk. tileData.BackTitle = "Hátulsó cím". hogy a lapkákra kattintva alkalmazásunk a megfelelő háttérszínben pompázva induljon – azaz használjuk a Deep Linking lehetőséget! A háttérszínt beállító kódot akkor kell futtatnunk. megfelelő részvényhez stb. mint amit az előző fejezetrészben is használtunk. a másikat „Piros” felirattal! A gombok megnyomására alkalmazásunk egy-egy másodlagos lapkát hoz majd létre. alkalmazásunkhoz tartozhatnak másodlagos lapkák is. a leendő másodlagos lapka csak címet kap: StandardTileData tileData = new StandardTileData().BackContent = "Tartalom". //Számláló az elülső oldalon tileData.Title = "Elülső cím".BackBackgroundImage = new Uri("http://IKON_AZ_INTERNETROL"). egyiket „Kék”.Lapkák létrehozása és frissítése alkalmazásunkból private void UpdateAppTileButton_Click(object sender. az itt beírt három sort másoljuk át a „Piros” gomb Click eseményének kezelőjébe is (ügyelve arra.Create(new Uri("/MainPage. amikor alkalmazásunk betöltődik.Update(tileData). amiket megnyomásukkor megkap az alkalmazás.Count = 15. Az így elkészült másodlagos lapkát pedig egyszerűen felvesszük az alkalmazás lapkái közé: ShellTile.Relative).png". Ezeket (a felhasználó kérésére) kódból mi magunk hozhatjuk létre. a másik pedig piros háttérszínnel indítja majd programunkat. tileData). Használjuk erre az OnNavigatedTo eseményt! Álljunk a kurzorral egy üres kódsorhoz (mondjuk közvetlenül a private void UpdateAppTileButton_Click sor fölé). //Cím az elülső oldalon tileData.

xaml?color=blue"). Fontos tudni. stb. hogy a lekérdezéshez használt módszert használhatjuk a lapka létrehozása előtt is.Blue). DeleteBlueButton névvel. majd a Piros gombot! Látni fogjuk. A kikereséshez használhatjuk a lapka URL tulajdonságát. A létrehozott lapkákat megnyomva pedig alkalmazásunk újra elindul – a kiválasztott háttérszínnel. hogy létezik-e a törölni kívánt lapka a gyűjteményben. Egyszerűen védekezhetünk ez ellen a hibalehetőség ellen. hogy egyáltalán kaptunk-e color nevű paramétert. Vagyis ha a Kék gombot még egyszer megnyomjuk.ToString() == "/MainPage. hogy ennek értéke blue-e. akkor alkalmazásunk hibára fut. Ez a módszer nem igényel külső szervert. és létrehoz nekünk egy-egy új másodlagos lapkát. 254 . A lapkák igazi haszna azonban éppen abban rejlik. majd leellenőrizzük. amely garantáltan egyedi – ahogyan azt korábban már bemutattam.ActiveTiles. korábban létrehozott lapkát. hogy a ShellTile. if (NavigationContext. akkor alkalmazásunk hátterét kékre állítjuk. annak ellenőrzésére.ContainsKey("color") && NavigationContext. Ha egyezést találunk. Erre a felhasználónak az alkalmazásunktól függetlenül is van lehetősége. hogy a kirakott másodlagos lapkákat törölni szeretnénk. letörli: if (ShellTile.10.Single(i => i. és időzített frissítést használ. Hozzunk létre egy újabb gombot felületünkön. és ha létezik. Az alábbi kódrészlet (a C#-ba épített LINQ lekérdezőnyelv segítségével) ellenőrzi.ActiveTiles gyűjtemény tartalmaz-e már a létrehozni kívánt URL-lel egy lapkát. majd meghívni a Delete() metódusát. mint a Tab gomb megnyomásával létrehozni ezt az eseménykezelőt.Delete(). bővíteni és törölni lapkáinkat. hogy azok képesek alkalmazásunk futása nélkül is frissülni! A következő fejezetrészben a lapkák Background Agentből való frissítését ismerjük meg. „Kék törlése” felirattal. Ezt a mechanizmust kihasználva a háttérszín-váltásnál sokkal komplexebb belső navigációt is kivitelezhetünk.NavigationUri.xaml?color=blue") > 0) { ShellTile. Lapkák és értesítések A Visual Studio erre egy listából felkínálja számunkra azt az eseményt. hogy a telefon mindkét gomb megnyomására bezárja az alkalmazásunkat. amelynek kódját felül szeretnénk írni. repülőút. azaz alkalmazásunk leállása után is működik.Background = new SolidColorBrush(Colors.ToString() == "/MainPage. Nincs más dolgunk. Az eseménykezelőn belül a NavigationContext objektum QueryString tulajdonságán keresztül kérhetjük el alkalmazásunk indítási paramétereit.QueryString. Elsőként megnézzük.ActiveTiles. } Ezt a kódrészletet még egyszer – értelemszerűen – felhasználva tudjuk kezelni a piros szín esetét is. Másodlagos lapka törlése Előfordulhat. ha a lapka kirakása előtt ellenőrizzük.QueryString["color"] == "blue") { LayoutRoot.Count(i => i. majd dupla kattintással lépjünk be az eseménykezelőjébe! A lapka törléséhez egyszerűen ki kell azt keresnünk a lapkák gyűjteményéből.NavigationUri. Futtassuk az F5 gombbal alkalmazásunkat! Nyomjuk meg előbb a Kék. lezárulta után célszerű automatikusan törölni a hozzá tartozó. hogy egy adott URL-ű másodlagos lapkából egyszerre csak egy lehet. hogy az nem létezik-e már! Lapkák frissítése Background Agent-ek segítségével A korábban bemutatott ShellTile API segítségével alkalmazásunk futása alatt teljes körűen tudjuk frissíteni. } Vegyük észre. de az aktuális játszma.

Kattintsunk jobb gombbal a BackgroundAgentTileUpdateSample projekt References mappájára. hogy hol találja a neki rendelt Background Agent-et. tudatnunk kell a telefonalkalmazással. Példaalkalmazásunk az aktuális időt írja majd ki a lapkára.Lapkák frissítése Background Agent-ek segítségével A Background Agent a Windows Phone 7. fejezete foglalkozik. így az előző fejezetrészben megismerteket hasznosíthatjuk újra. A példaprogram elkészítése során csak a Background Agent funkcionalitásának szükséges részét használjuk ki. Készítsünk egy új Visual Studio projektet. Ezért ezt a sort ne töröljük ki. így ide kell elhelyeznünk a lapkát frissítő kódunkat. és hagyjuk mindig a saját kódunk után! A lapka frissítésére a ShellTile API-t vehetjük igénybe. Ez a háttérben futva rendszeres időközönként frissíti majd az alkalmazás lapkáját. A kód megírásához először is szükségünk van egy sor névtérre. amint azt a 10-14 ábra mutatja! 10-14 ábra: A Background Agent projekt hozzáadása Itt ismét találkozunk a projektek listájával. és a megjelenő ablak Projects fülén válasszuk ki a ScheduledTaskAgent1 elemet! A projektfájlok létrejötte után a Visual Studio automatikusan megnyitja számunkra a ScheduledAgent. amely egy Background Agentet regisztrál be. Miután mindkét projektünket létrehoztuk. Ehhez a BackgroundAgentTileUpdateSample projektből fel kell vennünk egy referenciát a ScheduledTaskAgent1 projektre. Egy éles alkalmazás ennél természetesen sokkal bonyolultabb logikát is meghívhat a Background Agent-ből.1 verziót (vagy újabbat) válasszunk! A Background Agent kódját külön projektbe kell helyeznünk. Hozzunk létre egy Windows Phone Scheduled Task Agent típusú projektet! Ennek neve maradhat az alapértelmezett ScheduledTaskAgent1.cs) legtetejére! 255 . A Background Agent futásakor az itt található OnInvoke() metódust hívja meg a futtatókörnyezet. hogy a Background Agent elvégezte a rábízott feladatokat. fejezetben. A következő oldalakon egy példaprogramot készítünk.5-ben debütált. Részletes ismertetésével a könyv 5. legyen ez egy Windows Phone Application! Projektünk neve legyen BackgroundAgentTileUpdateSample! Az előző fejezetrészhez hasonlóan itt is Windows Phone OS 7. A szolgáltatás teljes leírása megtalálható az 5. és az Add menüből válasszuk a New Project lehetőséget. és futása leállítható. számos egyéb rendszeresen végrehajtandó vagy erőforrás-igényes feladat elvégzésére használható. A metódus végén már megtalálható a NotifyComplete() hívás. A Windows Phone Application projekt létrejötte után kattintsunk jobb gombbal a Solution Explorer ablak legtetején található Solution ’BackgroundAgentTileUpdateSample’ sorra. Írjuk be az alábbiakat a kódfájl (ScheduledAgent. válasszuk az Add Reference lehetőséget. Ez jelzi az operációs rendszer számára.cs állományt. és nem kizárólag a lapkák frissítésére való – épp ellenkezőleg.

de rendszeresen szeretnénk elvégezni. Lapkák és értesítések using System.catch blokk belsejébe. using System. így a PeriodicTask időzítési módot használjuk. Miután ezzel megvagyunk.Remove(periodicTaskName). külső áramellátás) megléte esetén kap futási jogot. ha a felhasználó a kéthetes automatikus törlési időszak alatt újra kéri a Background Agent időzítését. dupla kattintással lépjünk be a gomb Click eseménykezelőjébe! A kódfájl tetejére helyezzük el az alábbi névteret. 10 percig. Első feladatunk. Ha igen. Minden Windows Phone alkalmazáshoz legfeljebb egy Background Agent tartozhat. ami a Background Agent-ek időzítéséhez szükséges eszközöket tartalmazza! using Microsoft.. Ezt kétféle módon időzíthetjük:   PeriodicTask időzítési mód: A Background Agent rövid ideig (25 másodpercig) kap futási jogot kb. tileData.Find(periodicTaskName) as PeriodicTask. melyről egy kivétel formájában értesülünk. Ezután következik a tényleges időzítés.10.Scheduler. 30 percenként.First(). ShellTile. ha egy éles alkalmazásban erre valamilyen módon emlékeztetjük. Ehhez először egy objektum formájában létrehozzuk és beállítjuk a leírását (ezt látja majd a felhasználó az operációs rendszer beállításai között. A lapka frissítése jellemzően nem erőforrás-igényes. ugyanis a felhasználó a telefon beállításai között letilthatja a Background Agent-eket. A Background Agent-et ezzel felprogramoztuk.ToShortTimeString(). ehhez telefonalkalmazásunknak előbb időzítenie kell azt. felirata legyen „Background Agent időzítése”. neve pedig ScheduleBackgroundAgentButton! Miután kihúztuk. Az időzítő az egyes Background Agent-eket nevük alapján azonosítja. if (periodicTask != null) ScheduledActionService.Linq. az épp futó Background Agent-ek listájában).Now.Update(tileData).. Fontos tudni. a lapka címét frissíti a ShellTile API segítségével: StandardTileData tileData = new StandardTileData(). így felhasználónknak legalább ilyen gyakorisággal újra kell időzíttetnie – célszerű. ResourceIntensiveTask időzítési mód: bizonyos külső feltételek (pl. hogy időzítése után két héttel a Background Agent automatikusan törlődik a rendszerből. hogy ellenőrizzük. létezik-e már az általunk kívánt néven Background Agent.) Ennek elvégzéséhez helyezzük az alábbi sorokat a gomb eseménykezelőjébe: string periodicTaskName = "TileUpdaterSample".Phone.Phone. using Microsoft. letöröljük.ActiveTiles. 256 .Title = DateTime. Húzzunk ki a kezelőfelületre egy gombot. PeriodicTask periodicTask = ScheduledActionService. Ezt mindenképp tegyük egy try. Ezután utasítjuk a futtatókörnyezetet a Background Agent időzítésére. (Ez könnyen előfordulhat.Shell. Magától természetesen nem fog lefutni. Térjünk vissza a BackgroundAgentTileUpdateSample projektbe! A Background Agent időzítését egy gomb végzi majd. gépeljük be az alábbi kódot az OnInvoke() metódusba (a NotifyComplete() fölé)! Ez semmi újdonságot nem tartalmaz.

periodicTask. amellyel a Background Agent lefuttatása néhány másodperc várakozás után kikényszeríthető. 10-15 ábra: A Background Agent által frissített lapka Ha szeretnénk.". hogy a fenti kódban semmilyen módon nem adtuk meg.Description = "This is the Tile Updater sample.Message). amint azt a 10-15 ábra is mutatja. Ehhez lépjünk be a telefon beállításai közé (Settings). mert a Marketplace ellenőrzésen valószínűleg meg fog bukni! ScheduledActionService. Ezzel tulajdonképpen elkészültünk. A próbafuttatáshoz érdemes beírni a következő programsort is. A futtatókörnyezet biztosít egy hívást. és nyomjuk meg a Background Tasks lehetőséget (10-16 ábra)! 257 .Show(ex. hogy az Agent lefuthasson! Tűzzük ki alkalmazásunkat a kezdőképernyőre! Kisvártatva tanúi leszünk a lapka frissülésének. a Background Agent működését megszemlélhetjük a telefon beállításai között is. } catch (Exception ex) { MessageBox. 30 percenként futnak. hogy korábban felvettünk egy referenciát a ScheduledTaskAgent1 projektre. lapozzunk az Applications fülre. ami nagyon megnehezíti a tesztelésüket. } Észrevehető.Add(periodicTask). melyik osztályt kívánjuk az időzített feladat futtatása során használni. ám a Background Agent-ek kb. Az F5 megnyomásával futtassuk alkalmazásunkat! Nyomjuk meg a „Background Agent időzítése” gombot. majd az emulátor Windows gombjával lépjünk ki programunkból. de az alkalmazás publikálása előtt feltétlenül töröljük ki.LaunchForTest(periodicTaskName.FromSeconds(30)). try { ScheduledActionService.Lapkák frissítése Background Agent-ek segítségével periodicTask = new PeriodicTask(periodicTaskName). és ezt Background Agent-nek ismerte fel. TimeSpan. Ezt az operációs rendszer onnan tudja.

fix alkalommal vagy határozatlan ideig)? Milyen gyakran történjen meg a frissítés (óránként. azaz nem használhatunk a telefonon lévő helyi erőforrásokat. és letöltése nem tarthat 30 másodpercnél tovább. A Background Agent nagy előnye.1 vagy újabb verziót célozva! A ShellTileSchedule beállítását már rögtön az alkalmazás indulásakor elvégezzük. A képfájl maximum 80 kilobájtos lehet. alkalmazásunk leállását követően is. hetente vagy havonta)?  Milyen URL-ről töltődjön le a kép? A letöltésre kiválasztott kép kizárólag internetes URL-ről származhat. szerver igénybevétele nélkül. Ehhez kódunkat helyezzük a MainPage() konstruktorába. a többi tulajdonság ezen az API-n keresztül nem módosítható. hogy a felhasználó a kezdőképernyőre tűzve tartsa alkalmazásunkat. Az időzítés beállításához az alábbi paramétereket adhatjuk meg: A frissíteni kívánt lapka (lehet elsődleges vagy valamelyik másodlagos lapka is)   Hányszor történjen meg a frissítés (egyszer. Egy folyamatosan frissülő lapka pedig jó ok arra. imperatív módon tudtuk frissíteni lapkáinkat.10. a telefon pedig egyszerűen csak letöltse azt. akkor az időzítést törli a futtatókörnyezet. A ShellTileSchedule ezek közül kizárólag a lapka elülső felületén található háttérképet tudja frissíteni. Használatához (a Background Agent-hez hasonlóan) alkalmazásunk futása közben időzítenünk kell a frissítéseket. amelyek utána a háttérben futnak majd. Lapkák és értesítések 10-16 ábra: Background Agent-ünk a telefon listájában A Background Agent segítségével alkalmazásunk a leállása után is naprakészen tarthatja lapkáját. hogy a megjelenítendő információt szerveroldalon készítsük elő. óránként szeretnénk frissíteni. hanem egy kiszolgálón állítjuk elő. 258 . Mindkét módszer segítségével a telefonon futó kódból. Időzítés beállítása az elsődleges lapkára Korábban megismerkedtünk a lapkák tulajdonságaival. Windows Phone OS 7. ami bemutatja a ShellTileSchedule használatát! Az eddigiekhez hasonlóan hozzunk létre egy új Windows Phone Application típusú projektet ShellTileScheduleSample néven. Ha az időzített művelet végrehajtása 3 egymást követő alkalommal sikertelen. ha a szükséges tartalmat nem a készüléken. Írjunk egy rövid példaprogramot. Bizonyos esetekben azonban kényelmesebb lehet. A ShellTileSchedule arra ad lehetőséget. hogy ehhez még külső szerverre sincs szüksége. naponta. közvetlenül az InitializeComponent() metódushívás után! Lapkánkat határozatlan ideig. Lapkák frissítése ShellTileSchedule segítségével Az előző két fejezetrészben megismerkedtünk a ShellTile API-val és a Background Agent-ekkel.

de a további webes technológiák is biztosítanak erre lehetőséget.) A RemoteImageUri tulajdonsággal állíthatjuk be a letölteni kívánt kép címét. Beállítjuk a kívánt paramétereket. schedule. Ezt követően a telefon megvárja a StartTime időpontot. Ezért célszerű. Az UpdateRecurrence. hogy lapkánk milyen gyakorisággal frissüljön. A tulajdonság értékét csak akkor veszi számításba a telefon.Lapkák frissítése ShellTileSchedule segítségével Az időzítés beállításához egy ShellTileSchedule típusú objektumot használunk. Némi idő elteltével megtörténik a frissítés. A fenti tulajdonságok használatával készíthetünk egyszeri alkalommal. schedule.Start(). az UpdateRecurrence. Az Interval tulajdonság adja meg.MaxUpdateCount = 0. schedule. EveryDay.Onetime értéket adtunk meg. Ha a tulajdonság értéke nagyobb. Ne feledjük azonban a korábban látott korlátozásokat! Három egymást követő sikertelen frissítési kísérlet után (azaz ha a képfájl nagyobb.png"). hogy erre sokat kell várnunk (akár egy órát is). mert az energiatakarékosság érdekében az esedékes frissítéseket összegyűjti és egyszerre hajtja végre a telefon. A kód megírása után indítsuk el alkalmazásunkat. ha a lapka nem csak egyszer frissítendő (lásd Recurrence tulajdonság). akkor a lapka a megadott számú alkalommal lesz frissítve.Interval érték esetén többször is. és onnantól kezdve a megadott beállítások szerint végzi a lapka frissítését. Ha 0 vagy annál kisebb.     Végül a Start() metódushívás kiadja a parancsot az időzítés tényleges elvégzésére.Interval. vagy letöltése 30 másodpercnél tovább tart) a telefon törli az időzítést.Recurrence = UpdateRecurrence.Onetime érték esetén pedig csak egyszer. Lehet. EveryWeek és EveryMonth. A StartTime tulajdonsággal határozhatjuk meg az időzítés kezdő időpontját.StartTime = DateTime. hogy időzítésünk hányszor fut le. schedule. Egy éles alkalmazásnál ennek kiszolgálására egy saját szervert használhatunk.Interval = UpdateInterval.RemoteImageUri = new Uri("http://www. (Ha a Recurrence tulajdonságnál UpdateRecurrence. mint 80 KB. Lehetséges értékei: EveryHour.gov/forecasts/graphical/images/conus/MaxT1_conus. schedule. hogy ez csak az internetről származhat (azaz helyből nem). amely egy adott URL-en egy dinamikusan frissülő képet tesz elérhetővé. eredménye a 10-17 ábrához hasonlít majd. akkor nincs korlát a frissítések számára. határozott alkalommal vagy akár határozatlan ideig futó időzítéseket is. mint 0. Nézzük meg az egyes paraméterek jelentését!  A Recurrence tulajdonság értékétől függ. majd lépjünk ki belőle és tűzzük ki a kezdőképernyőre. Fontos. schedule.Now. A MaxUpdateCount segítségével különböztethetjük meg a határozatlan ideig futó és a bizonyos időre szóló időzítéseket. Ez ASP. akkor ennek a beállításnak nincs értelme.NET Web Forms esetén például képeket visszaadó Handler-ek (ASHX fájlok) segítségével oldható meg. majd a Start() metódus hívásával érvénybe léptetjük az időzítést. ha alkalmazásunk minden egyes indításakor újra és újra elvégzi a beállítást. ShellTileSchedule schedule = new ShellTileSchedule().EveryHour.weather. 259 .

majd meg kell hívnunk a Stop() metódusát.weather. schedule.png").gov/forecasts/graphical/images/conus/MaxT1_conus.Recurrence = UpdateRecurrence. használatukhoz a felhasználónak ki kell tűznie alkalmazásunkat a kezdőképernyőre.10. A lapkák passzívak. hogy a létrehozott ShellTileSchedule értelmét veszti. ShellTileSchedule schedule = new ShellTileSchedule(). Amint a bevezetőben arról már szó volt. az összes többi elem pedig az épp aktuális másodlagos lapka. ha később rájuk is néz. fenti példakódunkat így kellene módosítanunk: ShellTileSchedule schedule = new ShellTileSchedule(tile).RemoteImageUri = new Uri("http://www. schedule. A felugró értesítések (angolul: toast notification) ezzel szemben aktívak! Bármilyen alkalmazást is futtat a felhasználó.Interval. ezzel felülírjuk a korábbi időzítést.Interval = UpdateInterval. schedule. azaz nem lesz aktív időzítés. hogy az időzítést a programunk egy korábbi futásakor állítottuk be. Lapkák és értesítések 10-17 ábra: A ShellTileSchedule által frissített lapka Időzítés beállítása egy másodlagos lapkára Hogy állíthatunk be ShellTileSchedule időzítést egy másodlagos lapkára? Az objektum paraméterezése nem változik. Előfordulhat. schedule. schedule.Now. a frissen létrehozott példányt pedig leállítjuk. A tile változóba egy ShellTile típusú objektumot vár a telefon. Mivel egyszerre csak egy ShellTileSchedule lehet aktív lapkánként.Stop(). így az eredeti ShellTileSchedule objektum természetesen már nem elérhető. A felugró értesítések A fejezetben idáig alaposan megismerkedtünk a lapkákkal és különböző frissítési lehetőségeikkel. (Emlékezzünk vissza. csak létrehozásakor át kell neki adnunk a frissíteni kívánt másodlagos lapkát.StartTime = DateTime. schedule.ActiveTiles gyűjteményben találjuk.MaxUpdateCount = 0. az elküldött értesítés mindenképpen megjelenik a telefon kijelzőjének 260 . ahol az első elem az elsődleges lapka. a lapkákon kívül a felugró értesítések is fontos módjai a felhasználóval való kapcsolattartásnak. hogy a másodlagos lapkákra mutató referenciákat a ShellTile. schedule. így szeretnénk azt letörölni. Egy időzítés törléséhez először referenciát kell rá szereznünk. és a lapkákon található információ csak akkor jut el hozzá.EveryHour.Start(). majd rögtön le is állítjuk.) Így ha egy másodlagos lapkára szeretnénk időzítést létrehozni. Ilyenkor egyszerűen újra létrehozzuk és elindítjuk az időzítést. Időzítés törlése Előfordulhat.

Azaz ha fut az alkalmazásunk. ám összesen kb. A ShellTileSchedule osztállyal pedig telefonunk időzítetten kérhet adatokat egy szervertől egy lapka frissítéséhez. Ne feledjük el befejezni a lapkáknál megismert műveleteket. így egy URI-t is beállíthatunk az értesítés mögötti tartalom eléréséhez (10-18 ábra). Viszont mindkét módszer csak kérni tud adatokat (azaz pull irányban működik). toast. majd a Scheduled Task Agent projektben található ScheduledAgent. vegyünk fel mellé egy Windows Phone Scheduled Task Agent projektet. Az alkalmazás ikonja természetesen változtatható (erről lásd a korábbi fejezeteket). Így alkalmazásaink – és a felhasználók is – a különféle eseményekről óhatatlanul késéssel értesülnek. különben az értesítés nem lesz látható)! Néhány másodperc elteltével megjelenik az értesítés. A megjelenő értesítések bal oldalán alkalmazásunk ikonjának kicsinyített változata található. Végezzük el az ott leírt lépéseket (azaz hozzunk létre egy Windows Phone Application projektet. akkor az értesítésre nyomva a felhasználó alkalmazásunk kezdőképernyőjét látja majd megjelenni. hogy csak alkalmazásunkon kívül jelennek meg. Az ikon melletti félkövér szöveg az értesítés címe.A Push Notification szolgáltatás felső részén. 40-50 karakter jelenik meg. Ez a két szöveg már állítható. toast. felesleges üzenetekkel bombázzuk a felhasználót. majd a telefon Windows gombjának segítségével lépjünk ki az alkalmazásból (ez fontos.cs fájl OnInvoke() metódusában helyezzük el a következő kódot: ShellToast toast = new ShellToast(). regisztráljuk be a Background Agent-et. hiszen csak bizonyos 261 .Show(). Így kommunikálhatunk szerverrel. és megjeleníthetünk értesítéseket. Ha viszont szeretnénk használni a Deep Linking lehetőséget. indítsuk el az alkalmazásunkat. A Background Agent szolgáltatással tetszőleges kódot futtathatunk a háttérben. majd ezt követi az értesítés tartalma. de az értesítésekhez nem állítható be külön ikon. nem tudunk értesítést küldeni. azaz írjuk meg a Background Agent-et beregisztráló kódot is! Miután ezzel elkészültünk. akkor a lapkáknál leírtakkal azonos módon itt is megtehetjük. Ha ennek értékét nem adjuk meg. frissíthetünk lapkákat. a többi kilóg a képernyőről és nem látható.Title = "Értesítés". 10-18 ábra: Egy felugró értesítés Az értesítések fontos megkötése. Azaz két módszert is láttunk már a szerveroldali kommunikációra. Természetesen óvatosan kell bánnunk az értesítésekkel – ha túl agresszívan. Végül a lapkákhoz hasonlóan az értesítéseknél is használhatjuk a Deep Linking technikát.Content = "Az üzenet tartalma". A toast objektumnak van még egy NavigationUri tulajdonsága is. lehetősége van letiltani alkalmazásunk értesítéseit. Mértékkel használva viszont hatékonyan hívhatjuk fel alkalmazásunkra a figyelmet. Ennek megfelelően csak Background Agent-ből (illetve a fejezet későbbi részében ismertetett Push Notification szolgáltatás segítségével) van lehetőségünk megjeleníteni egyet! Az értesítések kezeléséhez szükséges kód igen egyszerű. toast. rányomva pedig egyből a hozzá tartozó alkalmazás indul be. adjunk hozzá erre egy referenciát az első projektből stb. A Push Notification szolgáltatás A fejezet eddigi részében megismertük a Background Agent szolgáltatást és a ShellTileSchedule osztályt.). A lapkáknál már részletesen megismertük a Background Agent-ek készítését.

A Push Notification szolgáltatás működése A Push Notification szolgáltatás architektúrája 3 elemből áll: az általunk írt telefonalkalmazásból. Ezt egyszerű használni. Az összekapcsolás után kiszolgálónk bármikor küldhet a telefonnak üzeneteket. A Push Notification szolgáltatáson keresztül háromféle üzenetet küldhetünk a telefonnak: 262 . azaz nem alkalmazásunknak kell kérésekkel bombáznia a szervert. Alkalmazásunknak ezt az URL-t közölnie kell a szerverünkkel. és vállalja. Erre tetszőleges kommunikációs forma használható. Ezenkívül lehetőséget kell neki biztosítani az értesítések kikapcsolására is. hogy az ide érkező üzeneteket továbbítja a telefonnak. fejezetben bővebben esik szó. mind az alkalmazás-felhasználók számára. Ebben a fejezetrészben a Push Notification szolgáltatás tulajdonságaival. a szintén általunk írt szerveroldali alkalmazásból és a központi Microsoft Push Notification Service-ből (MPNS). hogy a korábban telepített alkalmazások már mindet lefoglalták. Alkalmazásonként maximum 1 csatorna létezhet. hogy akár 3 percenként küldhetünk egy üzenetet a nap minden órájában. az alkalmazást visszautasíthatják a Marketplace-ből. Érdemes webszolgáltatásokkal megoldani. használatával ismerkedünk meg. Használata a következőképpen néz ki: 1. mert az alkalmazásunk előző futásaikor létrehozott csatornát lehetőségünk van újrahasznosítani. Telefononként maximum 30 ilyen csatorna lehet. Ez a korlátozás szerencsére nem súlyos.NET nyelven programozzuk majd. Az MPNS egy publikus URL-t állít elő. így tetszőleges szerveroldali technológiával megírható.) A fentebb leírt regisztrációs lépések egy csatornát hoznak létre az MPNS és a telefon között. Ha ennél többre van szükségünk. A szolgáltatás leírása megtalálható az internetes MSDN könyvtárban. A szerveroldali komponens platformfüggetlen elemeket használ (XML formátumú üzeneteket kell küldenie). de telefononként (csatornánként) és naponta maximum 500 üzenetet küldhetünk ki. és hitelesített csatornát kell létrehoznunk. azaz fel kell rá készülnünk. Lapkák és értesítések időközönként kapnak frissítést.    A hitelesített csatornák létrehozására és a hozzájuk kapcsolódó „callback” üzenetküldésre ebben a fejezetben nem térünk ki. Ez push irányú forgalom lesz. hogy szeretne push üzeneteket fogadni. A Microsoft Push Notification Service ingyenes mind a fejlesztők. 4.10. hanem a szerver üzenhet valamilyen esemény megtörténtekor. Ráadásul. Ezt az URL-t pedig visszaküldi a Push kliensnek. aki visszaadja az alkalmazásuknak. és a mi alkalmazásunknak nem jut hely. akkor egy HTTPS tanúsítványt kell vásárolnunk. Ebben a fejezetrészben ASP. Alkalmazásunk jelzi a telefon felé. ha sokáig nem történik semmi. A Push Notification mechanizmus segítségével az alkalmazásunkat futtató telefont összekapcsolhatjuk egy általunk fenntartott szerveroldali alkalmazással. Ezt az MPNS kapja meg. akkor felesleges kérésekkel fogyasztják a telefon akkumulátorát. (Ha ezeknek a feltételeknek nem teszünk eleget. Ha szerverünk ezután bármikor üzenni szeretne a telefonnak. Ez a korlátozás megint csak nem súlyos: napi 500 üzenet azt jelenti. akkor erre az URL-re küldi el üzenetét. 3. A telefon operációs rendszerének részét alkotó Push kliens az interneten át közli ezt a szándékot az MPNS-szel. Használata azonban az alábbi feltételekhez kötött:  A Push Notification-öket a felhasználónak kimondottan kérnie kell az alkalmazás felületén található valamilyen vezérlőelemmel (opt-in rendszer). amikről a 9. Szerverünk és az MPNS között alapértelmezésként HTTP (titkosítatlan) csatornán folyik a kommunikáció. és továbbítja a készülék felé. 2.

amit éles környezetben egy webszerveren vagy a felhőben tartunk. amit később továbbfejlesztünk majd az értesítések és a raw üzenetek küldésére és fogadására. Felugró értesítés: a Push Notification-ök segítségével felugró értesítéseket is megjeleníthetünk a felhasználó számára. Az eredeti eseményfeliratkozások az alkalmazáson belül történtek.A Push Notification szolgáltatás  Lapkafrissítés: a fejezetben már megismertük a lapkák különféle tulajdonságait – elülső és hátsó felület. mint újra feliratkozni annak eseményeire. akkor nincs más dolgunk. akkor töltsük le és telepítsük az ingyenes Visual Web Developer Express verziót! Hozzunk létre egy új Windows Phone Application projektet PushNotificationClientSample néven! Továbbra is a Windows Phone OS 7. Ehhez a HttpNotificationChannel objektumot és annak metódusait használjuk majd. hogy a csatorna még nincs beregisztrálva. Az alkalmazásnak két szükséges komponense van: egy kliens. hogy a csatorna jogosult a lapkák frissítésére! A mintakódban láthatóak lesznek az esemény-feliratkozások.Phone. és még egy Deep Linking-re alkalmas URL-t is átadhatunk. hogy alkalmazásunk korábbi futtatásakor regisztrált-e már be csatornát. ami a telefonon fut majd. A fejezet hátralévő részében egy példán keresztül megismerjük. és egy szerver. Az egyszerűség kedvéért ezt már közvetlenül az alkalmazás indulásakor lefuttatjuk.cs kódfájl MainPage() konstruktorába: 263 . A beregisztrált csatorna egyrészt különféle eseményeket indíthat (például: hiba történt. éles alkalmazásban ne feledjük ezt valamilyen vezérlőelemhez (például egy gombhoz) kötni! Elsőként írjuk a következő sort a fájl legtetejére: using Microsoft. A webszerver elkészítéséhez erre alkalmas Visual Studio változatra van szükségünk. Ha viszont korábban már megnyitottuk a csatornát. Mivel alkalmazásonként maximum 1 csatornánk lehet az MPNS felé. és tetszésünk szerint feldolgozhatjuk.   A fenti üzenettípusok mindegyikének rögzített formátuma van. és a csatorna lapkafrissítésre való regisztrációja is (BindToShellTile() hívás). ezért feltétlenül meg kell vizsgálnunk. Ha azt találjuk. akkor viszont az üzenet elvész. Ha alkalmazásunk nem fut.xaml. Egy Push üzenetből a lapka valamennyi tulajdonságát frissíthetjük. stb.Notification. így természetesen az alkalmazás leállásakor azok elvesznek. Ha alkalmazásunk fut.1 vagy újabb verziót válasszuk! Első lépésként megírjuk azt a kódot. háttérkép. amelyekre fel kell iratkoznunk. az üzenetet a telefon operációs rendszerében lévő Push kliens fogadja. „Raw” (nyers) üzenet: Minden más esetre a Raw Notification használható. ami beregisztrálja alkalmazásunkat az MPNS felé. akkor megjelenik az értesítés. cím. hogy miként tudjuk regisztrálni alkalmazásunkat az MPNS-ben. és ő végzi el a módosítást. Ha a telepített Visual Studio nem teszi lehetővé a webfejlesztést. tartalmát. Nevéhez hűen ebben tetszőleges adatokat (szöveget vagy akár egy bájttömböt) is elküldhetünk a telefonnak. ha pedig fut. Lapkák frissítése Push Notification-ök segítségével Ismét egy példaalkalmazást készítünk. ebben a példában azonban a helyi fejlesztői gépünkről szolgáljuk ki. akkor kódból elkaphatjuk az üzenetet. akkor ezt megtesszük. Ha nem fut. A fentiek elvégzéséhez helyezzük az alábbi kódot a MainPage. vagy megváltozott az MPNS által biztosított URL). majd hogyan küldhetjük ki a különféle üzenettípusokat. A korábban megismert tulajdonságok itt is használhatók: beállíthatjuk az értesítés címét. akkor megkapja. másrészt közölnünk kell a telefonnal. A frissítéshez nem kell futnia az alkalmazásunknak.

ChannelUri.WriteLine(pushChannel. például egy webszolgáltatáson keresztül. } Ezzel a kliensoldali kódot meg is írtuk – az alkalmazás vagy új csatornát hoz létre.Diagnostics. pushChannel = HttpNotificationChannel. } //Már létezik .Open(). pushChannel. } A fenti kód két eseménykezelőre is hivatkozik.WriteLine(e. }). pushChannel. } void pushChannel_ErrorOccurred(object sender. NotificationChannelUriEventArgs e) { Dispatcher.Debug.ChannelUri. Írjuk most meg az alkalmazás szerveroldali komponensét! Ehhez nyissunk egy új Visual Studio projektet! 264 . string channelName = "SampleChannel".létrehozzuk. A második (pushChannel_ErrorOccurred) pedig hibakezelésre való. és feliratkozunk az eseményeire. fejezetben részletesen olvashatunk.Diagnostics.ToString()). itt mindössze egy erre vonatkozó üzenetet íratunk ki a Visual Studióval.Message). //Megnézzük. amiről a 9. Az első (pushChannel_ChannelUriUpdated) akkor kerül meghívásra. else { pushChannel. Éles alkalmazásban ezt célszerű közölnünk a webszerverünkkel. vagy újrahasznosítja a régit.BeginInvoke(() => { MessageBox. System. és a vágólapon keresztül másoljuk át a szerverre.BeginInvoke(() => { System. ha az MPNS megváltoztatja a csatorna URL-jét. pushChannel. pushChannel. if (pushChannel == null) { pushChannel = new HttpNotificationChannel(channelName). ebben a kódban a hibákról üzenetet küldünk a felhasználónak. Látszólag hiányzik viszont egy fontos elem: nem küldjük el az URL-t a szerveroldalra! Egy éles alkalmazásban valóban így történne. void pushChannel_ChannelUriUpdated(object sender. }).Show("Hiba történt: " + e.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(pushChannel_ErrorOccurred).BindToShellTile(). //Még nem létezik .Find(channelName).ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(pushChannel_ErrorOccurred).ismét feliratkozunk az eseményeire.10. NotificationChannelErrorEventArgs e) { Dispatcher. Lapkák és értesítések HttpNotificationChannel pushChannel. és lekezeli annak különféle eseményeit. pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(pushChannel_ChannelUriUpdated).ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(pushChannel_ChannelUriUpdated).Debug. hogy létezik-e már a csatorna.ToString()). Most az egyszerűség kedvéért mindössze kiíratjuk az URL-t.

aspx oldal a vezérlőelemekkel Következik a szerveroldali kód megírása. string tileMessage = "<?xml version=\"1. A második szövegdobozba írjuk üzenetünket. amit megjelenítünk majd a lapkán! A gombbal kezdeményezzük a küldést. using System.NET Empty Web Application. Ha valamelyik XML tulajdonságot üresen hagyjuk. a többi tulajdonságot változatlanul hagyja. 10-19 ábra: A Default. Default. a címkébe pedig a visszatérési értéket helyezzük majd el.Text + "</wp:Title>" + "<wp:BackBackgroundImage></wp:BackBackgroundImage>" + 265 . mert a telefonos fejlesztésre használt Visual C# Express nem támogatja a webfejlesztést. Amint a példakódban levő XML-ből látjuk. Hozzunk létre az űrlapon két szövegmezőt UrlTextBox és MessageTextBox néven. Ezután írjuk meg a gomb SendTileButton_Click eseménykezelőjének kódját! Mindhárom értesítési típusnak egy kötött struktúrájú XML üzenetet kell küldenie egy HTTP kérésen keresztül. akkor új példányt kell indítanunk. akkor az nem változik a lapkán. valamint egy címkét ResponseLabel néven! Az első szövegdobozba kerül majd az MPNS által visszaadott URL.IO. a lapkák korábban megismert valamennyi tulajdonságát frissíthetjük.A Push Notification szolgáltatás Ezt létrehozhatjuk a már megnyitott Visual Studio példányban is. egy gombot SendTileButton néven és „Lapkafrissítés küldése” felirattal. neve PushNotificationServerSample ! A projekt létrejötte után adjunk ahhoz egy új Web Form típusú elemet. A projekt típusa legyen ASP. A fentiek elvégzése után az űrlapnak a 10-19 ábrához kell majd hasonlítania.Net. A telefonnál megszokott módon kattintsunk duplán a Lapkafrissítés küldése gombra! A megnyíló kódfájl tetejére helyezzük el a következő néhány sort: using System. de ha a Visual Studio Express verzióit használjuk. kódunk ezért először felépíti ezt az XML struktúrát. //Előállítjuk az üzenetet.0\" encoding=\"utf-8\"?>" + "<wp:Notification xmlns:wp=\"WPNotification\">" + "<wp:Tile>" + "<wp:BackgroundImage></wp:BackgroundImage>" + "<wp:Count></wp:Count>" + "<wp:Title>" + MessageTextBox.aspx néven! A Visual Studio automatikusan megnyitja az űrlap HTML nézetét. ehhez a Visual Web Developer Express-re van szükségünk. using System. A ShellTileSchedule osztállyal ellentétben itt háttérképeket helyi erőforrásból is beállíthatunk – ehhez használjunk relatív URL-t (amire már láttunk példát a fejezet korábbi részeiben)! A példakód az egyszerűség kedvéért kizárólag a lapka címét frissíti a megadott üzenetre. ahová üzenetünket küldjük majd.Text.

miután elküldte az üzenetet..Length).Headers. akkor azonnal. notificationMessage.Write(notificationMessage. és mennyire sürgős. Ezek után már nincs más hátra.Default. Ezzel elkészültünk. Ezeket a fejlesztő felület Output ablakában nézhetjük meg. sendNotificationRequest. akkor pedig legkésőbb 900 másodpercen belül továbbküldi a telefon felé az MPNS.GetRequestStream()) { requestStream.com/enus/library/ff402558(VS. Ha ehhez írunk programot.Headers.10.Headers["X-NotificationStatus"]. ResponseLabel.0 operációs rendszerben. Az üzenetet bájttömb formájában kell majd átküldenünk a hálózaton. Teszteljük a programot! Indítsuk el mindkét projektet! A Windows Phone alkalmazás látszólag semmit nem csinál. //Létrehozzuk a HTTP kérést.Text). akkor ezeket hagyjuk ki! Ezekről lásd: http://msdn. A fenti kód Windows Phone 7.Add("X-WindowsPhone-Target".catch blokkal. Bizonyos tulajdonságok még nem léteztek a Windows Phone 7. HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest. "token"). sendNotificationRequest. és az eredményül kapott URL-t kiírja a Visual Studio Debug üzenetei közé. Erre a HttpWebRequest osztályt használjuk.Headers["X-SubscriptionStatus"].ContentLength = notificationMessage. sendNotificationRequest. byte[] notificationMessage = Encoding. akkor a View menü Output menüpontjával tegyük láthatóvá (lásd 10-20 ábra)! 266 . a HTTP fejrészében be kell állítanunk. using (Stream requestStream = sendNotificationRequest.Create(UrlTextBox. Az MPNS visszajelez. sendNotificationRequest. string notificationChannelStatus = response. hogy az üzenet milyen célt szolgál.Text = notificationStatus + " | " + deviceConnectionStatus + " | " + notificationChannelStatus.Headers["X-DeviceConnectionStatus"]. Az X-WindowsPhone-Target tulajdonság értéke adja meg. 0. string notificationStatus = response. Lapkák és értesítések "<wp:BackTitle></wp:BackTitle>" + "<wp:BackContent></wp:BackContent>" + "</wp:Tile> " + "</wp:Notification>". Ezt rögtön ki is íratjuk az erre a célra létrehozott ResponseLabel címkébe. hogy lapkafrissítésről. a különféle státusz-üzenetek a válasz HTTP fejlécében érkeznek. A HttpWebRequest paraméterezésére is ügyelnünk kell! Egyrészt. így a korábban létrehozott XML formátumú szöveget bájttömbbé alakítjuk. értesítésről vagy raw üzenetről van szó. //Elküldjük az üzenetet és kiolvassuk a választ. de valójában elvégzi az MPNS regisztrációt. A X-NotificationClass pedig az üzenet sürgősségét határozza meg – ha 1.aspx Az előállított XML fájlt egy HTTP kérésen keresztül tudjuk elküldeni az MPNS-nek.GetBytes(tileMessage).GetResponse(). } HttpWebResponse response = (HttpWebResponse)sendNotificationRequest. Mivel hálózati kódról van szó. "1"). ha 11.Method = "POST".microsoft. sendNotificationRequest.Add("X-NotificationClass".Length. akkor legkésőbb 450 másodpercen belül. mint az üzenet tényleges elküldése. ha 21.92). a kérést POST üzenet formájában kell elküldenünk. Másrészt.ContentType = "text/xml".5 (Mango) vagy újabb operációs rendszer esetén működőképes. ezért érdemes a fentieket körbevenni egy try. Ha ez nem látszik. string deviceConnectionStatus = response.

A felugró üzenetet és a lapkafrissítést küldő kód csak az elküldött XML fájl formátumában és néhány paraméter-értékben tér el.A Push Notification szolgáltatás 10-20 ábra: Az Output ablak és az MPNS-től visszakapott URL A megjelenő URL-t másoljuk ki. Ennek hatására a frissítés gyakorlatilag azonnal megjelenik. Mindössze azt kell közölnünk a telefonnal. elküldjük az URL-t a szervernek. Írjuk be a pushChannel. hogy a létrehozott csatornán keresztül értesítések is érkezhetnek. ha az alkalmazás lapkája nem volt kitűzve. és tűzzük ki a kezdőképernyőre. hogyan tudunk felugró értesítéseket megjeleníteni Push Notification-ök segítségével! A művelet logikailag szinte teljesen megegyezik a lapkafrissítésekkel – a telefonon beregisztráljuk a csatornát. a Push Notification-öknél ez nincs így – ha az alkalmazás épp nincs kitűzve. Hozzunk létre egy új gombot a webes projektben SendToastButton néven és „Értesítés küldése” felirattal! Dupla kattintással lépjünk be Click eseménykezelőjébe. a szerverről pedig XML formátumú kéréseket irányítunk a csatornába. A szerveroldalon szintén nagyon kevés változtatásra van szükségünk. Ennek megfelelően a kliensoldali kódban minimális változtatást kell csak végrehajtanunk. A lapkákhoz hasonlóan itt is 267 . hogy ez az XML is tartalmazza a felugró értesítések valamennyi lehetséges tulajdonságát.BindToShellToast(). Végül térjünk vissza a webalkalmazáshoz. és kattintsunk a Lapkafrissítés küldése gombra! A webalkalmazás összeállítja az XML-t. elküldi az MPNS-nek. és illesszük be a weboldalunk felső szövegdobozába! Az alsóba írjunk valamilyen rövid üzenetet! A telefonon lépjünk ki az alkalmazásból. és ezeket is kezelje le. hogy míg a ShellTile API-n keresztül elvégzett változtatásokat akkor is elmentette a telefon. ha ékezetes betű van az üzenetben. Értesítések megjelenítése Push Notification-ök segítségével Nézzük. ami rögtön továbbítja azt a telefon felé.BindToShellTile(). Szintén fontos. az üzenet elvész. amint az a 10-21 ábrán látható. hogy a Push Notification-ök sajnos nem minden karaktert támogatnak. 10-21 ábra: A Push Notification-nel frissített lapka Jó tudni. Hibát kaphatunk. sor alá a következő egyetlen sort: pushChannel. és egy az egyben másoljuk át a SendTileButton_Click eseménykezelő tartalmát ide! Módosítsuk az XML üzenetet a felugró üzenetek sémájának megfelelően! Láthatjuk.

Helyezzük a következő kódot mindkét pushChannel.Add("X-NotificationClass".0-s operációs rendszert futtató telefonok még nem ismerik mindet az itt szereplő tulajdonságok közül! //Előállítjuk az üzenetet. amikor alkalmazásunk fut. A HttpNotificationReceived eseménykezelő törzsében mindössze kiolvassuk és megjelenítjük a kapott üzenetet – egy éles alkalmazás természetesen ennél sokkal bonyolultabb logikát is végrehajthat: 268 .Add("X-WindowsPhone-Target". már tesztelhetjük is az alkalmazást.Headers. akkor csak újrahasznosítja a csatornát. "2"). és kattintsunk az Értesítés küldése gombra! Az eredmény a 10-22 ábrához hasonlít majd. 10-22 ábra: A megjelenő felugró üzenet Ha az alkalmazás futása közben is szeretnénk kezelni a megérkező értesítéseket. akkor ehhez a ShellToastNotificationReceived eseményre kell feliratkoznunk.ErrorOccurred += kezdetű sor után: pushChannel. A raw üzenetek csak akkor fogadhatók. 12 a 450 másodpercen belülit. azaz „toast” típusú. majd másoljuk át az URL-jét a webalkalmazásba. és nem fut le a módosított kódunk.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(pushChannel_HttpNotificationReceived). így ezúttal egy eseményre kell majd feliratkoznunk. mert korábbi tesztjeink során az már megnyitotta a Push Notification csatornát.0\" encoding=\"utf-8\"?>" + "<wp:Notification xmlns:wp=\"WPNotification\">" + "<wp:Toast>" + "<wp:Text1>" + MessageTextBox. A teszteléshez előbb el kell távolítani a kliens alkalmazást a telefonról. majd indítsuk el a két projektet! A telefonalkalmazásból lépjünk ki (különben az értesítés nem jelenik meg). hogy ez egy értesítés. ami lapkafrissítéshez is beregisztrálná (a BindToShellToast() hívás). Lapkák és értesítések ügyeljünk. Távolítsuk el tehát a programot a telefonról. sendNotificationRequest. Így ha most elindítjuk. string tileMessage = "<?xml version=\"1. mert a 7. Erre azért van szükség. Miután ezzel elkészültünk. és 22 a 900 másodpercen belülit).Text + "</wp:Text1>" + "<wp:Text2></wp:Text2>" + "<wp:Param>/MainPage.Headers.10.xaml</wp:Param>" + "</wp:Toast> " + "</wp:Notification>". Raw üzenetek fogadása a Push Notification szolgáltatáson keresztül Végül ismerkedjünk meg a Raw üzenetek küldésével! A felugró értesítésekhez hasonlóan nagyon kevés változtatást kell végeznünk már meglévő kódunkon. "toast"). és át kell írnunk a kézbesítés gyorsaságát szabályozó konstanst is (itt 2 jelenti az azonnali kézbesítést. Ezután módosítsuk a kérés HTTP fejrészét! Meg kell adnunk. sendNotificationRequest.

sendNotificationRequest. string tileMessage = MessageTextBox.Add("X-NotificationClass". és küldjünk egy raw üzenetet! A várható eredmény a 10-23 ábrán látható. módosítsuk a HTTP fejléceket! Az X-WindowsPhone-Target fejlécre ezúttal nincs szükségünk – ezt a lenti kódrészletben kommentálással jeleztük. 10-23 ábra: A kézbesített raw üzenet Push Notification-önök és a Windows Azure Ha szerverre van szükségünk. lépjünk be Click eseménykezelőjébe. hogy az MPNS maximum 1 kilobájtnyi fejléccel és 4 kilobájtnyi törzzsel rendelkező üzeneteket továbbít! //Előállítjuk az üzenetet. hogy a felhőt használjuk erre a célra. és ami a leglényegesebb: a Push Notification-ök használatára is.Notification. Az X-NotificationClass értéke raw üzenet esetén 3. szöveg vagy akár egy tetszőleges bájttömb is. Másodszor. }). ami kész alkalmazás-sablonokat tartalmaz.Headers. "toast").Body)) { string message = reader. 450 másodpercen belüli vagy 900 másodpercen belüli kézbesítést jelent.ReadToEnd(). //sendNotificationRequest. Elsőként írjuk be az elküldendő üzenetet! Ez raw üzenet esetén bármi lehet – XML. Ügyeljünk azonban arra.BeginInvoke(() => { MessageBox.StreamReader(e. vagy az Azure-on keresztüli felhasználó-hitelesítésre. Készen állunk az alkalmazás tesztelésére.Headers. A felugró üzeneteknél látott módon távolítsuk el az alkalmazást a telefonról. A Microsoft külön toolkit-et készített Azure Toolkit for Windows Phone 7 néven.A Push Notification szolgáltatás void pushChannel_HttpNotificationReceived(object sender. Dispatcher.Show(message). Jó hír. kézenfekvő. } } Most módosítsuk a szerveroldalt is! Hozzunk létre egy új gombot SendRawButton néven „Raw üzenet küldése” felirattal. 13 vagy 23 lehet – a megszokott módon ez azonnali.Text. Architekturális szempontból ugyanazt valósítják 269 .StreamReader reader = new System.Add("X-WindowsPhone-Target".IO. másoljuk át az URL-t a webalkalmazásba. Ezek képesek az Azure tárhelyek használatára. HttpNotificationEventArgs e) { using (System.IO. hogy a Windows Azure kifejezetten támogatja a Windows Phone-nal való együttműködést. "3"). majd indítsuk be a két projektet. majd másoljuk át ide a SendToastButton_Click eseménykezelő törzsét! Ezt ismét csak két helyen kell módosítanunk.

10. vagyis a szerver kezdeményezi a frissítést. fejezet tárgyalja. Ezen eszközökkel alkalmazásunk nemcsak addig „él”. időzített módon. 270 . interaktívabb élményt biztosíthatunk. de más-más esetben érdemes őket használni. Push Notification Láttuk továbbá a felugró értesítéseket is. érdemes kipróbálni a toolkit-et. Szolgáltatás ShellTile API Background Agent ShellTileSchedule Jellemzők Csak a telefon kell hozzá. hogy az értesítések a lapkákhoz hasonlóan Background Agent és Push Notification segítségével is küldhetők. a telefon kezdeményezésével működik. Az alábbi táblázatban összehasonlítjuk a lapkák frissítésére használható lehetőségeket. Szervert is igényel. Megismertük. mint a fentebb leírtak. mert segítségükkel sokkal professzionálisabb megjelenést. Ezek célja ugyan azonos. eseményvezérelt. hanem leállítása után is képes friss információkat biztosítani. Alkalmazásunk futása alatt használható. Szervert is igényel. Ha lehetőségünk van az Azure használatára. melyekkel a felhasználó figyelmét aktívan irányíthatjuk alkalmazásunkra. Csak a telefon kell hozzá. Alkalmazásunknak nem kell futnia. érett kód formájában. Lapkák és értesítések meg. amelynek beállítását. amíg a felhasználó aktívan futtatja. Érdemes őket használni. Alkalmazásunknak nem kell futnia. Összefoglalás A fejezetben megismertük a lapkák tulajdonságait. egyes funkcióinak használatát a 9. Alkalmazásunknak nem kell futnia. de kész. a frissítés időzítetten történik. és láttuk a frissítésükre használható négy módszert.

Amikor a platform utódjának fejlesztésébe kezdtek. és tartalmaz mindent. és mikor tudjuk kihasználni az új lehetőségeket. A fejezet első részében megismerkedünk az XNA Framework és a grafikus programozás legfőbb mozzanataival.11. Ez azt jelenti. Ezek után megnézzük. Miután a teljes . ahogy azt megszoktuk. hogy mindenképpen érdemes adni egy rövid ízelítőt a telefonos játékok fejlesztéséből. hogy a céleszközök között az alkalmazások átvihetők. amire egy játékprogram esetében szükség lehet (11-1. Az XNA a Microsoft játékfejlesztési eszközkészlete és futtatókörnyezete különböző eszközökre. Xbox és most már a Windows Phone is. amely magasabb absztrakciójú megoldásokat kínál.NET fejlesztő számára sokkal kevésbé megterhelő.NET alapú programozási felülettel rendelkezik. és az arra való áttérés egy . mint azelőtt volt. amely a teljes platformnak csak egy darabja). Azonban hiába a gazdag médiatámogatás. azonban úgy gondoltuk. Ők nagy valószínűséggel nem fognak egy komplex grafikus rendszert kitanulni. skálázási eltérésekre és néhány. az eszközök közötti különbségekből származó eltérésre szükséges csak odafigyelni a játék fejlesztése során. így a platform felépítésekor két fő szempontot kellett betartani: a megszokott alkalmazásfejlesztési modell alkalmazható legyen általános alkalmazásfejlesztéshez. PC-re írt játékok esetében két elterjedt grafikai API létezik: OpenGL és DirectX (pontosabban a Direct3D. egy olyan sokkal átgondoltabb és korszerűbb rendszert szerettek volna alkotni. A Silverlight mint korszerű alkalmazásépítési platform jó választásnak tűnt. Windows Phone – a motorháztető alatt A Windows Mobile fejlesztése során a Microsoft rendkívül sok tapasztalatot halmozott fel. hanem a játékok fejlesztése iránt érdeklődő hobbi. de az okos telefonok piacán egyre nagyobb teret hódító játékok és grafikus alkalmazások se maradjanak támogatás nélkül. hogy ezen a téren a Mango frissítés milyen újdonságokat hozott magával. ábra):       Átgondolt irány-architektúra a játék számára Grafikai rendszer Bemenetek támogatása magas szinten Audiorendszer Tartalmakat kezelő alrendszer Különböző eszközök 271 .NET Framework számos okból nem vihető át egy mobil eszközre.és kezdő fejlesztőket is. így a választás a Direct3D lehetett volna. akik eddig még soha nem találkoztak fejlesztői szempontból számítógépes játékokkal vagy grafikus programozással. a teljesítménye nem megfelelő sebességorientált magas számítási kapacitást igénylő megoldásokhoz – ide bizony egy grafikus technológiára volt szükség. illetve bemutatni. Azonban a Windows Phone az ipar számára egy újonnan belépő tagot jelentett. aránylag rövid kiadási ciklusokkal. . több éve kedvelt és elterjedt technológia. amely a legújabb technológiákra épít. ezzel elméleti és gyakorlati alapot adva azon Olvasóinknak is. így sokkal kényelmesebb megoldásra volt szükség. így nemcsak a tapasztalt játékfejlesztőket kellett megcélozni a technológiai támogatásokkal. a fejlesztői modell előnyei és hátrányai jól körvonalazódtak. Természetesen. Játékok a Mango világában A most soron következő fejezet témáját tekintve merőben eltér a korábbi fejezetektől. mint Windows. Miután a Microsoft a nyílt OpenGL-t nem használja saját fejlesztéseihez. és a Windows a grafikus alrendszer támogatásán kívül mást nem nyújt. pontosan mit is jelent a Silverlight és az XNA hibrid megjelenítési rendszere. könnyebben tanulható és könnyebben kezelhető. A választás az XNA Frameworkre esett.

azonban gyorsan feldolgozható – és lehet vektoros alapon számítva – amely skálázás esetén is mindig pontos lesz. amit egy játékmotor. Képek reprezentációja során jól ismerjük a két létező analógiát. hogy valamilyen gyorsító megoldásra itt is szükség lesz. Ha nem szeretnénk minden apró részletet saját magunk kifejleszteni a legelejétől fogva. az annál több számítást fog igényelni.11. Ha ezt térbe szeretnénk levetíteni. akkor az interneten számos nyílt forráskódú játékmotor fellelhető. Ha a legújabb funkciókat szeretnénk Windows környezetben kihasználni. Egy játékmotor sokkal specifikusabb. azonban a matematikai számításokat újra és újra végre kell hajtani. Megjelenítéskor a csúcspontokat összekötjük. azonban ezt azon az áron teszi. A keretrendszer pillanatnyilag a 4. ábra: A Windows Phone Mango fejlesztői platform Nem keverendő össze az XNA Framework egy játékmotorral (game engine)! Sok szempontból úgy tűnhet. miszerint egy kép lehet pixeleivel számítva – amely az esetleges skálázások során pontatlanságot és darabosságot okoz. akkor ahhoz DirectX-re és natív kódra lesz szükségünk. minden. 3 dimenziós térben gondolkozunk. másodsorban pedig a folyamatosan fejlődő technológiáknak. Amikor a grafikus processzor feldolgozza és megjeleníti ezeket a poligonvázakat.0-s változatánál tart. mesterséges intelligencia. Természetesen minél több poligonnal szeretnénk dolgozni. és a területüket kitöltjük. hogy soha nem a legfrissebb natív grafikus platformhoz van igazítva. szkript rendszer. amely az esetek egy jelentős részében – a jól optimalizálhatóság miatt – C++-ban íródik. akkor már előre megjósolható. aminek támogatásával rövidebb idő alatt. térben helyezkedik el. egyszerűbben juthatunk el a kívánt célunkig. De milyen komponensekből épül fel egy játék grafikája? Nos. Az XNA egy jól átgondolt alapot ad. Játékok a Mango világában 11-1. amit meg szeretnénk jeleníteni. Windows Phone telefonokon azonban nincs lehetőségünk natív kódot futtatni. ami a mi esetünkben a DirectX. stb. akkor először a térbeli információk kerülnek be a megjelenítéshez szükséges elemeket tartalmazó csővezetékbe.). de ez messze nem igaz. azonban szerves részét képezi a Windows Phone fejlesztői készletnek is. Fontos megjegyzés az XNA-val kapcsolatban: sokat egyszerűsít a játékfejlesztési folyamaton. így a poligonok számának függvényében fog változni az adott modell részletessége is. illetve az számos olyan komponenst kínál (fizikai számításokért felelős komponens. nem fogjuk minden egyes pontját az adott térbeli testnek kiszámítani. az esetek jelentős részében kötötten egy játékkategórián belül használható jól. amelyeket az XNA nem. Grafikus programozási és XNA alapok A kép kialakítása A mai játékok hónapról hónapra egyre szebb grafikai megvalósításokat sorakoztatnak fel. amelyek kimondottan XNA-hoz készültek. amely elsősorban a fejlődő hardveres erőforrásoknak köszönhető. Helyette poligonokra (sokszögekre) bontjuk fel az alakzatot. A GPU több 272 . a poligonoknak pedig a csúcspontjait tároljuk le. amely külön is letölthető a Microsoft letöltő központjából. hogy az XNA mindent tartalmaz.

Elhangzott egy fontos fogalom: a fény. de részletessége még nagyon messze áll ettől. Mi kell a fények megjelenítéséhez? Valamilyen fényforrás és az adott térbeli alakzat információja arra vonatkozóan. így azt a hatást keltve. hanem több különböző réteg több feladatot tud ellátni. alakja kezd hasonlítani arra. ezért nem a poligonok számának növelésével és színezésével finomítjuk a modellt tovább. hanem anyagmintákat (textúrákat fogunk) felhasználni. akkor azt hogyan verjük vissza és milyen intenzitással. ábra: Poligonváz textúra nélkül és textúrával Most már olyan érzetet kelt bennünk. A visszaverődéshez egy felületi tulajdonságra van szükségünk. mennyire árnyalt. azaz levetíti a képernyő megfelelő pixeleire (11-2. és így tovább. ábra). melyeket térben a megfelelő poligonra vetítünk le. hogy ha egy fénysugár becsapódik. de még mindig nem az igazi. és számításigényes lehet. hogy az alapmintázatot megadja. a keletkezett háromszögeket pedig raszterizálja. 11-2. ábra: Egyszerű poligonváz A 11-2. 11-3. ábrán jól látható. azonban (mint minden más is egy játékban) ez matematikai alapon van megfogalmazva. ábra). mintha tényleg valamilyen valós objektumot jelenítettünk volna meg egyszerűen a számítógép segítségével. mennyi fényt tud elnyelni az adott test helyenként. egy másik rétegben tárolhatunk olyan információkat is. A textúrák nemcsak egyetlen rétegben helyezkedhetnek el a modellen. Az anyagminták egyszerű képfájlok. amik arra vonatkoznak. hogy a térben megalkotott delfin alakzat nem igazán valósághű. amit létre szeretnénk hozni. mintha az adott test felületén helyezkedne el (11-3. A számítógépes grafika minden területén a való életből merít ötleteket.Grafikus programozási és XNA alapok lépésen keresztül tovább bontja azokat háromszögekre. Azon túl. Rendkívül sokat tud a valóságérzet kialakításában segíteni egy jól elkészített fény-árnyék rendszer. ami 273 .

ha minden egyes pixelre külön határozzuk meg a fények hatását. amelyet a grafikus technológiák nem segítenek alapértelmezetten. ábra. mint az adott poligon normálvektora. ábra: Poligononkénti megvilágítás A 11-4. ábra: Pixel alapú fény egy kis felbontású modellen 274 . ábrán jól megfigyelhető. 11-5. ha magas poligonszámú vázzal van dolgunk.11. Ennek lehetséges orvosolása. hogy a poligononként meghatározott visszaverődés csak akkor ad szép eredményt. amit megfogalmazunk. Itt már csak a számítási komplexitás szabhat határt. 11-4. ehhez azonban pixel alapú manipulációra van szükségünk. Egy pixel alapú megvilágítást mutat be a 11-5. A normálvektor és a fényvektor skaláris szorzata meghatározza a visszaverődési paramétert. Játékok a Mango világában nem más. A beépített – és egyben korlátos – megoldások (Fixed Function Pipeline) megkerülésére aránylag hosszú ideje van lehetőség grafikus processzorra írt árnyaló (shader) kódok segítségével. azt közvetlenül a GPU (grafikus processzor) fogja végrehajtani.

amelyek játékokban valós időben tudnak megvalósítani sugárkövetést. ábra: Buckaleképezés és a normálvektorokat tartalmazó textúra Sajnos a könyv terjedelme (és legfőképpen témakörei) miatt a virtuális objektumok számítógépes grafikai módszereit nincs lehetőségem tovább részletezni. Ezeket az effektusokat mondatokkal megfogalmazva nehézkes szemléltetni. De ilyen például a sci-fi filmekre jellemző. helyette csak a képernyő felbontása szerinti pixelekkel kell számolnunk. azonban a poligonváz – számítási teljesítmény miatt visszafogott – felbontása még mindig problémát okoz. ezzel a matematikailag tökéletes világítást megvalósítva. drámai hatások elérése is. se nem közvetlen szemből). ábrán. Ahogy haladunk előre a színtér elemeinek megismerésével. Amit a fejezetben eddig tárgyaltunk. az a sebességorientált (inkrementális) képszintézis. Ha megfelelő szögben nézzük az adott objektumot (se nem túl kis szögben. egyre finomabbá kezd válni a virtuális térben létrehozott környezetünk. zavaros (zajjal torzított) megjelenítés. amely egy újabb réteg textúrát ad a modellünkhöz. azonban szorosan kapcsolódva az eredeti mintához. mint a képernyőtér (a képernyő pixelei. mint a kásás. azonban a komplex számítási rendszer miatt a komolyabb megoldások még jó ideig csak a filmekben maradnak. és 118. helyettem inkább beszéljenek a képek (11-7. azonban a tökéletes tükröződések. térbeli felület hatását kelti. hanem a filmekben használt speciális effektusok nagy része is ezekre épít. akkor a felület úgy néz ki. Ennek a lényege az. amin „keresztül” a teret látjuk). vagy a filmszakadást imitáló sávosítás is. 11-6. Ilyenek például a dinamikus fénykontrasztokat leíró HDR (High Dynamic Range) effektek. hogy a képernyő minden egyes pixeléből sugarakat indítunk – akárcsak a való életben a fotonok . mintha jóval több poligon segítségével modelleztük volna azt. Ez a textúra minden pixelében egy normálvektort ír le. bár minden egyes említett témakör még hosszasan taglalható lenne. Ide tartoznak a különböző elmosások. hogy milyen anyagi tényezőket gyűjtöttek össze. törések és megvilágítások reprezentiációjához létezik egy sugárkövetés (ray tracing) nevű megközelítés is. Természetesen vannak kezdeményezések megfelelő sebességű algoritmusok előállítására. A buckaleképezés elemei megfigyelhetők a 11-6. ami nem más. melyekkel valósághű vakító és tompított fényviszonyokat tudunk létrehozni. ahol a textúrát egy nagyon alacsony poligontartalmú gömbre feszítettük ki. Erre egy elterjedt megoldást jelent az úgynevezett buckaleképezés (Bump Mapping). melyet szintén pixelenként kiértékelve a fénysugár függvényében egy részletes. hogy a térelem minden egyes pixelét számításba vegyük. és megfigyeljük. Helyette térjünk át a színtér egy másik aspektusára. melyeknek az útját követjük. amelyekkel a sebesség illetve a térbeli távolság hatását tudjuk hangsúlyozni.Grafikus programozási és XNA alapok Érdekesség: a fény-árnyék rendszerek nemcsak a számítógépes játékokban jelentősek.a virtuális térbe. Nagyon sok valóságérzetet keltő effektus ezen keresztül valósítható meg. ábra)! 275 . amely megspórolja számunkra azt.

füst és az ősszel hulló falevelek? Ezeknek a modellezése pixel alapon rendkívül körülményes lenne. akkor a helyére pótoljon egy új elemet. Képzeljünk el egy egyszerű kis textúrát. még egy kitérőt teszünk a játékciklus megismerésével. hogy egy egyszerű kétdimenziós játék megvalósításához milyen elemekre van szükségünk. sok elemből álló és egységes szabály szerint működő jelenség megvalósítható vele. ábra: Többszörös effektek képernyőtérben A fenti megoldások segítségével sok minden megvalósítható. amely mindig a kamera felé néz. Elég sokat barangoltunk az elméleti síkon. Játékok a Mango világában 11-7. amely még sokkal valósághűbb eredményt ad. Készítsünk belőle sokat. azonban hol vannak az olyan természetben előforduló jelenségek. ábra: Fénykontrasztos (HDR) effekt 11-8. amellyel az egész folyamat újra lejátszódik! Ezt a megközelítést részecskerendszernek hívják. ezért makroszkopikusabb elemekkel kell megközelítenünk a problémát. A mai modern játékok a részecskerendszert is a GPU segítségével valósítják meg és fizikai szimulációval egészítik ki. és adjuk át egy olyan metódusnak. fűzzük fel egy listára. majd utána a gyakorlatban is megnézzük. 276 . milyen sebességgel és hogyan kell mozogni! A kód gondoskodjon arról is. hó. és a legtöbb.11. tűz. mint az eső. hogy ha egy elem már nem látható. hogy az egyes négyzeteknek milyen irányba. amely megmondja. és hogyan használjuk őket. amely egy esőcsepp mintázatát tartalmazza áttetsző háttérrel! Feszítsük azt ki egy négyszögre.

Ha pedig ez is megtörtént. folyamatosan fut. Windows Phone telefon képernyőjének megérintése. de hogyan kezeljük a bemenetet. egy olyan környezethez vagyunk hozzászokva. amelyen belül folyamatosan ismétlődni fog a renderelési lépés. így garantáltan másodpercenként legalább 30-szor létrejön a kívánt kép.Grafikus programozási és XNA alapok A játékciklus Amikor alkalmazásokat fejlesztünk. hogy úgy tekintünk a programra. a fizikai szimulációt. billentyű illetve egérkattintás. A program indulása során inicializáljuk a szükséges paramétereket. a felhasználó másodpercenként 30 alkalommal biztosan nem fogja lenyomni az egérgombot. stb. amíg az előbb felsorolt tevékenységek közül valamelyik be nem következik. hogy volt-e valamilyen bemenet a felhasználó oldaláról – Xbox kontrolleren egy gomb lenyomása. Először megnézzük. (11-9. akkor megáll. ahogy az valójában működik is. mint szemlélő kívülről tekintünk) renderelése. ábra) 11-9. ez az eseményvezérelt szemlélet sajátossága. 30-szor kell pillanatfelvételt készítenie. Egy játéknak a PC esetében másodpercenként körülbelül 60. majd továbblépünk például a mesterséges intelligencia lépéseinek a számítására. a felhasználó valamilyen interakciót végez a felhasználói felületen vagy a háttérben valamilyen adatszinkronizáció történik. azaz a számítások és a bemenetek függvényében a színtér (az a tér. ábra: A játékok végrehajtási modellje Egy XNA program felépítése A hosszas elméleti bevezető után nézzük meg. Mindezt másodpercenként 30 alkalommal végezzük el. Ez eddig tökéletesen működőképes elgondolás. amelyek nélkül működésképtelen? Ezekhez nincs szükségünk eseményekre! Mindössze a ciklus törzsén belüli sorrendre kell odafigyelnünk. majd belépünk egy végtelen ciklusba. modellek.0 kategóriát! Ezen belül egy Windows Phone Game (4. majd amikor nincs több feladata. és amit. ahol a központi szerepet az események kapják. hangok. így magunknak kellene eseményt létrehozni. hanem az úgynevezett játékciklusos megoldást. Játékok írása során nem ezt a megközelítést szokták használni. betöltjük a tartalmakat (képek. akkor a ciklusból kilépünk. ahol a játék szereplői. mobiltelefon esetében kb. a mesterséges intelligenciát és még számos más komponensét a játéknak. Ha valamilyen tennivalója van a programnak. elmentjük az állapotot és felszabadítjuk a memóriából a jelentősen erőforrásigényes tartalmakat. Ha a felhasználó a menüben a kilépésre kattint (Windows Phone esetében ezt a szerepet a Vissza gomb kapta). amely hatására megtörténik a képszintézis (adott képkocka létrehozása – továbbiakban csak renderelésként fogjuk említeni). dinamikus és statikus tartalmai elhelyezkednek. Az alkalmazás a háttérben egy pillanatra sem áll meg. hogy „fut”. a mozgás érzetét keltve. Ha volt. akkor kezeljük azt. ezzel nem jön létre külső interakció. akkor úgy tekintünk a programra. ábra). amíg ki nem lépünk. Ez azt jelenti. 277 . akkor jöhet a képszintézis. és egészen addig nem végez újabb feladatot. így a folytonosság. és az adott képkockát megjelenítenie a felhasználó számára. Nos. Természetesen ez csak elgondolás szintjén történik így.0) típusú projektre lesz szükségünk (11-10.). hogyan épül fel egy XNA alkalmazás! Indítsuk el a Visual Studio-t. és hozzunk létre egy új projektet! Itt a C# nyelvű sablonokat tartalmazó szekción belül válasszuk ki az XNA Game Studio 4.

hogy az XNA és Silverlight környezeteket együtt használjuk. Játékok a Mango világában 11-10. amelyet az alkalmazás elemeinek dekompozíciójához tudunk felhasználni. Content Pipeline Extension Library: Ezzel a projekttípussal saját fájlformátumunkhoz készíthetünk feldolgozót a tartalomkezelő számára. ábra: Új XNA projekt létrehozása Visual Studio-ban Minden sablont nem tudunk részletesen megvizsgálni ebben a fejezetben. a tartalomkezelőt és a játékciklust tartalmazza. de a fejezet során megnézzük a működését.5 újdonság. ábra: Egyszerű XNA sablon emulátoron való futtatása 278 . alapbeállításokat. Az inicializáláshoz szükséges részeket. A tartalomkezelőről még nem beszéltünk. hogy a projekt milyen részekből épül fel. amely lehetővé teszi. Windows Phone Silverlight and XNA Application: A Mangóhoz szorosan kapcsolódó Windows Phone 7. Windows Phone Game Library: A fordítás során DLL fájl keletkezik belőle. hogy melyik mire használható:    Windows Phone Game: Ez az alapja a leendő XNA játékunknak. emulátor segítségével próbáljuk ki az alkalmazást! 11-11.11.  Mielőtt részletesen megnéznénk. álljon itt egy rövid összefoglalás arról.

Nézzük meg a tartalmát: public class Game1 : Microsoft. olyankor a tartalomfájlok is átdolgozásra kerülnek. Hiába dolgozunk valamilyen tömörítési algoritmust használó médiaformátummal. } protected override void Draw(GameTime gameTime) { GraphicsDevice. Content. a zenék. hogy az XNA számára kezelhető formátumba kerülnek átalakításra.Update(gameTime).FromTicks(333333).Buttons. Az egyik maga a játék. mint például a textúrák. a kiterjesztését az elérési útban már nem fogjuk szerepeltetni.Pressed) this. public Game1() { graphics = new GraphicsDeviceManager(this). Tekintsünk például egy textúrát.png! Amikor a tartalomkezelőtől ezt az állományt lekérjük majd. hogy a program teljes feladatát pillanatnyilag a Game1 osztály látja el.Framework. az átkódolt állomány mérete jelentősen nagyobb lehet. SpriteBatch spriteBatch.Back == ButtonState.Game { GraphicsDeviceManager graphics.GetState(PlayerIndex. és így tovább. ahol kódunkat fogjuk írni. TargetElapsedTime = TimeSpan. base. } protected override void Initialize() { base. } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice). 279 . És itt felhívom a figyelmet arra.One).cs fájlban található. a hangok. melyet az XNA majd értelmezni tud. amely a Game1. a modellek. hanem a tartalomkezelő rendszer segítségével tudjuk betölteni. a másik viszont egy tartalomkezelő (Content Pipeline) projekt. A tartalomkezelő kódból való használatát még a későbbiekben látni fogjuk. és abból egy XAP fájl keletkezik (melyet aztán a telefonra tudunk telepíteni). vagy valamilyen saját. melynek feladata egy helyre összegyűjteni a játékhoz tartozó tartalmakat. Ha a tartalomkezelő nem támogat egy fájlformátumot.Xna. Amikor a játék forráskódját Visual Studio-ban lefordítjuk.Grafikus programozási és XNA alapok A Visual Studio két projektet készített elő számunkra. mivel a PNG formátumú képfájlunkból a Visual Studio egy bináris képfájlt készít. } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { if (GamePad.FromSeconds(1). mivel az már egy belső formátumra kerül átalakításra.CornflowerBlue). InactiveSleepTime = TimeSpan. Ha áttérünk a játék kódját tartalmazó projektre.RootDirectory = „Content”. amely azt jelenti. hogy a XAP fájl méretét jelentősen növelni tudják a képek és zenék.Initialize(). amelynek a neve xnalogo. általunk készített formátumhoz szeretnénk értelmezőt készíteni. Miért van erre szükség? Az XNA alatt a különböző fájlokat nem fájlokként fogjuk használni.Clear(Color.Exit(). akkor arra lehetőségünk van a Pipeline Extension projekttípus segítségével. akkor láthatjuk.

nem érdemes vele próbálkozni. minden. Továbbá definiálja. Amikor emulátorban lefuttattuk a programot. Ahhoz. A másodpercenkénti képkockák számát (frames per second) harmincra korlátozza. láthattuk. és nem is használja a teljes képernyőt. azonban ennek a sebessége katasztrofális. hogy mi magunk állítsuk be a felbontást a Windows Phone telefonok által pillanatnyilag egységesen támogatott 480×800 pixeles méretűre. Ha az Update lefutott. hogy az adott funkciót nem használhatjuk ki.11. Az első a betöltésért. 280 . helyezzük el a következő kódsorokat az osztály konstruktorán belül: graphics = new GraphicsDeviceManager(this). amelyre a játéknak szüksége van. Itt nincsenek limitációink. graphics. a státuszsort eltüntetni. a játék logikáját és minden egyéb számítást. akkor a CPU-nak is átadható a feladat.Draw(gameTime). Két külön metódusunk van. hogy kiderítse az adott hardver képességeit − sajnos nem rendelkezik minden egyes grafikuskártya ugyanazokkal a képességekkel. azt szabadon használhatjuk. hogy a felbontása nem megfelelő. Ha valamit nem támogat a hardver. A Reach profil mind a három platformon azonosan működik.PreferredBackBufferWidth = 480. A másik profil a HiDef. A konstruktor tartalmaz még két fontos beállítást. Játékok a Mango világában base. hogy az alkalmazás futni fog az adott célhardveren. ábra). és a játék grafikája már nem lesz olyan szép. és lekérdezni a fejezet korábbi részében tárgyalt profilbeállításokat. ami az XNA és a hardver által támogatott. hogy az a későbbiekben a 2D-s képeinket (ezek az ún.IsFullScreen = true. graphics. Ennek az objektumnak a feladata közvetlen kapcsolatba lépve a grafikus hardverrel. } } A GraphicsDeviceManager objektum segít elérni a program számára használható beállításokat. sprite-ok) kirajzolja. amely a telefonokon futó játékprogramok számára irányelv. graphics. Itt érdemes kezelnünk a bemeneteket.PreferredBackBufferHeight = 800. amely először törli a rasztertár előző tartalmát. az Update felel a mögöttes számításokért. Az előnye. Így csak az marad. akkor kerül sorra a Draw meghívása. Kétféle profilt használhatunk. hol fogjuk a tartalomkezelő segítségével elérni a játékhoz tartozó fájlokat. míg a második a memóriából való felszabadításért felel. Ahogy a nevük is mutatja. OpenGL és Direct3D használata esetében a játékmotor feladata az. és ezzel teljes képernyőssé tenni a programot. Az XNA keretrendszer egyszerűsíti ennek a folyamatnak a lépéseit. amely az osztályhoz tartozó SpriteBatch példányt hozza létre. és érdemes is minden esetben betartani. azonban nem használja ki a grafikuskártyák adta legkülönfélébb speciális funkciókat. és felrajzolja a színterünket pillanatnyi állapotnak megfelelően. hogy biztosak lehetünk. A LoadContent() metódus elején található egy nagyon fontos sor. A Draw() és az Update() metódusok a játékciklus részei. Itt tudjuk például beállítani a játék felbontását. amely a tartalmak kezelésével foglalkozik. mint amilyennek eredetileg terveztük. A profilbeállítások az XNA projektre kattintva a Properties szekcióban találhatók (11-12.

Ugyanaz a négyszög. Mivel nincs még képünk. Egy négyszög. Ez mindig a SpriteBatch. amelybe típusuktól függően rendezhetjük a fájlokat. hogy alakzatokkal foglalkozzunk. 2. és ennek egyetlen paramétere a törlési szín megadása. A Draw több paraméterezéssel is elérhető. A kirajzolandó textúra objektum. Ha a képernyőt töröltük. 2. amely az előző paraméterezés esetében is. Ha fehértől eltérőt adunk meg. ezek közül kettő fontos számunkra: Az első paraméterezésben szereplő paraméterek sorrendben: 1.End() metódushívások között történik a Draw metódus hívásával. Itt is tudunk létrehozni mappákat és almappákat. amely első két paramétere a sprite pozíciója. A kirajzolandó textúra objektum. A tartalom (jelen esetben ez a textúra) lekérést a Content. a második kettő pedig a sprite mérete pixelekben kifejezve. A második paraméterezés: 1. ezek a képek egy négyszög területét töltik ki. 3. és azoknak a csúcspontjai alapján hajtsuk végre a renderelést. csak a 2D-s játékok fejlesztéséhez szükséges elméleti és gyakorlati anyagokat vesszük sorra. nem foglalkozunk 3D-s tartalmakkal. Gondoljunk csak bele egy egyszerű 2D-s játék esetében képeket rajzolunk fel. Egy térbeli játék esetében szükséges lenne.Clear() metódusa végez el. azonban most sokkal könnyebb dolgunk lesz. így keressünk egy tetszőleges PNG vagy JPG fájlt.Begin() és SpriteBatch. mivel a tartalomkezelő számára ez átalakításra kerül a projekt fordítása során. ábra: XNA alkalmazásprofilok Sprite-ok Ahogy azt már a fejezet korábbi részében leszögeztük. A textúrát lehetőségünk van összemosni egy másik színnel. így a betöltés kódból sokkal strukturáltabb lesz. Ebben a feladatban a Texture2D objektum fog segíteni. a képernyő összes pixele ezt a színt veszi fel.Load<T>() generikus metódus segítségével tudjuk elvégezni. esetleg automatizálható. 281 . amelyet a GraphicsDevice. Ha valamilyen interakció történik. és helyezzük el a Content projekten belül! Tipp: a tartalomkezelő (Content) projekten belül mindig érdemes rendet tartani. Itt mindig a tartalom Content projekten belüli elérési útjára hivatkozzunk és az adott fájl kiterjesztését hagyjuk le. akkor ezeket a négyszögeket kell mozgatnunk a képernyő dimenziói között. Hogyan tudunk egy képet megjeleníteni XNA-ban? Textúraként. amely a tartalomvezérlőtől le tudja kérni a szükséges képinformációkat. Ezek után megkezdhetjük a sprite kirajzolását! Ez mindig képernyő (pontosabban a rasztertár) törlésével kezdődik. akkor a textúra pixelei összeszorzásra kerülnek az adott színnel.Grafikus programozási és XNA alapok 11-12. akkor jöhet a tényleges rajzolás.

11. ábra: Két sprite kirajzolása két különböző módon 282 . 5.Black). A következő kód egy textúrát rajzol ki két különböző módon: private Texture2D xnaLogo. } protected override void Draw(GameTime gameTime) { GraphicsDevice. protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice). base. spriteBatch. Z-Index: ez egy nagyon fontos paraméter! Ezzel adhatjuk meg [0. Vector2. Alapesetben ez a képernyő bal felső sarka (0. 7. Color. 45.0f.0f ). Color. 4. Egy újabb négyszög. 114 ). 1] közötti valós számok segítségével. A sprite origójának megadása. spriteBatch. 6. 400. sprite sheetek létrehozásakor fogjuk látni a fejezet egy későbbi részében. A program futását a 11-13. new Rectangle( 200.Clear(Color.End(). ezzel mélységi sorrendet tudunk kialakítani. hogy az adott sprite a többi előtt vagy mögött helyezkedik-e el. amely segítségével a textúrából egy darabot ki tudunk vágni. ha egy fűcsomó vagy bokor lenne a játékosunk előtt.CornflowerBlue. SpriteEffects. 230. Az összemosási szín.Zero.FlipVertically.Load<Texture2D>( @"xna-logo" ).Draw( xnaLogo. 114 ). akkor nyugodtan próbáljuk ki emulátorban az alkalmazást (ha van rá lehetőségünk. A sprite horizontális illetve vertikális tükrözésére van lehetőségünk a SpriteEffects osztály használatával. 400. Z-tengely körüli (a képernyő síkjában) való forgatás valós szöggel kifejezve. Jelentőségét az ún. xnaLogo = Content. 0 ). így a mélységi sorrendjüket megváltoztatni szükséges. telefonon is kipróbálhatjuk. spriteBatch. Játékok a Mango világában 3. spriteBatch.White ).Draw( xnaLogo. Pl. 0.Draw(gameTime). 8. new Rectangle( 200. 230.Begin(). null. ugyanazt az eredményt fogjuk kapni). egy egyszerű kétdimenziós játékban nem szeretnénk. ábra szemlélteti. 11-13. } Ha a kódot implementáltuk és a megfelelő képfájl a Content projekt része.

pár pillanatig tartó érintés (tap). 11-14. Azonban a Windows Phone magas szintű támogatást nyújt az érintéspontok kezelésére. hogy a program milyen választ szolgáltasson a bemenet hatására. Az érintések kezelésére többféle lehetőségünk is van. amelyek bizonyos érintésmódok hatására aktiválódnak. vagy egymás után gyorsan végrehajtva két rövid érintés (double tap). Ebből saját algoritmussal kell megállapítanunk. ahol a képernyőhöz ért a felhasználó. ábra: Érintésminták Windows Phone Mangón 283 .Grafikus programozási és XNA alapok Bemenetek kezelése Minden egyes XNA által támogatott eszközre külön meg lehetne nézni a bemenetek kezelését. Ebben a fejezetben mi a Windows Phone Mangóra szeretnénk játékokat írni. és a programozó számára már események képében kerülnek megvalósításra. ami azt jelenti. Az operációs rendszer beépítve tartalmaz mintákat (gestures). de ez lehet akár egy folyamatos mozgatás is a képernyő felületén (touch and hold). mivel az teljesen más egy Xbox és egy PC esetében is. így az alkalmazásainkat egy Multi Touch (több érintést kezelő) környezetre kell kialakítanunk. Az 11-14. akkor lehetőségünk van a „nyers” érintésadatok lekérésére. A telefonok azonos időben egyszerre több érintést képesek lekezelni a képernyőjükön keresztül. hogy egy tömbben visszakapjuk azokat az (X. Y) koordinátákat. ábra a különböző érintésmintákat mutatja be. Ha nem kérjük az operációs rendszer segítségét. hanem mi magunk szeretnénk feldolgozni minden bemeneti információt. Ilyen lehet például egy egyszerű.

FreeDrag: position = new Point( (int)gesture. amelyekkel dolgozni szeretnénk.149 / 2. Ha egyszerű érintés törént.IsGestureAvailable ) { GestureSample gesture = TouchPanel. folyamatos mozgatás a képernyő felületén.Initialize(). Color clearColor = Color.Position.FreeDrag | GestureType.11. akkor megváltoztatjuk a program háttérszínét. Point position. (int)gesture. A következő kis mintaalkalmazás két mintát figyel.Tap: clearColor = clearColor == Color. a másik pedig a szabad.ReadGesture() metódusa teszi.White. Megkérjük az operációs rendszert.IsGestureAvailable tulajdonságának lekérdezése –. switch ( gesture. akkor a Windows Phone logót ábrázoló textúrát elmozdítjuk az érintés irányába. amelyiket legutoljára észlelt. wp7Logo = Content. akkor a játékciklusunk Update szekciójában folyamatosan figyelnünk kell. hogy volt-e valamilyen bemenet. Texture2D wp7Logo. Az egyik az egyszerű érintés. base.EnabledGestures = GestureType. break. hogy szolgáltassa vissza számunkra azt a érintésmintát. Játékok a Mango világában Az érintésminták feldolgozása az XNA alkalmazásokban nagyon könnyen elvégezhető! Első dolgunk engedélyezni a program számára azokat a gesztusokat.ReadGesture(). case GestureType. akkor elkezdjük azokat feldolgozni.177 / 2 ). } 284 . Ha a gesztusok engedélyezésre kerültek.Y .Black : Color. } } base.Load<Texture2D>( @"xna-logo" ). Ha voltak interakciók –ennek ellenőrzéséhez nem kell más. ha pedig a szabadon való mozgatás. xnaLogo = Content. protected override void Initialize() { TouchPanel.X .White.Load<Texture2D>( @"wp7-logo" ).Zero. Az EnableGestures tulajdonságát a GestureType elemeivel kell feltöltenünk. Ezt a TouchPanel objektumon keresztül tudjuk megtenni.White ? Color.Update(gameTime). } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice). Az egyes elemeket logikai “vagy” művelet segítségével tudjuk felsorolni. Ha több minta is engedélyezve van. Ezt a TouchPanel. mint a TouchPanel. position = Point. ahol felsoroljuk a használni kívánt érintésmintákat. break.Tap. akkor meg kell vizsgálnunk a minta típusát. private private private private Texture2D xnaLogo.Position. } protected override void Update(GameTime gameTime) { while ( TouchPanel.GestureType ) { case GestureType.

Ha ezeknek az ütközését figyeljük. akkor sokkal kevesebb számítással jutunk eredményre. Például a BSP vagy a Quad fa a teret cellákra osztja fel. azaz a játék objektumainak egymással való ütköztetése minden játékban nagyon fontos szerepet tölt be. Viszont sok objektum esetében még ez is lassuláshoz vezethet. akkor velük már nem is 285 . position.White ). ábra: Az érintések hatása a mintaalkalmazásban Ütközések detektálása Az ütközések észlelése.X. ha az objektum köré valami sokkal egyszerűbb térgeometriai alakzatot vonunk.Draw( wp7Logo. 400. ezért más módszerre lesz szükségünk! Sokkal jobb megoldás az. és levontuk a következtetést: egy grafikus alkalmazásban minden matematikai alapra vezethető vissza. hogy tudjuk. de a felhasználó szempontjából hibásnak tünteti fel a programunkat – amely teljesen jogos következtetés! Hogyan történik az ütközések kezelése? Először nézzük meg ezt általánosítva! A fejezet korábbi részében alaposan kiveséztük a poligonvázak felépítését.Grafikus programozási és XNA alapok protected override void Draw(GameTime gameTime) { GraphicsDevice. 11-15. Miután összetett alakzatokról beszélünk. pl. a belül található objektumok között lehetetlen az ütközés. spriteBatch. akkor is az A szereplő összes poligonjára meg kell vizsgálnunk. ábrán láthatjuk. Ez még kevés objektum esetén is jelentősen vissza tudja fogni a teljesítményt. } Az érintések hatásait a 11-15. Gondoljunk csak bele. a golyó szabadon elrepülhet a végtelenbe. és ha két cella olyan helyzetben van egymáshoz képest.White ). new Rectangle( 200. 102 ). 230. new Rectangle( position. Color. téglatest. 256. gömb. Color.Draw( xnaLogo. spriteBatch. hogy B szereplő valamelyik poligonjával ütközött-e.Draw(gameTime). stb. 114 ). Ez a játékélményt nemcsak.Clear( clearColor ). így sokszögek sokszöggel való ütközését (metszését) kell kezelnünk.End().Y. spriteBatch. hogy ha egy lövöldözős játékban nem kezeljük le a lövedék becsapódását. hogy teljesen megöli. ezért különböző struktúrákat és eljárásokat szoktak még bevezetni. Ha csak két szereplőt nézünk.Begin(). base. spriteBatch.

akkor az egyik objektumot átszínezzük. az autós példánál maradva. Játékok a Mango világában számolunk. és ennek függvényében haladunk tovább a játékban. amik a sík/térbeli forgatásokra is fel vannak készítve. akkor programozottan. Szerencsére mi kétdimenziós környezetben dolgozunk. if ( IsCollision() ) logoColor = Color. hogy volt-e ütközés. new Rectangle( position. Ha két négyszög akármilyen formában is metszi egymást. és a kódban kell meghatároznunk. hogy az alakzatot merre toljuk el térben. position. 230. Rectangle wp7 = new Rectangle( position. logoColor ).Intersects( wp7 ). Amikor a telefon mozgatásának segítségével egy autót kormányozunk. Négyszögekkel fogjuk körülvenni az alakzatokat. 400. vagy mennyire kicsinyítjük le. 102 ). A mai játékok jelentős hányada is ezeket a megközelítéseket használja. Az IsCollision() metódus a két befogó négyszöget megnézi. Ha az előbbiről van szó. kódból kell az animációt létrehoznunk. 256. hogy pontosan melyik esetről is van szó. 256. amikor magát a virtuális objektumot animáljuk. akkor a meglévő objektumot mozgatjuk a térben különböző szabályok alapján. .White. különböző módokon kombinálva és továbbfejlesztve azokat. fontos megkülönböztetnünk. } Animációk Amikor számítógépes játékokban animációról beszélünk. spriteBatch.. és ebből valamilyen valósághű 286 . hogy metszik-e egymást. nagyítjuk fel. akár egyes pontjaiban más animációkkal kombinálva folytatódhat tovább a cselekmény. Az Update() metóduson belül folyamatosan figyeljük.. amin az objektum végighaladhat. position.11. Meghatározhatunk görbéket (utakat). akkor ütközés történt. ahol eltekintünk a különböző forgatásoktól.Y. így jóval egyszerűbb esetekre kell csak felkészülnünk..X. és a képernyő megérintésével például lehetőségünk van fékezni. return xna. Viszont a második esetben nem tudjuk kódból (legalábbis csak nagyon nehézkesen) létrehozni az előbb említett lépéseket.Update(gameTime). else logoColor = Color. base.. és annak is a könnyebben kezelhető formájával. Axis Aligned Bounding Volume-nak hívják.Yellow.Draw( wp7Logo. 102 ). Egy másik eset az.. és ha igen. } protected override void Draw(GameTime gameTime) { . az adott geometriának a pontjait körülményes lenne külön-külön transzformálni. 114 ). Azokat a befogó alakzatokat. és az ennek megfelelő logikai értéket dobja vissza.. részletes leírásokat lehet találni Wikipedián. protected bool IsCollision() { Rectangle xna = new Rectangle( 200. } protected override void Update(GameTime gameTime) { .White. mennyire forgatjuk el. private Color logoColor = Color.Y.X. az autónak több tengely körül forognak a kerekei vagy akár kinyílhatnak az ajtói.

gyorsan megjeleníteni. amelyen a híres Unreal Engine játékmotor karakteranimálása látható. amelyek a program komplexitását jelentősen növelni tudják. A térbeli animálásnak rengeteg aspektusa létezik. ábrán egy futónak az animációját bemutató sprite sheet látható. ezért ezt valamilyen modellező alkalmazás segítségével (3D Studio Max. Ha egy soron végigértünk. ízületi részekkel összeköti őket. stb) szokták végrehajtani. akkor az animáció lehetne a képek egymás után váltakozása adott sebességgel. hogy egy térd mekkora szögben és merrefelé tud hajlani. Rhino 3D. Az animáció összes lépése egy adott képfájlban kerül eltárolásra. akkor a következő sorban folytatjuk a „kis képek” kivagdosását. Egy másodperc animációhoz tegyük fel. ábra: Csontozásos animáció – Unreal Engine Két dimenzióban azonban nincsenek olyan poligonok. Maya. Helyette a sprite sheet nevezetű megoldást fogjuk használni. ábra mutatja be. A csontozásos animációt az 11-16. A grafikus szakember a csontokat animálja. Ha ez megvan. akkor a poligonmodellel összeköti és definiálja az anyagtulajdonságokat. akkor a poligonváznak hogyan kell ahhoz alkalmazkodnia és deformálódnia. ezt kiegészítve ízületekkel és a csontok bőrhöz (skin) való igazításával. amelyet úgy dolgozunk fel. 287 . amelyeket animálni lehetne akármelyik módszert is használva. amíg a végére nem érünk az adott animációnak. Ehhez 30 különböző képet kell egymás után. 30 külön képfájlban tárolva a képeket. 11-16. A 11-17.Grafikus programozási és XNA alapok mozgást előállítani. transzformálódnia a térben. azok kezelését jelentősen túlbonyolítanánk. ráadásul feleslegesen. A modern játékok jelentős része – megint csak a valós életre visszavezetve – ún. Adott egy ötlet: ha a karaktereket sprite-ként jelenítjük meg. mivel a fizikai motor szintén felhasználhatja a csontokat rugalmas testek fizikai hatásainak modellezéséhez. „csontozáson” alapuló karakter animációkat alkalmaz. hogy sorra vesszük a kép X × Y méretű részeit. hogy ha a csontozat mozog. amely megszabja például. Ezek a tulajdonságok azt írják le. Továbbá a csontozásos rendszer segít a játéktérben való adaptációban is. hogy szükség lenne 30 képkockára.

ha a játék nem futtatható valamilyen eszközön megfelelő sebességgel. Rotation – Z-tengely körüli elforgatás mértéke szögben mérve. SheetSize – Hány képkockát tartalmaz a sprite sheet (sorban. Ennek feladata a játékban eltelt idő mérése. Az egyik a frissítésért felel (Update). magasság). amely a sprite sheetet tartalmazza. Position – A kirajzolandó sprite (X. akkor a későbbiekben nem kell a metódusokról saját magunknak gondoskodnunk. hogy az adott animációt milyen sebességgel játssza le. Ha az osztályt a GameComponent ősosztályból származtatjuk. a játékciklus megfelelő helyein meghívásra fognak kerülni. Az osztály tetszés és igény szerint tovább bővíthető. FrameRate – Az animáció sebessége (képkocka per másodperc). A telefonon egy játék 30 FPS-szel fut. a másik pedig a kirajzolásért (Draw). Miért van erre szükség? Gondoljunk csak bele. A következőkben egy olyan sprite sheet osztályt fogunk készíteni. az teljesen furcsa hatást keltene. oszlop)? Texture – Az a Texture2D objektumpéldány. oszlopban)? CurrentFrame – Éppen melyik képet jelenítjük meg (sor. hogy a fenti kép egy 6 × 5 = 30 képkockás animációt tartalmaz. akkor a valóságban eltelt idő mérése nem lesz elegendő. 288 . ábra: Egy futó animációjának leírása sprite sheettel Látható. ha például egy autó ugyanolyan sebességgel haladna. Játékok a Mango világában 11-17. A frissítést megvalósító metódus paraméterül kap egy GameTime objektumpéldányt. Nézzük. amelyen szabályozható. Két metódust kell létrehoznunk. de a fenti tulajdonságok megvalósításával a program legtöbb esetben már így is jól használhatónak fog bizonyulni.11. mint a felhők. milyen tulajdonságokra lesz szükségünk az osztályban:        FrameSize – Egyetlen képkocka mérete (szélesség. Y) koordinátái. de nem lehet minden animációnak azonos a sebessége.

Itt kell megadnunk. int y = CurrentFrame.Y.Milliseconds.Y. FrameSize. if ( y >= SheetSize. set.X. } public Texture2D Texture { get. FrameSize. } public float Rotation { get. FrameRate = speed.Draw( Texture.X.Y ). Vector2.X. A Draw() metódus többi paraméterét a fejezet korábbi részében már átbeszéltük. A második paraméter feladata megmondani az XNA-nak.X.X ) { x = 0. SpriteEffects. } public Point SheetSize { get. new Rectangle( Position. set. amely a játékunk „lassult” végrehajtási sebességéhez igazodik. FrameSize. Itt sorszám × képkocka_szélesség és oszlopszám × képkocka_magasság értékekkel kell számolnunk. Számunkra itt a második és a harmadik paraméterek a fontosak. Point sheetSize.Y ).X * CurrentFrame. Texture2D tex. set. set. if ( x >= SheetSize. mint amit a fejezet korábbi részében használtunk.0f ). SheetSize = sheetSize. } public override void Update(GameTime gameTime) { timeSinceLastRender += gameTime.None. Rotation. } public void Draw( SpriteBatch spriteBatch ) { spriteBatch. A rajzolásért felelős kódunk a már ismert SpriteBatch.Draw() metódust hívja egy más paraméterezési móddal.Zero. int x = CurrentFrame. } public Point CurrentFrame { get. hogy mekkora darabját rajzolja ki az eredeti sheet-nek. public class SpriteSheet : GameComponent { public Point FrameSize { get. FrameSize = frameSize. set. Point frameSize. set. FrameSize. A harmadik paraméter már egy kicsit izgalmasabb. set. x++. FrameSize. hogy a következő képkockára mutasson. public int FrameRate { get. A metóduson belül megnézzük.Y.Y * CurrentFrame. y++. Texture = tex. Y) pozícióba rajzolja fel a textúrát és mekkora méretekkel. int speed ) : base( game ) { CurrentFrame = Point. new Rectangle( FrameSize. 0. ha igen.Grafikus programozási és XNA alapok szükségünk lesz egy olyan időmérési módszerre is.Y ) 289 . } public SpriteSheet( Game game. } private int timeSinceLastRender = 0. Color. ami az FPS számunknak megfelelő. eltelt-e már annyi idő. hogy melyik (X. if ( timeSinceLastRender > ( 1000 / FrameRate ) ) { timeSinceLastRender -= 1000 / FrameRate. akkor a CurrentFrame tulajdonságot megfelelően növeljük.White. Position. } public Point Position { get.X.ElapsedGameTime.Zero.

Update(gameTime). base. spriteBatch. ( 800 . ennek következtében az Update() metóduson belül az XNA automatikusan hívni fogja az objektumhoz tartozó Update() metódust. } 11-18. 296 ). 20 ). majd a játék komponensei közé felvesszük az objektumpéldányt. } protected override void Draw(GameTime gameTime) { GraphicsDevice.Position = new Point( ( 480 . Components. walk. Content. protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice).Load<Texture2D>( "walk" ). ábra: A sprite animáció egy pillanatfelvétele 290 . ábra illusztrálja.240 ) / 2.Begin(). A pozícióját a képernyő közepére kiszámítva adjuk meg. } } Ha az osztály készen van. 5 ). walk = new SpriteSheet( this. Játékok a Mango világában y = 0. spriteBatch. private SpriteSheet walk.296 ) / 2 ).Clear( clearColor ). } base.End().cs fájlban használjuk is fel! Hozzunk létre egy új adattagot. walk. } CurrentFrame = new Point( x. y ). amely az újonnan létrehozott osztály egy példánya! A LoadContent() metóduson belül szükséges inicializálnunk. new Point( 6.Draw( spriteBatch ). akkor a Game1.Draw(gameTime). new Point( 240.11.Add( walk ). Az emulátoron való futtatás eredményét a 11-18.

Ez a leírás csak a játék alapjait fogja bemutatni. ha nincs a segítségünkre a Silverlight. szövegmezőket még magunknak kell implementálnunk. akkor a gombokat. pl: menü megjelenítése. Hogyan tudjuk a kettőt közös nevezőre hozni? Az XNA pixelalapú tartalmakat rajzol ki. és ezenkívül számos egyéb is megtalálható az állapotgráfban. amely jelen esetben csak egy érintés a telefon képernyőjén! Ha az érintés koordinátái az adott gomb által takart síkrészbe tartoznak. Azonban a két technológia fúziója kérdéseket vet fel! Az egyik játékciklust használ. Így ha sikeresen ki is alakítunk egy menürendszert. hogy minden egyes eleségdarabka felszedése után a kígyó hosszabb lesz. játék vége állapot. még egy elemet leszámítva: a szüneteltetés gomb. Ezt úgy képzeljük el. így például egy Silverlightot használó programban nem jeleníthettünk meg semmilyen XNA tartalmat. hogy a gombot csak egyszer tekintsük lenyomottnak. A játékot bonyolítja. amelyeket nem játékalkalmazásokban már megszoktunk. azaz Silverlight alkalmazásokban akár háromdimenziós. a különböző játékélmény-elemek kialakítása már a kedves Olvasó feladata. textúrázott poligonmodelleket is meg tudunk jeleníteni. Mivel a játékciklus másodpercenként harmincszor lejátszódik. teljes mértékben a kreativitására bízom.XNA és Silverlight integráció XNA és Silverlight integráció A Windows Phone 7 első verziója még élesen szétválasztotta az XNA és a Silverlight által képviselt két külön világot. ahol maga a játék irányítása csak egyetlen állapotot jelent. miközben nem ütközik se saját testébe. mentés megjelenítése. A Mango egyik nagy újdonsága. és nincsen navigációs rendszerünk. Silverlight és XNA együtt a gyakorlatban Ahhoz. egy Snake játékot fogunk írni. így nehezebb lesz elkerülni. A pályán másra nem is nagyon lesz szükségünk. A felrajzolás ugyanúgy a játékciklusban történik. Valószínűleg mindenki jól ismeri a klasszikus kígyós játékot. amely az egyes alkalmazásoldalak között tud minket átvinni. akkor végrehajtunk valamilyen eseményt. Érdekesség: természetesen XNA-ban is készülnek különböző menürendszerek és „vezérlők”. azonban ezeknek az elkészítése körülményesebb sokkal. a pontszámítás. A pálya hátterét a 11-19 ábrán látható 480×800 pixel felbontású textúra fogja adni. amíg a Silverlight vektoralapon számított vezérlőkkel látja el ezt a feladatot. így a gombnyomás is harmincszor hajtódna végre. Hogyan tudjuk a különböző tartalmakat megjeleníteni? Ezekre a kérdésekre kapunk válaszokat ebben a részben. hogy a pályán véletlenszerűen megjelenő eleségeket összegyűjtse. illetve egy apró pontot ábrázoló textúrát fogunk a kígyó szegmensekhez felhasználni. se a pályát határoló falakba. melyet Silverlight segítségével valósítunk meg. stb. hogy valahol ne ütközzön. és a játékos feladata úgy irányítani a kígyót. míg a másik egy eseményvezérelt környezetet valósít meg. ahol a szereplőnk apró blokkokból épül fel. hogy az XNA és Silverlight együttműködését gyakorlatban is megismerjük. A játékot mint egy nagy állapotgépet kell elképzelnünk. Azonban figyelnünk kell arra. hogy képes hibrid renderelésre. listadobozokat. 291 . hogy lekezeljük a bemenetet.

a mögöttes kód viszont az XNA-val való együttműködésre fel lett készítve. amely a kígyónak a szegmenseit tárolja. a másik viszont újdonság. melynek neve SnakeBlock. amely a felhasználói felületünknek az alapját jelenti. Minden egyes szegmensről tudnunk kell a következő információkat:     Position: a szegmens pozíciója a játék felületén (X. A játék jelentős részét itt fogjuk megírni. ennek a típusa most Windows Phone Silverlight and XNA Application legyen. Készült még két projekt. amikor a kígyó kanyarodik valamerre Texture: a kígyószegmens textúrája Hozzunk is létre egy új osztályt a SnakeLib projekten belül. a neve pedig Snake.xaml fájllal is. Az egyik az XNA tartalomkezelője. és a tartalma a következő osztálydefiníció a megfelelő tulajdonságokkal: 292 . amerre haladnia kell (irányvektorként tekintsünk rá) PrevDirection: akkor fogjuk felhasználni. Játékok a Mango világában 11-19 ábra: a Snake játék háttértextúrája Hozzunk létre egy új projektet. hogy a fő projekt tartalmazza a Silverlight alkalmazásokban jól megszokott MainPage. Y) koordinátákkal Direction: az aktuális irány. továbbá alkalmas arra. amely hivatkozik a Content projektre. Miután a projektet létrehoztuk. melynek deklaratív része teljes mértékben üres. Továbbá bővült a projektünk az eddigiekhez képest egy GamePage. szükségünk lesz egy osztályra. ahogy a 11-20 ábrán is látható! 11-20 ábra: új projekt létrehozása a játékhoz Látható.11. Egy XNA könyvtár. amellyel már találkoztunk a fejezet során.xaml fájlt. hogy elkészítsük benne az XNA komponenseinket.

akkor másodpercenként 30szor lesz léptetve a játékos.XNA és Silverlight integráció public class SnakeBlock { public Vector2 Position { get. public bool IsPaused { get. amely magát a kígyót és a viselkedéséhez szükséges elemeknek egy nagy részét tartalmazza.Y * 4 * 16 ) } ). snake = new List<SnakeBlock>(). snake. } public Vector2 PrevDirection { get. snake[ 0 ]. Position = new Vector2( basePos.Y . 1 ). és ehhez tároljuk le az utolsó frissítés időpontját! A konstruktor feltölti kezdeti értékkel az adattagokat.PrevDirection = snake[ 0 ]. private readonly Vector2 basePos = new Vector2( ( 480 . Először is szükséges egy lista. ( 800 .16 ) / 2 ). a ContentManager létező példányát is át kell majd adni konstruktoron keresztül és letárolni azt.Y . basePos.baseDir. Position = new Vector2( basePos.Y . } public Vector2 Direction { get. Állítsuk majd be mondjuk fél másodpercenkénti frissítésre. és létrehozza az első öt szegmenst a kezdeti irány és a pozíció függvényében: public class SnakeObject { public List<SnakeBlock> snake { get.Add( new SnakeBlock { Direction = baseDir.Add( new SnakeBlock { Direction = baseDir. private set. snake. Ha nem korlátozzuk valamilyen módon. set. akkor készítenünk kell még egy másik osztályt is (ígérem.X.baseDir. amely a szegmenseket sorolja fel (kezdetben legyen ötelemű).baseDir. } } 293 . egy kezdeti irány. } // megállítható lesz a játék Silverlight UI-ról public SnakeObject( ContentManager cm ) { this. set. } private ContentManager contentMgr.Direction. snake. Miután a textúrákat az osztály magának fogja lekérni. amitől teljesen irányíthatatlanná válik.Now.Y * 1 * 16 ) } ). set. basePos. Position = basePos } ).Add( new SnakeBlock { Direction = baseDir. snake.contentMgr = cm.Y * 2 * 16 ) } ).Add( new SnakeBlock { Direction = baseDir. Position = new Vector2( basePos.Y * 3 * 16 ) } ). set.X.X. basePos. set.Add( new SnakeBlock { Direction = baseDir. private DateTime lastTime = DateTime. Position = new Vector2( basePos.és pozícióvektor. basePos.X. private readonly Vector2 baseDir = new Vector2( 0.16 ) / 2.Y . A sebesség sem közömbös tényező.baseDir. nem visszük túlzásba az objektum-dekompozíciót). } public Texture2D Texture { get. Ezt is a SnakeLib nevezetű XNA projekten belül. } } Ha megvagyunk a szegmens osztállyal. snake.

Draw() metódust. 16. Ez egy kicsit nagyobb falat lesz. mint a frissítést végző Update() metódust megvalósítani. public void Draw( GameTime time. irányt mutató mozdulata merre mutat.Texture = contentMgr. } Betöltöttük a textúrákat. fel tudjuk rajzolni a szegmenseket. nem azt szerettük volna elérni. amely jól használható olyan esetekben.ReadGesture().Y ).Delta. ami fél másodpercenként a kígyót továbblépteti a felületen. A kígyó irányításához. public void Update(GameTime gameTime) { if ( IsPaused ) return. így az irányvektort magunknak kell meghatároznunk.Delta. mindegy. -1 ). } A fejezet példáinak a végigolvasása (esetleg végigpróbálása) után a felrajzolás nem okozhat problémát. while ( TouchPanel. Amikor az új irányt meghatároztuk. mely tartományba mutatott az irányvektor.Y. SpriteBatch spriteBatch ) { foreach ( SnakeBlock block in snake ) spriteBatch.Direction. nincs más hátra.Position.X. A feladat egyetlen Texture2D példánnyal is megoldható lett volna. amely a szegmensek között mindig egy elcsúsztatást fog jelenteni.GestureType == GestureType. a legegyszerűbb paraméterezési móddal fogjuk meghívni a SpriteBatch. és ennek függvényében előállítjuk a kígyó új irányát. A frissítésnek van még egy második része is.Flick ) { double angle = GetAngle( gesture. Játékok a Mango világában Következő feladatunk a megfelelő textúra betöltése a szegmensek számára.11. public void LoadContent() { foreach ( SnakeBlock block in snake ) block. akkor megnézzük. if ( gesture. ezt mindenképpen le kell kezelnünk. amelyet egy segédfüggvény végez (GetAngle). Vector2 dir = snake[ 0 ]. hogy a határozott. new Rectangle( (int)block. 16 ).Draw( block. hanem iterációnként mindig csak egy szegmens.Texture.Position. Arkusztangens segítségével kiszámoljuk a mozdulatból származó irányvektorhoz tartozó szöget.IsGestureAvailable ) { GestureSample gesture = TouchPanel. melyet radiánban mérve kapunk vissza. mint azt előre gondolnánk. Ehhez a Direction és a PrevDirection tulajdonságokat fogjuk felhasználni. gesture. Minden egyes blokk ugyanazt a textúrát fogja kapni. Ezt nekünk valódi szögre kell átváltanunk.White ). azt fogjuk nézni. Először is a képernyőn gesztusok segítségével tud navigálni a felhasználó. azonban szerettem volna egy automatizált megoldást mutatni ciklus segítségével. hogy hol ér a képernyőhöz. hogy vízszintesen és függőlegesen mekkora változás történt. amikor több objektum textúráit töltjük be. a rá következő pedig majd egy másik iterációban. if ( 45 <= angle && angle < 135 ) { if ( dir. (int)block. Mivel az érintésminta csak azt tudja visszaadni. Ha a szög megvan. } 294 .Load<Texture2D>( @"Textures/sprite" ).Y <= 0 ) dir = new Vector2( 0. hogy a kígyó összes szegmense egyszerre mozduljon el az új irányba.X. Color.

} return num * 360.28318530717959.0 / 6.1 ]. 0 ).PrevDirection = snake[ 0 ].0 ) { num = 6. ezért 2 × pí.Position += new Vector2( dir2. beleütközött-e a kígyó a falba vagy a saját testébe.X >= 0 ) dir = new Vector2( 1.Direction.lastTime ). lastTime = DateTime. ezért át kell váltanunk valós szögmértékbe.PrevDirection. public static double GetAngle( double deltaX. } else { if ( dir.PrevDirection = snake[ i ]. hogy eldöntse. Az elsőnek annyi a feladata. } snake[ 0 ].Now . for ( int i = 1. Ha előállt a megfelelő érték. A képernyő és a játékunk koordinátarendszere egymáshoz képest el van forgatva.Position += new Vector2( snake[ i . snake[ i .XNA és Silverlight integráció else if ( 135 <= angle && angle < 225 ) { if ( dir.Y * 16 ).TotalMilliseconds >= 500 ) { var dir2 = snake[ 0 ].Atan2( -deltaY.1 ]. ++i ) { snake[ i ]. } } Mivel az érintésminta nem tudott szöget meghatározni. snake[ i ].Direction.Now.X <= 0 ) dir = new Vector2( -1.Count.PrevDirection = snake[ 0 ]. snake[ i ]. 295 .Y >= 0 ) dir = new Vector2( 0. snake[ 0 ].X * 16. double deltaY ) { double num = Math.X * 16.Direction = snake[ i . de a játékunk mit sem érne ütközésdetektáció nélkül.Direction = dir. } else if ( 225 <= angle && angle < 315 ) { if ( dir. ha igen. } Majdnem készen vagyunk a kígyót leíró osztállyal.Direction.Direction. deltaX ). Továbbá negatív szögekkel nem szeretnénk számolni.28318530717959 + num. i < snake. } } if ( ( DateTime. } snake[ 0 ]. 0 ).PrevDirection.Y * 16 ). így a függőlegesen mért értéket invertálnunk kell.1 ]. dir2. Két külön metódust fogunk bevezetni. snake[ 0 ]. akkor az még radiánban van. if ( num < 0.PrevDirection. akkor a megfelelő logikai értéket adja vissza. azaz 360 fokos forgatással számoljuk ki az adott szöget. 1 ). ezt magunknak kell megtennünk.

com/expression/blend/2008" xmlns:mc="http://schemas.Phone.Y.openxmlformats. if ( snakeHead.Count. hogy megnézze. a kígyó feje érintkezett-e a pályán elszórt kinccsel.Position.X.1 ].Y >= 784 ) return true.Position.Direction.X <= 16 || snakePosition.Position.microsoft.Intersects( block ) ) { var prev = snake[ snake.Intersects( snakeBody ) ) return true. Rectangle block = new Rectangle( (int)newBlock.microsoft. if ( snakePosition. (int)snake[ i ].Position.Direction.X * 16. (int)snake[ 0 ]. 16.Phone" xmlns:d="http://schemas.assembly=Microsoft.assembly=Microsoft.X.Add( new SnakeBlock { Position = prev.Direction. A gombnak explicit méretezést adtam.X.Shell.Phone. public bool DetectCollision() { var snakePosition = snake[ 0 ]. Továbbá létrehoztam a Click eseményvezérlőt is. } return false.X >= 464 ) return true. hogy történik ez. 16. if ( snakePosition.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" 296 .Texture } ).Count . Az ütközésvizsgálathoz megint csak jól közelített befoglaló négyszögeket használunk. } A kígyót leíró osztállyal készen vagyunk.Position. <phone:PhoneApplicationPage x:Class="Snake.Phone" xmlns:shell="clr-namespace:Microsoft. if ( snakeHead.microsoft. 16 ). Rectangle snakeHead = new Rectangle( (int)snake[ 0 ].Y <= 16 || snakePosition.Y.Y * 16 ). Direction = prev. (int)newBlock. 16. } public bool DetectCollisionWithNewBlock( SnakeBlock newBlock ) { Rectangle snakeHead = new Rectangle( (int)snake[ 0 ].Position. és a képernyő jobb felső sarkába igazítottam. } return false. (int)snake[ 0 ]. snake.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft. 16 ).Position. A korábbi fejezetek során részletesen láttuk.11. Játékok a Mango világában A másik metódus feladata pedig az.Y.Y. 16 ).Position. akkor adjon hozzá a kígyó testének legvégéhez egy új szegmenst. Texture = prev. i < snake. -prev. és azoknak a metszésviszonyát figyeljük.X. így a következő néhány sor kód semmilyen meglepetést nem tartogat.GamePage" xmlns="http://schemas. return true.Position + new Vector2( -prev.Position. i++ ) { Rectangle snakeBody = new Rectangle( (int)snake[ i ].Controls. for ( int i = 1. A GamePage. 16. 16 ).xaml fájlban létre kell hoznunk a szüneteltetés gombot. ha igen.

Szükségünk lesz egy új objektumpéldányára a kígyó osztályunknak. akkor hívhatjuk így is) inicializálása is. UIElementRenderer uiRenderer. mint a textúrák lekérését a tartalomkezelőtől.Current as App).SetSharingMode(true). snake = new SnakeObject( contentManager ). ami a mi esetünkben semmi mást nem jelent. akkor be kell töltenünk a tartalmakat. Itt történik meg az első felszedhető szegmens (ha az eleség név tetszetősebb. amikor a felület frissül. protected override void OnNavigatedTo(NavigationEventArgs e) { SharedGraphicsDeviceManager. hogy ide ne kelljen a későbbiekben visszatérnünk. private private private private private private private private ContentManager contentManager. 297 . Ahhoz.Draw += OnDraw.UpdateInterval = TimeSpan.xaml-lel indul az alkalmazás. GameTimer timer. Random rand = new Random(). } Amikor az oldalra navigálunk (először a MainPage. SpriteBatch spriteBatch. amely minden egyes alkalommal le fog játszódni. ha deklaráljuk.EnabledGestures = GestureType. timer. elhelyeztem egy UIElementRenderer adattagot is. timer.Current. TouchPanel. LayoutUpdated += new EventHandler(GamePage_LayoutUpdated). amellyel az eleséget fogjuk elszórni a pályán.Flick. SnakeBlock newBlock. egyelőre elég.Content. kelleni fog egy háttér textúra és egy véletlen szám generátor. Texture2D background.Update += OnUpdate.XNA és Silverlight integráció FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="480" shell:SystemTray.IsVisible="False"> <Grid x:Name="LayoutRoot"> <Button Width="140" Height="100" HorizontalAlignment="Right" VerticalAlignment="Top" Click="Button_Click">Pause</Button> </Grid> </phone:PhoneApplicationPage> Mögöttes kódban több új adattagot is létre kell hoznunk.GraphicsDevice.FromTicks(333333). a tartalomkezelő felhasználásával inicializálnunk kell a kígyó objektumpéldányunkat. public GamePage() { InitializeComponent(). timer = new GameTimer(). és onnan térünk át a játékoldalra). Az osztály konstruktorában engedélyeznünk kell az érintésminták használatát. amelynek funkcióját a későbbiekben részletesen megismerjük majd. contentManager = (Application. timer. és fel kell iratkoznunk az oldal LayoutUpdated eseményére is. SnakeObject snake.

mivel a kígyó osztály ütközésdetektáló metódusa az előző elemet automatikusan a kígyó testéhez fogja fűzni. Nagyon fontos megfelelő sorrendben dolgoznunk. rand.ActualWidth > 0 && LayoutRoot. } void GamePage_LayoutUpdated(object sender. hogy az is kirajzolásra kerüljön. } Két nagyon fontos része van vissza a játéknak. (int)LayoutRoot. private void OnUpdate(object sender.11. A sima ütközés lekezelését az Olvasóra bízom.Next() % 800 ). az ütközések két különböző típusát fogja figyelni. if ( snake.Load<Texture2D>( "Textures/Background" ).Next() % 480. és a Silverlight alapon definiált felület automatikusan nem kerül megjelenítésre. base. A játékciklus két komponensét el kell készítenünk. akkor a textúrába renderelt Silverlight tartalmat is egy egyszerű Sprite-ként felrajzoljuk.Update( null ).ActualHeight > 0 ) uiRenderer = new UIElementRenderer( LayoutRoot. mivel tartalma egészen egyszerű lesz. RoutedEventArgs e) { snake. Miután ezek is megjelenítésre kerültek.IsPaused = !snake. // ezt a részt az olvasó kreatívitására bízom if ( snake. textúrát kell belőle készítenünk.Start().Next() % 800 ).Load<Texture2D>( "Textures/sprite" ) }. a másik pedig a LayoutUpdated eseményvezérlő.DetectCollision() ) . Az egyik a szüneteltetés gomb Click eseményvezérlője. amikor az elszórt szegmenst összeszedjük. timer. } } Mielőtt a rajzolást is megvalósítanánk. Texture = contentManager. amíg az eleség összeszedéséért felelős ütköztetést még együtt elkészítjük. mint generálni a helyére egy másikat.Position = new Vector2( rand. newBlock = new SnakeBlock { Position = new Vector2( rand.OnNavigatedTo(e). Először is megkérjük a környezetet.Next() % 480.IsPaused. amely egyelőre nem fog megjelenni. Játékok a Mango világában spriteBatch = new SpriteBatch(SharedGraphicsDeviceManager.GraphicsDevice). amelyhez a tartalmat folyamatosan frissítenünk kell. még két dolog hiányzik. } És a végére maradt a rajzolást végző OnDraw() metódusunk létrehozása.ActualHeight ). Nagyon egyszerű feladat! Semmi mást nem kell tennünk. EventArgs e) { if ( uiRenderer == null || LayoutRoot. Az utóbbit miért is hoztuk létre? Az XNA tartalom elsőbbséget élvez a kirajzolás során. hogy renderelje le a Silverlight tartalmat. Először érdemes a frissítést végző Update() metódust létrehozni. Ahhoz. 298 . snake. GameTimerEventArgs e) { snake.DetectCollisionWithNewBlock( newBlock ) ) { newBlock.Current. Utána felrajzoljuk a háttér textúrát és a kígyót. rand.LoadContent().ActualWidth. private void Button_Click(object sender. (int)LayoutRoot. background = contentManager. melynek feladata a színtér felrajzolása.

16 ). spriteBatch. spriteBatch. uiRenderer.XNA és Silverlight integráció private void OnDraw(object sender.Zero.Begin(). spriteBatch.Draw( uiRenderer. és a Pause gomb lenyomásának hatására a játék szüneteltetésre kerül. és betekintést nyertünk a számítógépes (vagy mondhatnám inkább okostelefonokra tervezett?) játékok 299 .White ). 16. 0.Xna. spriteBatch ).Draw( null. spriteBatch. spriteBatch. 11-21 ábra: A Snake játék futás közben Összefoglalás Ebben a fejezetben megismerkedtünk a Windows Phone platformot alkotó technológiák felépítésével. és futtassuk emulátor segítségével! A 11-21 ábrán látható eredményt kell kapnunk.Position.Rectangle( 0. } Ha készen vagyunk. Vector2. Határozott mozdulatokkal irányítható a kígyó. akkor fordítsuk le.Position.Texture.Draw( background. illetve újraaktiválódik.GraphicsDevice.Current.Xna.Draw( newBlock.Framework.Rectangle( (int)newBlock. spriteBatch.End(). Color.Texture.White ).Black).Render().White ). 800 ). new Microsoft. Color. 480.End().Begin().Y.X. sehol nincsenek már a projektben szintaktikai hibák.Framework. new Microsoft. snake. Color.Clear(Color. (int)newBlock. GameTimerEventArgs e) { SharedGraphicsDeviceManager. spriteBatch.

melyet az Olvasó tetszése szerint tovább bővíthet. illetve láttuk a Mangóban újdonságként bevezetett hibrid renderelési rendszer működését és használatát is. Éppen csak a felszínt érintve áttekintettük a számítógépes grafika elméleti hátterét és ennek kapcsán a játékokat alkotó grafikus megoldásokat is. Az utóbbira építve elkészítettük egy Snake játéknak az alapjait is. Megismerkedtünk az XNA Framework alapvető használatával. 300 . Játékok a Mango világában fejlesztésébe.11.

com – keretein belül a 99 USD éves díjat nem kell kifizetnünk.msdn. Magánszemély (akkor alkalmazzuk. hogy a Windows Phone 7 -nél már nemcsak egy egyszerű fájl másolásából áll a telepítés. ha elkészítünk egy alkalmazást. másfelől azért. nyomon követhetik azok népszerűségét. ami három fejlesztői készülék használatát (developer unlock) tartalmazza és a piactérre való publikálás lehetőségét. hanem már csak az a fejlesztő férhet a 301 . hogy ellenőrizze. mert felmérhetjük. ahonnan alkalmazásokat tölthetünk le. vagy szervezet) 2. Azok lehetnek ingyenesek vagy díjkötelesek. mert az emulátor és a fizikai készülék között komoly eltérések lehetnek a teljesítményt illetően. A fejlesztői regisztráció éves díja jelenleg 99 USD. frissíthetik azokat. aki megfelel a Marketplace feltételeinek. A regisztráció magánszemélyek esetén 1-2 napot. mint a Windows Mobile esetében. viszont az alkalmazásainkat célszerű kipróbálni egy fizikai készüléken is. ha a fejlesztő egy cég. ha aktív státuszú középiskolai vagy felsőoktatási hallgatók vagyunk. Cégek esetében a regisztrációt követően egy GeoTrust nevű cég fogja felvenni a kapcsolatot annak érdekében. Ezért minden esetben. Készüléken történő hibakeresés és regisztráció Könyvünk eddigi fejezeteiben az alkalmazások fejlesztésénél csak az emulátorra koncentráltunk. Egyfelől ez azért hasznos. a vállalat tényleg az általa megadott országban tevékenykedik. Ebben az esetben a DreamSpark program –http://dreamspark. és bárki publikálhat. és követhetik az értékesítésükből befolyt összegeket is. cégek esetén olykor 3-4 napot is igénybe vehet. Megnehezíti azonban a dolgunkat. ahol a fejlesztők kezelhetik az alkalmazásaikat. Ebben a részben a következő témákat nézzük át:          Mi az a Marketplace? Készüléken történő hibakeresés Készülék regisztráció Publikálás Screenshot készítés Marketplace Test Kit Képek és ikonok Marketplace Task-ek Trial Mode APPHUB Az AppHub a Microsoft Windows Phone 7 fejlesztői menedzsment oldala. A telefon és a rajta lévő operációs rendszer bármennyire is jó.com címen érhető el. mielőtt publikálnánk azt. cégek és a magánszemélyek esetén egy bankszámlára is. célszerű azt kipróbálni egy fizikai készüléken is. hogy használhatóság szempontjából milyen az alkalmazásunk. és ingyenesen publikálhatunk. a Marketplace-szel.12. Az AppHub a http://create. Cég nevében (akkor használatos. akár díjköteles alkalmazásokat is!) A regisztrációnál szükségünk lesz egy Windows Live ID-ra. Marketplace Ebben a fejezetben megismerkedhetünk a Windows Phone 7 ökoszisztémájának központi szereplőjével. A Windows Phone 7-hez tartozik egy piactér. üres lenne alkalmazások nélkül. Diákként (akkor válasszuk ezt a lehetőséget. illetve fejlesztőként publikálhatjuk saját alkalmazásainkat. Az AppHubra háromféle regisztrációtípus létezik: 1. ha egy egyszerű magánszemélyről van szó) 3.

majd ha ez megtörtént. adjuk meg a Live ID-nkat – azt. Ha a regisztrációt elvégeztük. amelyikkel korábban a Marketlace-re regisztráltunk –. hogy ha a készülékünket frissítettük vagy reseteltük. a telefonunk fejlesztői zárolása feloldásra került (12-2 ábra). akkor a developer unlock is eltűnik. Miután elindítottuk.net) telepítve kell lennie! Amikor összekötöttük a Windows Phone 7-et a géppel (12-1 ábra). USB kábellel kössük össze a készülékünket a számítógépünkkel! Figyeljünk arra. ha a képernyőzár fel van oldva! 12-2 ábra: Windows Phone Developer Registration Tool Az AppHub-on a saját fejlesztői fiókunk devices menüpontja alatt láthatjuk a zárolás alól feloldott készülékeink listáját. Marketplace készülékhez. hogy legyen egy ilyen előfizetésünk.zune. ilyenkor ezt a folyamatot meg kell ismételnünk! 302 . 12-1 ábra: Zune szoftver Fontos! Csak úgy tudjuk unlockolni a készüléket. indítsuk el manuálisan!). akkor automatikusan el fog indulni a Zune szoftver (ha ez valamilyen oknál fogva nem történne meg. regisztrálnunk kell magunkat a Marketplace-en. Figyeljünk arra. hogy a Zune szoftvernek (www. Abban az esetben.12. majd ezt követően el kell indítanunk a Windows Phone Developer Registration tool nevezetű alkalmazást (ez az alkalmazás a Windows Phone 7 SDK része). Ahhoz. kattintsunk az Unregister gombra! Ha minden rendben zajlott. ha esetleg lecserélnénk a jelenlegi készülékünket egy újabbra. aki rendelkezik fejlesztői fiókkal (developer account). akkor ezen az oldalon tudjuk eltávolítani a zárolás feloldását is.

Készüléken történő hibakeresés és regisztráció 12-3 ábra: AppHub a feloldott fejlesztői zárolású készülékek listájával Ha minden rendben zajlott. és megnyomjuk a Deploy gombot (12-5 ábra). Itt is fontos megjegyezni. Ezt követően az F5-öt megnyomása után már a készülékre kerül fel az alkalmazás. amelynek kezünkben van az XAP fájlja. Abban az esetben. akkor „Access is denied” hibát kapnánk. Ehhez mindössze a Visual Studio-ban kell a kimenetet átállítani Windows Phone Emulator-ról Windows Phone Device-ra. hogy a művelet során a telefon képernyője nem lehet zárolva! 303 . ahogy az emulátornál. Ez mind Visual Studio-ból. ha a fejlesztői környezetből publikáljuk a készülékre az alkalmazást. mind Expression Blendből egyszerűen megoldható. és ott tudunk hibát keresni (12-4 ábra). Alkalmazások telepítése Abban az esetben. hibát tudunk keresni az alkalmazásban. Az alkalmazás felépítése nagyon egyszerű: először megmondjuk. a debugger rögtön elindul és ugyanúgy. 12-4 ábra: Készülékre történő publikáció Figyelnünk kell arra is. ami szintén a Windows Phone 7 SDK része. hogy melyik eszköz a cél (target) – a készülék vagy az emulátor –. akkor az adott alkalmazás megjelenik a készülék vagy az emulátor alkalmazásai között. majd kikeressük a telepítendő XAP fájlt. ha csak egyszerűen telepíteni szeretnénk egy már lefordított alkalmazást. akkor már lehetőségünk van az alkalmazásunkat a fizikai készülékünkön is tesztelni. akkor ezt az Application Deployment Tool-lal tehetjük meg. Ha minden rendben zajlott. hogy az alkalmazás Visual Studio-ból történő telepítésekor is fel kell oldani a képernyőzárat! Ha ezt nem tennénk meg.

com/ oldal (12-6 ábra). hogy használni tudjuk. nem kell évente megújítanunk. függetlenül attól. 9 USD-be kerül telefononként. hogy ez nem ún. akkor egy előző. mégis hasznos lehet. vagy hogy az adott országból elérhető-e a Marketplace. általunk telepített alkalmazást el kell távolítanunk. Ezzel a feloldással csak a telefonra tudunk alkalmazásokat telepíteni. A 9 USD-t egyszer kell kifizetnünk. interop unlock. azaz nem kapunk hozzáférést a telefon mélyebb részeihez. ChevronWP7 A Microsoft támogatásával elindult a http://labs.chevronwp7. 12-6 ábra: Chevronwp7 labs Ha van Marketplace előfizetésünk. általában felesleges ezt a szolgáltatást megrendelnünk. Fontos kiemelni. Ezzel a feloldással is csak maximum 10 alkalmazást telepíthetünk a készülékre (diákok 3 alkalmazást). Marketplace 12-5 ábra: Az Application Deployment Tool A készülékre maximum tíz alkalmazást tudunk feltelepíteni a feloldott fejlesztői zár birtokában. a Marketplace-re nincs jogunk azokat feltölteni! Ahhoz. hogy milyen régióba tartoznak. Bár ez a szolgáltatás nem ingyenes. Ha ennél többre lenne szükségünk. egy Live ID-re lesz szükségünk. 304 . ahol a hobbifejlesztők feloldhatják telefonjuk zárolását.12. mint a Marketplace esetén.

0-val is. Az alkalmazásunkban nem lehet rosszindulatú kód (Maleware). az alkalmazásunknak több funkcionális és formai követelménynek meg kell felelnie. akkor felmentést kérünk. (Kezdhetjük akár 5. Ez meglehetősen általános leírás arról. Ezeket az alábbi 4 pontban foglalhatjuk össze: 1. mely csak az AppHubon fog megjelenni. milyen információt kell és lehet ezen az oldalon megadnunk (12-8 ábra):   App name for App Hub: Az alkalmazás neve. de a fentieken kívül elég sok feltételt kell még teljesítenünk ahhoz. Browse to Upload a file: Itt kell feltöltenünk az XAP fájlunkat. hogy mit nem tehet az alkalmazásunk. Az alkalmazások verziózása tetszőleges. hogy kell egy már elkészült alkalmazást publikálni a piactéren! Ehhez öt egyszerű lépést kell elvégezni. hogy publikáljuk. az első a Public Marketplace. ami akkor lehet hasznos. 3. például tesztelési célból. Az alkalmazásnak válaszképesnek kell lennie. itt az ideje publikálni a Marketplace-en! Ahhoz.) Requires technical exception: Ha ezt az opciót megjelöljük. Itt kell feltöltenünk az alkalmazásunkat.msdn. hogy az a piactéren megtalálható legyen! A következő néhány lépésben bemutatjuk a publikálás folyamatát. Az alkalmazásnak hatékonyan kell használni a telefon erőforrásait.Publikálás Publikálás Ha kész az alkalmazásunk. Ennek a névnek egyedinek kell lennie! Distribute to: Két menüelem közül választhatunk. 4. és a bejelentkezés után kattinsunk a Submit for Windows Phone gombra (12-7 ábra)! 12-7 ábra: AppHub oldal − Submit for Windows Phone A következő ablak az Upload. és egyedi nevet is itt kell választanunk a számára! Nézzük meg részletesen.com. Nézzük meg lépésről lépésre. mivel az alkalmazásunk valamilyen speciális oknál fogva nem felel meg a „Windows Phone 7    305 . 2. amivel az alkalmazásunkat mindenki számára elérhetővé tesszük. Az alkalmazásunk nem befolyásolhatja a telefonunk megfelelő működését. a másik lehetőség pedig a Private beta test. Látogassunk el az AppHub-ra: http://create. Application version number: Itt határozhatjuk meg az alkalmazásunk verzióját. ha csak meghatározott személyeknek szeretnénk az alkalmazást elérhetővé tenni.

illetve egyéb dokumentációra mutat. ennek segítségével hívhatjuk fel legelőször az alkalmazásunkra a felhasználók figyelmét. kitöltése opcionális. 12-8 ábra: Alkalmazás feltöltéséhez szükséges információ az AppHubon Ha az oldal adatait kitöltöttük. amivel a felhasználók kapcsolatba léphetnek az alkalmazás fejlesztőivel. és jóval hosszabb ideig tart. akkor minden nyelvhez külön-külön leírást kell adnunk! Nézzük át. Fontos megjegyezni. hogy ha többnyelvű az alkalmazás.     306 . hogy milyen tulajdonságokat lehet és kell kitöltenünk!    Kategória: Itt választhatjuk ki. Keywords: Meghatározhatunk maximum 5 kulcsszót. Ez maximum 25 karakter lehet. Marketplace Application Certification Requirements” által támasztott követelményeknek. például az alkalmazás-támogatási csoporttal. Az alkalmazásunk elbírálása ilyenkor egyedi. Ez is opcionális. amely az alkalmazásunkkal kapcsolatos licencekre. mint egy átlagos alkalmazás esetén.12. és a hozzá tartozó képeket. Email address: Egy olyan e-mail cím. milyen funkciói vannak. Legal URL: Egy olyan URL cím. kattintsunk a Next gombra! Néhány másodperc múlva betöltődik a Describe oldal (12-9 ábra). App name: Ez a mező automatikusan töltődik ki. és kötelező kitölteni. Ezt a mezőt kötelező kitölteni. de ajánlott a kitöltése. Detailed Description: A programunk részletes leírását adhatjuk meg. Ezt a mezőt kötelező kitölteni. amivel a felhasználók könnyebben megtalálhatják az alkalmazásunkat. Ezt az információt az XAP fájlból nyeri ki a rendszer. hogy az alkalmazásunk mire való. hogy az alkalmazás milyen kategóriába és alkategóriába (Subcategory) tartozik. Ezt kötelező kitölteni. ikonokat is itt adhatjuk meg. Short Description: Itt az alkalmazásunk rövid leírását kell megadnunk. ez maximum 2000 karakter lehet. Itt írhatjuk le részletesen.

a vásárlók ezt az ikont látják meg először a piactéren. Screenshots( 480x800 PNG fájlok): Minimum egy. hogy ezeket a képeket nem szabad grafikai szoftverrel módosítani. Background art (1000x800 PNG fájl): Ez a kép akkor látható. ha az alkalmazásunk ki van emelve a Marketplace-en (ún.Publikálás 12-9 ábra: A Describe fül alatt adjuk meg az alkalmazásunk leírását Az alapadatokat ezzel meg is adtuk. Opcionálisan választható a megadása. kötelező megadni. Ezt a képet láthatjuk a Zune-ból is.  307 . amikor egy katalógusban vagy egy keresési listában böngésznek. ha az alkalmazásunk részletes nézetét vizsgáljuk. ha a Zune szoftverből böngészik a piacteret. A kép megadása kötelező. mert a felhasználók sokszor ezek alapján döntenek. A screenshotok készítéséről a következő alfejezetben olvashatunk. amelyek az alkalmazásunkat működés közben mutatják be. maximum nyolc képet adhatunk meg. featured app). Fontos megjegyezni. Ebben az esetben ez a kép jelenik meg háttérképként. Ezek a képek nem lehetnek transzparensek!     Large mobile app Tile (173x173 Fájl): Egy png fájl. amikor az alkalmazásunkat betöltik. Small mobile app Tile (99x99 Fájl): Ezt a képet a felhasználók akkor látják. mit is lehet megadni (12-10 ábra)! A képek ajánlott felbontása 96DPI. Ezeket mindenképpen érdemes megadnunk. most már csak az alkalmazásunkkal kapcsolatos képeket és ikonokat kell feltöltenünk. Large PC app Tile (200x200 PNG fájl): Ezt az ikont látják a felhasználók. Nézzük meg sorban.

Az ár 0. Set Price tier: Itt határozhatjuk meg az alkalmazásunk árát. ahonnan a Marketplace elérhető. ilyenkor a „0.00” értéket válasszuk! WorldWide distribution: Kiválaszthatjuk.7 centben realizálódik.99 USD és 499.tehát ha egy alkalmazást mi például 1 USD-ért szeretnénk eladni. amit engedélyez. az nálunk 0. hogy az alkalmazásunkat az összes olyan országban elérhetővé tesszük-e. hogy az alkalmazásunkat trial (próba) módban engedélyezzük-e letölteni. A fejlesztőnek kell meghatároznia. hogy az alkalmazásunk mely piacokon legyen elérhető és hogy mennyiért. hogy a trial módban mi az. Természetesen ingyenesen is feltölthetünk alkalmazásokat. Ezen az oldalon a következő dolgokat állíthatjuk be (12-11 ábra):  Enable trials to be downloaded: Meghatározhatjuk.99 USD között lehet.   308 . Marketplace 12-10 ábra: Itt adhatjuk meg az alkalmazásunkhoz tartozó képeket és képernyőmentéseket Ha a Describe oldalon minden lényeges információt kitöltöttünk. illetve mit tilt le az alkalmazás funkcionalitásából. Az ár meghatározásánál vegyük figyelembe.12. hogy a teljes ár 70%-át kapjuk meg (bizonyos országoknál a helyi adókat is be kell fizetnünk). hogy mely országban vagy régióban publikáljuk az alkalmazásunkat. vagy egyesével megadhatjuk. A Trial mód használatával a fejezetünk későbbi részében ismerkedhetünk meg. Itt tudjuk beállítani azt. akkor kattintsunk a Next gombra! Néhány pillanat múlva betöltődik a Price ablak.

) Ezt akkor használjuk. ha az alkalmazásunkat csak egy szűk réteg fogja használni. mellyel az alkalmazásunkat rögtön publikálják a Marketplace-re. ha átmegy a teszteken. Ezt a funkciót „my dashboard” menüpont alatt érhetjük el. Az elfogadás folyamata néhány napot igénybe vehet: általában 1-2 nap. de csak azok a felhasználók érhetik el. és ezt követően bármikor visszatérhetünk az oldalra az alkalmazást publikálni. but make itt hidden: Hasonlóan az előző beállításhoz. akkor kattintsunk a Next gombra! Ezt követően a Test ablakra jutunk. deep linkre. Publishing options: Azt határozhatjuk meg. akkor sem kell aggódnunk. As soon as it’s certified: Ez egy automatikus folyamat. As soon as it’s certified. Akkor kell kitöltenünk. Menthetjük a folyamatot. Itt néhány teszteléssel kapcsolatos adatot adhatunk meg (12-12 ábra):   Test notes or instructions: A mező kitöltése opcionális.   Ha ezzel is készen vagyunk. (pl: egy cég számára készítünk egyedi fejlesztést). ekkor a soron következő köszöntő képernyő fogad. akikkel mi megosztjuk az alkalmazás elérhetőségét (ehhez szükségünk lesz egy ún.Publikálás 12-11 ábra: Price oldal – az alkalmazásunk árát és piacterületét határozhatjuk meg Ha kitöltöttük a megfelelő adatokat. kattintsunk a Submit gombra. 309 . hogy engedélyezzük a piactérre kerülést. de ha esetleg 4-5 nap lenne. ha az alkalmazásunk tesztelését végző személlyel speciális információt szeretnénk megosztani. amint sikeresen átment az ellenőrzéseken.  None: Ezzel a beállitással nem lehet publikálni az alkalmazást. hogy mikor kerüljön az alkalmazás a piactérre. itt is azonnal a Marketplace-re kerül az alkalmazás.  I will publish it manually after it has beed certified: A sikeres ellenőrzés után saját magunk kézzel kell.

Marketplace 12-12 ábra: Az alkalmazás beküldése Screenshot készítés Az alkalmazásunk feltöltése során a Marketplace megköveteli. OneNote. és a képet nem szabad módosítanunk semmilyen grafikai eszközzel! A képernyőkép készítéséhez persze elég sokféle eszközt tudunk felhasználni: például Snipping tool. de a legtöbbjük használata legtöbbször kényelmetlen. de a Windows Phone 7. 12-13 ábra: Screnshot készítése Nézzük meg használat közben! Indítsuk el az alkalmazást.12.1 SDK-ja óta ez a funkció már az emulátor mellett is megtalálható (12-13 ábra). akkor indítsuk el az 310 . A neten persze találhatunk erre is jó néhány eszközt. és kapcsoljuk ki a Frame rate számlálókat is! Ha ez megtörtént. hogy legalább egy 480x800-as képernyőkép legyen az alkalmazásunkról mellékelve. majd a nagyítási beállításokat (nagyító ikon) állítsuk 100%-ra. A méretnek pontosnak kell lennie.

ahol különböző teszteket futtathatunk le: Nézzük meg. Ezenkívül ezen a fülön adhatjuk meg az alkalmazások piactérre feltöltendő képeit és képernyőképeit. Windows Phone Marketplace Test Kit A Windows Phone 7. mire alkalmasak ezek a tesztek! Application Details Az Application Details fülön (12-15 ábra) adhatjuk meg az ellenőrzés során használt. és ezen kattintsunk a Capture gombra! Ezt követően már csak el kell mentenünk ezt a képet a „Save…” gomb segítségével. Ha nem adjuk meg ezeket a képeket. A tesztek lefuttatásához egy Release konfigurációval történő fordításra is szükségünk van. az alapbeállítás szerint a Bin\Release mappában található XAP-ra mutat.Publikálás alkalmazást. az alkalmazásunkhoz tartozó képeket. Az Applicaton package mezőbe az XAP fájl útvonala található.1 SDK –val érkezett egy hasznos eszköz (Marketplace Test Kit) is. ami nem engedélyezett a számunkra? Használ-e olyan API-t. majd az emulátor jobb felső sarkában található menüben válasszuk ki az Additional Tool ablakot (12-14 ábra)! 12-14 ábra: Additional Tool A megjelenő ablakban válasszuk ki a Screenshot fület. és navigáljunk arra az oldalra. Mit is árul el ez az eszköz alkalmazásunkról?              Megfelelőek-e a képek és a képernyőképek a követelményeknek? Megfelelő-e az XAP fájl mérte (maximum: 225 MB)? Elég gyorsan indul-e az alkalmazásunk? Nem használ-e túl sok memóriát? Rendeltetésszerűen működik-e a Back gomb? Nem használ-e olyan API-t. ikonokat és képernyőképeket. amivel megvizsgálhatjuk. akkor a tesztünk sikertelen lesz. 311 . amiről a screenshotokat szeretnénk elkészíteni. ami nem engedélyezett egy Backround Agenttel? Nincs-e váratlan hiba. ha bezárjuk az alkalmazást? Stb. hogy az alkalmazásunk megfelel-e a Marketplace követelményeinek. Application Details Automated Tests Monitored Tests Manual Test A Test Kit felhasználói felületén négy fül található.

Marketplace 12-15 ábra: Application Details (Marketplace Test Kit) Automated Tests Az Automated Tests fülön (12-16 ábra) az általános kritériumokat tudjuk tesztelni.xml fájlban. 12-16 ábra: Automated Tests (Marketplace Test Kit) Monitored Tests Ezen a fülön (12-17 ábra) mérhetjük meg az alkalmazásunk teljesítményét és válaszképességét. Az Application Details alatt megadott képeket is itt teszteljük. hogy az alkalmazásunk számára milyen Capability beállításokat (képességeket) kell meghatároznunk a WPAppManifest. Ha lefuttatjuk a tesztet.12. A teszt közben a program által felkínált lehető legtöbb felhasználói esetet hajtsuk végre az alkalmazáson! 312 . A teszt során az alkalmazást egy fizikai készüléken kell kipróbálnunk. akkor a teszt megmondja. tehát csak a fejlesztői zárolás feloldásával ellátott készüléken tudjuk ezt megtenni. például az alkalmazás méretét és képeit.

illetve visszalépéskor láthat a felhasználó. Célszerű ezeket a képeket mindig testreszabni. Abban az esetben. egy 62x62 pixeles kép.png egy nagyobb. ha nem teljesültek. hisz kellemetlen. és az alkalmazások listájában fog látszódni. ezenkívül van még egy SplashScreenImage. itt minden egyes tesztet végre kell hajtanunk. hogy minden kép Build Action tulajdonsága Content értékű legyen! Ha saját képet adunk 313 . Ezt azért használjuk. akkor egyszerűen a Result oszlop értékét állítsuk át Passedra. Ikonok Egy Windows Phone 7 –es solution úgy épül fel. amely egy 480x800 pixeles kép. Figyeljünk oda. ha az alkalmazást a felhasználó kirakja a főképernyőre.png.jpg. akkor a felhasználó ne nyomja meg rögtön a Back gombot. A Test Descriptionban leírt feltételeknek teljesülniük kell. ha például egy transzparens kép miatt visszadobják az alkalmazást. Ha ezek teljesültek. 173x173 pixeles kép. hogy három speciális képfájl található benne:    az ApplicationIcon. amit az alkalmazásunk indulásakor. akkor nagy valószínűséggel semmilyen probléma nem lesz a piactér publikálási folyamata során sem. a Background. felesleges a SplashScreenImage. amely az alkalmazás ikonja. Célszerű minden kész alkalmazásnál lefuttatni ezeket a teszteket! Időt spórolhatunk vele. ha az alkalmazásunk nagyon gyorsan be tud töltődni.Publikálás 12-17 ábra: Monitored Tests (Marketplace Test Kit) Manual Test A tesztnek van egy manuális része is. akkor Failedre (12-18 ábra)! 12-18: Manual Tests (Marketplace Test Kit) Ha ezeket a teszteket minden publikálás előtt elvégezzük. hogy ha lassan töltődik be valamiért az alkalmazás. amely a fő képernyő csempéi között jelenik meg.

Ebben a részben áttekinthetjük. melyek ezek.microsoft. akkor annak szintén a Content értéket kell felvennie! Persze nem muszáj ezeket a neveket használnunk.png 173x173 PNG <Deployment xmlns="http://schemas. a beállításokat a WMAppManifest.xaml"/> </Tasks> <Tokens> <PrimaryToken TokenID="MarketPlaceSampleToken" TaskName="_default"> <TemplateType5> <BackgroundImageURI IsRelative="true" IsResource="false">Background. akkor láthatjuk. Marketplace az alkalmazáshoz. de még nem néztük meg közelebbről a piactérre jellemzőeket. sőt azt is.12. Az alkalmazásunkból elindíthatjuk a Marketplace alkalmazást.0" Genre="apps. Ehhez négy taszk áll a rendelkezésünkre:   MarketplaceHubTask MarketplaceDetailTask 314 . Leírhatjuk.1"> <App xmlns="" ProductID="{1b0f2313-d341-4b64-b7b7-88caa0ed57b1}" Title="MarketPlace Sample" RuntimeType="Silverlight" Version="1.png</BackgroundImageURI> <Count>0</Count> <Title>MarketPlace Sample</Title> </TemplateType5> </PrimaryToken> </Tokens> </App> </Deployment> Ha jól megnézzük ezt a fájlt.png Large app tile Background. File Méret (Pixel) Fájl típus PNG Project File Példa Small app icon 62 x 62 ApplicationIcon.normal" Author="Turóczy Attila" Description="Sample description" Publisher="Livesoft"> <IconPath IsRelative="true" IsResource="false">ApplicationIcon.xml fájlban testreszabhatjuk. és hogyan is használhatjuk fel azokat.com/windowsphone/2009/deployment" AppPlatformVersion="7.0. hogy itt az alkalmazásunkkal kapcsolatban speciális tulajdonságokat adhatunk meg.0. milyen legyen a háttere (Background) vagy éppen az ApplicationIcon neve és elérhetősége. hogy melyik lapot töltse be az alkalmazás indulásakor. Marketplace Task Az előző fejezetekben már foglalkoztunk a launcherekkel. hogy mi legyen az alkalmazás címe (Title).png</IconPath> <Capabilities> <Capability Name="ID_CAP_CONTACTS"/> <Capability Name="ID_CAP_APPOINTMENTS"/> </Capabilities> <Tasks> <DefaultTask Name ="_default" NavigationPage="MainPage.

detailTask. és közvetlenül erről az oldalról le is töltheti a felhasználó az alkalmazást. képernyőképeit. 315 . hogy melyik típust szeretnénk megjeleníteni: MarketplaceHubTask hubTask = new MarketplaceHubTask().ContentType = MarketplaceContentType. Ezzel a launcherrel például megtehetjük azt. Kezdjük a legegyszerűbb taszkkal. akkor a kiválasztott program részletes nézete töltődik be. azt a MarkerplaceDetailTaskkal tehetjük meg (12-20 ábra).Applications.ContentType = MarketplaceContentType. hubTask. hogy az ingyenes próba változatban folyamatosan reklámozzuk az általunk írt alkalmazásokat. Itt meg kell adnunk a hivatkozni kívánt alkalmazás egyedi azonosítóját. ahol láthatjuk az alkalmazás logóját. detailTask. MarketplaceDetailTask detailTask = new MarketplaceDetailTask().ContentIdentifier = "078656ae-9f35-45bb-84b8-2f9270bbdd67".Marketplace Task   MarketplaceReviewTask MarketplaceSearchTask Alapvetően két különböző helyen tudunk keresni: az alkalmazások és a zenék között – ezt a ContentType tulajdonságnál tudjuk megadni. detailTask. és amikor betöltődik.Show(). a MarketplaceHubTaskkal (12-19 ábra)! Ezzel egyszerűen megnyithatjuk a Marketplace alkalmazást (Marketplace Hubot).Show(). leírását. hubTask. a Content Type értékével pedig meghatározhatjuk.Applications. 12-19 ábra: Marketplace Hub Ha viszont egy meghatározott alkalmazás Marketplace oldalát szeretnénk betölteni.

MarketplaceSearchTask searchTask = new MarketplaceSearchTask(). akkor maximum háromszor indíthatja el a felhasználó az alkalmazást.SearchTerms = "Auto". hogy megvennék azt. hogy az IsTrial értéket megfelelően beállítja. vagy időhöz köthetjük. és ezt bekapcsoljuk. ugyanis az IsTrial metódus eredetileg false értékkel tér vissza. az IsTrial értéke false lesz. utána leállítjuk. ami lehetőséget biztosít arra. Akár a saját magunk által készített alkalmazásokra is rákereshetünk. Trial Mode Amikor alkalmazásunkat a piactérre publikáljuk. Például megtehetjük azt. searchTask. hogy célszerű lenne megvásárolnia azt. és a mi dolgunk. Marketplace 12-20 ábra: Marketplace Details Task Nagyon fontos. csak akkor tudjuk használni.ContentType = MarketplaceContentType. hogy figyeljük. searchTask. Reklámokat és figyelemfelkeltő üzeneteket is elhelyezhetünk az alkalmazásban. meghatározhatjuk azt.Applications. hogy minél több felhasználó értékelje az alkalmazásunkat (előnye: előrébb kerül a Top listában)! Ezt elősegíthetjük a MarketplaceReviewTask használatával. ha az alkalmazásunk publikálva van. hogy annak van-e próba (trial) üzemmódja. és abban alkalmazásokat.Show(). Abban az esetben. jelezve a felhasználónak. A trial mód szimulálása fejlesztési időben viszonylag problémás. Ha van.Marketplace.LicenseInformation(). ezért fejlesztési időben ezt szimulálnunk kell. nem tehetjük meg például. A korlátozások kialakítása és kreatív megoldása a mi feladatunk. és fizikai készülékről indítjuk el az alábbi kódot: MarketplaceReviewTask reviewTask = new MarketplaceReviewTask(). searchTask. Annyiban különbözik ez a verzió a teljestől. akkor a feltöltött alkalmazásunkat szabadon letölthetik a felhasználók anélkül. ha megveszi a felhasználó az alkalmazást. egyszerűen csak megnyithatjuk az adott alkalmazás Review oldalát. var license = new Microsoft. hogy megnyissuk a Marketplace kereső ablakát. az IsTrial értéket. vagy figyelmeztetjük a felhasználót a vásárlásra.IsTrial(). reviewTask. a Marketplace csak annyiban nyújt segítséget.Phone. hogy előre meghatározott értékelést adjunk meg. hogy milyen módon korlátozzuk az alkalmazás funkcióit. var isInTrialMode = license. Az utolsó Marketplace-hez kötődő taszk a MarketplaceSearchTask. Ennek a taszknak nincs speciális paramétere. Ennek kezelésére a DEBUG 316 .12. hogy az alkalmazáslicenc IsTrial értéke true lesz. és ha az igaz. zenéket vagy podcastokat keressünk.Show(). Ezt a funkciót nem tudjuk kipróbálni az emulátorban.

hogy milyen módban fut az alkalmazás. Ahhoz.IsTrial(). a nekünk tetsző módon. és hogy hogyan kell próbamódú alkalmazást készíteni. Ha DEBUG módban indítjuk az alkalmazást. akkor ez a szimbólum eltűnik: public class ApplicationLicense { public bool IsInTrialMode { get { #if !DEBUG var license = new Microsoft. hogyan tudunk publikálni a Marketplace-re. hogy módosítsuk a fordítási módot. akkor az IsTrial metódustól kérdezzük le.Marketplace. a Visual Studio Toolbar-ján kell beállítanunk. Azt is megvizsgáltuk. a Windows Phone egyik központi szereplőjével. Megnéztük azt. Ha nem. #else return true. és milyen feltételeket kell alkalmazásunknak teljesítenie ehhez.Phone. hogy az alkalmazás nem DEBUG módban indul-e. akkor mindig true értéket fogja visszaadni az IsInTrialMode tulajdonság.Összefoglalás szimbólumot tudjuk felhasználni: ha Realease módban fordítjuk le az alkalmazást. Ebben az esetben az false értékkel tér vissza. 12-21 ábra: Release és Debug mód közötti váltás A feltételeket persze szabadon módosíthatjuk. #endif } } } Itt megvizsgáljuk.LicenseInformation(). hogy milyen módon szeretnénk fordítani (12-21 ábra). 317 . Összefoglalás Ebben a fejezetben megismerkedtünk a Marketplace-szel. return license. hogyan tudjuk a készülékünk fejlesztői zárolását feloldani. hogy milyen Marketplace taszkok állnak a rendelkezésünkre.

.

hogy a Windows Phone 7 platform Silverlight implementációja hogyan segít szembeszállni ezzel a kihívással! A tipikus teljesítmény-problémákról Míg az átlagember sokszor csak annyit tud mondani. Nézzük tehát. Az asztali gépen valószínűleg észre se vennénk 300ms késleltetést a kattintás és a szoftver reakciója között. szintén az elmúlt évezred végéről származó grafikus kártya. hogy a Windows Phone felhasználók elvárásai igen magasak – az egyik legfeltűnőbb és legtöbbet emlegetett pozitívum a platformmal kapcsolatban. bájtokkal és memóriakezeléssel – az adatbázisokat és sokszor még a vezérlési folyamatot is grafikus eszközökkel hozzuk létre. mint ahogy a felhasználók sem. A teljesítmény növelése lehetővé teszi.13. egyre jobban tudnak minket szolgálni – rövidebb várakozási idővel. Ami a GPU-t illeti. A CPU egymagos. 2010-re már nem elfogadható. Abban viszont biztosak lehetünk. (Splash screen-nel 20 másodpercünk van az első képernyő megjelenéséig). Ez a mobil fejlesztés egyik legnagyobb kihívása. Az érintőképernyő közvetlen modellel váltja fel az egér közvetett interakciós modelljét – most már a saját ujjunkkal érintjük meg és mozgatjuk a képernyőn megjelenő dolgokat! Ez nagyszerű. sőt.  319 . már üzleti alkalmazásoknál is megjelenő animációkkal. ami tíz éve csak az asztalon fért el. És a való világban a fizikai tárgyak nem 5-10 fps-el (frame per second – képkocka per másodperc) mozognak. nem kell minden egyes projektnél újra feltalálnunk a kereket. A felhasználók mára elvárnak egy bizonyos szintű felhasználói élményt – ami 2000-ben még jó volt. Mi. gazdagabb grafikával. egy 600 MHZ-en futó Pentium III-al állítható párba (1999-ből). Egy kétéves Intel Core 2 processzor kb. Lassú betöltődés: Az alkalmazás indítása után senki nem szereti. De hát mihez kezdtünk ezzel az elképesztő számítási erővel? Nos. amíg az ténylegesen használható nem lesz. Kisebb csoda. ha a betöltődés 5 másodpercnél tovább tart és nincs ún. a fejlesztők ugyanannyira nem kívánunk tíz évet visszalépni az időben. hogy fejlettebb. több segítséggel a munkához. ha sokat kell várni addig. akadozása. a Snapdragon processzor körülbelül azt a teljesítményt nyújtja. hogy mikortól zavarja egy animáció darabossága. A fejlesztői élmény is rengeteget változott – főleg a Microsoft világban. és a mobil platformoktól is az asztali vagy webfejlesztéskor megszokott produktivitást (termelékenységet) várjuk el. 30-szor múlja ezt felül. a fejlesztőknek ennél pontosabban kell ismerni a tüneteket ahhoz. hogy a mai felhasználók megnövekedett igényeit kell fejlesztőként kielégítenünk. és ha odébb lökjük őket. az OS meg is öli azt. Immár a . magasabb szintű eszközöket használjunk a fejlesztés során – legtöbbször már nem törődünk bitekkel. Az érintőképernyők megjelenésével az elvárások tovább nőttek. De ha belegondolunk abba. Lássuk. splash screen az alkalmazásban. Sőt. de emiatt a „dolgoknak” a való világbeli tárgyakhoz hasonlóan kell reagálniuk.NET keretrendszer negyedik generációját használjuk. a telefon ereje igencsak kevésnek tűnik. leginkább a felhasználói élmény javítására fordítottuk! Ahogy a számítógépek egyre gyorsabbak lettek. Teljesítmény Egy asztali vagy akár laptop számítógéphez hasonlítva a telefon igencsak gyenge teljesítménnyel bír. számítási teljesítményben kb. nem várnak még pár tized másodpercet mielőtt elkezdenének mozogni. de egy érintőképernyőn ez már igen zavaró lehet. hogy a zsebünkben hordozhatjuk azt. A kliens-szerver kommunikáció immár a keretrendszer része. hogy milyen finom (silky smooth) animációkkal kényeztet el minket. mint egy. hogy „ööö… lassú”. és hiába fut 1GHz-en. hogy a problémákat kezelni tudja. nagyobb felbontással. A telefon akkumulátora egy asztali gépet csak pár percig tudna ellátni árammal. milyen jelenségek tartoznak a teljesítmény-gondok témakörébe:  Akadozó animációk: Mindenkinek más az ingerküszöbe.

azt gondolva. mert a CPU önmagában nem lenne elég erős nagyfelbontású videók lejátszására. így elkerülhető a pixelesedés.de megfelelő használatával mégiscsak megteremthető a 3D illúziója. A program az első lépésben egy csillagmezőt jelenít meg. Visual Studio-ban hozzunk létre egy új C# nyelvű Windows Phone alkalmazást CpuAndGpu néven. a layout (elrendezés) számítása. Ez nem igazi 3D. csillagok… Illusztrációként készítsünk egy egyszerű programot – ezen fogjuk megvizsgálni a fenti teljesítményproblémákat. mint a nagytestvérei az asztali gépeken – háromszögeket képes a térben elhelyezni és megjeleníteni. mennyi idő alatt jön meg a válasz? Ha nincs semmi visszajelzés. még az is lehet. mivel nem testekről csak lapos textúrákról beszélünk . Perspektivikus torzítás – a textúra elforgatása 3D-ben. ha tudunk pár dolgot a GPU-ról. A mozgatás is ennek segítségével történik (a pozíció változtatása után a következő képkockában (frame-ben) újra egymásra helyeződnek a textúrák.5D. és a MainPage. A GPU hasonlóan működik. egymás fedő vagy félig átlátszó textúra (bittérkép) egymásra helyezése. Így viszont marad ideje egyéb feladatokra (pl. és természetesen a programunk futtatása is. a legtöbbször észre sem vesszük. utasítások és azokból szőtt algoritmusok végrehajtására. ábra). De hogy lesz egy vezérlőből (pl. hogy a GPU textúrákat. A GPU képes átméretezéskor az éleket elmosni. A GPU segít levenni a CPU válláról a terhet az alábbi műveletek esetén:  Kompozíció – két vagy több. amire nem ideális. (Komolyabb 3D alkalmazást inkább XNA-val készítsünk).      Figyelmes olvasóknak feltűnhetett. hogy nem érzékelte a telefon az érintést! Görgetés közben üres területek jelennek meg (blanking): Egy hosszú listát gyorsan végigpörgetve üres területeket látunk – a kirajzolás nem tud lépést tartani a görgetéssel. több millió darabot másodpercenként. Ilyenek például a grafikai műveletek. Az általunk írt program a CPU-n fut. a vezérlők létrehozása.13. mint ahogy a SurfCube 3D Browserben is történt (lásd 13-14. Elfogy a memória: Sokszor a felhasználó csak az alkalmazás lefagyását vagy hirtelen kilépését tapasztalja. stb). feliratok elhelyezésére. Négyszögletes vágás – a textúrákból a GPU is képes vágást készíteni (clip). Forgatás – egy bittérkép elforgatása Átméretezés – nagyítás vagy kicsinyítés. mert a Microsoft nemes egyszerűséggel visszadobja a túl sok memóriát használó alkalmazásokat…   A CPU és a GPU feladata A CPU általános feladatokra alkalmas processzor – képes matematikai műveletek elvégzésére. amennyiben a vágó geometria téglalap alakú. seek bar megjelenítésére. Teljesítmény  Hosszú válaszidő (reszponzivitás): Ha megnyomtunk egy gombot a programban. A CPU (processzor) egy remek kis jószág. A CPU feladata még a XAML értelmezése.xaml. vagy a videó dekódolás. Csillagok. egy gomb) textúra? Ezt a folyamatot renderelésnek vagy raszterizálásnak hívják. Videó dekódolás – a Windows Phone-on a videó dekódolást és átméretezést dedikált hardver végzi – ez jó hír. Fejlesztőként legkésőbb a Marketplace ellenőrzés során találkozunk ezzel a jelenséggel. Ezért a telefonokban egy GPU (grafikus processzor) is található. Azonban a teljesítmény-problémák orvoslásához már jó. inkább 2. bittérképeket manipulál.cs -be írjuk be az alábbiakat: 320 . hogy újra meg újra megnyomjuk a gombot. de van pár dolog. Szerencsére Windows Phone fejlesztőként nekünk nem kell a GPU-val ilyen alacsony szinten foglalkozni – sőt. és a javításuk módját. és a CPU végzi. hogy a Silverlight motor a GPU-t dolgoztatja.

Phone.ElapsedMilliseconds + " ms"). RoutedEventArgs routedEventArgs) { MessageBox. 0). Ha elindítjuk a programot az emulátorban. ContentPanel. CreateStarField(100).NextDouble()*3. ellipse. 0. Microsoft. csillagok… using using using using using using System.Children.Start(). A program működése igen egyszerű.Width = size.Add(ellipse).Next(607). i++) { Ellipse ellipse = new Ellipse(). System. // Constructor public MainPage() { stopwatch = new Stopwatch().Shapes.jpg fájlt.Fill = new SolidColorBrush(Colors.Media.Show("Startup time: " + stopwatch. i < numOfStars.Windows. x. ellipse.Top. ami az indulás óta eltelt ezredmásodperceket méri. A MainPage osztály létrehozása után elindítunk egy stoppert.Diagnostics.Margin = new Thickness(x. } public void CreateStarField(int numOfStars) { Random x = new Random().Next(456).Left.Windows. System. A stopper elindítása után az InitializeComponent függvény a XAML-ben leírtakat értelmezi.White). System.Csillagok.Windows.Width. } private void OnLoaded(object sender. ellipse. Loaded += OnLoaded. a 13-1 ábrán látható eredményt kapjuk.HorizontalAlignment = HorizontalAlignment. double size = x.Height = ellipse.Controls. } } } } A Solution Explorer-ben töröljük ki a SplashScreen. for (int i = 0. System. ellipse. majd az általunk írt CreateStarField metódus a paraméterként kapott numOfStarts számú véletlen elhelyezkedésű és méretű csillagot jelenít meg a képernyőn. namespace CpuAndGpu { public partial class MainPage : PhoneApplicationPage { private Stopwatch stopwatch. ellipse. 321 . ellipse. InitializeComponent(). stopwatch.VerticalAlignment = VerticalAlignment. A Loaded eseménykezelőjében (ami a MainPage megjelenése után kerül meghívásra) egy MessageBox-ban kiírjuk az induláshoz szükséges időt.

indítsuk el ott is! Egy első generációs LG Optimus 7 telefonon 558 ms alatt indul el az alkalmazás. hanem akár több ezer csillagot szeretnénk megjeleníteni? A mérések eredménye jól látszik a 13-2. ábra grafikonján: 13-2 ábra: csillagok kirajzolási ideje emulátoron és telefonon 322 . De mi történik. ha nem csak 100. Teljesítmény 13-1 ábra: 100 csillag.13. 388 ms A programnak azonban a telefonon kell futnia.

Width.HorizontalAlignment = HorizontalAlignment.t.Next(456)). láthatjuk. ellipse. és a teljesítményt arra hangoljuk be! A hagyományos . (double)x.Children.Top és Canvas.TopProperty.SetValue(Canvas. hogy a csillagok kirajzolásakor van lehetőség még a gyorsításra.Next(607). a rendelkezésre álló terület változásait jól kezelő. Nézzük. ellipse.xaml .12.  Lassú betöltődés kezelése A fenti csillagos alkalmazásnál egyértelműen probléma. i < numOfStars. Talán nem tűnik soknak ez a csillagonkénti 0. i++) { Ellipse ellipse = new Ellipse().Height = size.Left. sorral érjük el. 0. hogy nem minden egyes csillagnál egy újabb Dependency Property get-et végrehajtani. A Grid igen rugalmas. hogy hogyan viselkedik az emulátorban! Bár az emulátor rendkívül pontos. ContentPanel.Next(456). double size = x. mivel az alkalmazás nem indult el 20 másodpercen belül. hogy margók helyett a Canvas. mint maga a telefon. ezt mégiscsak egy asztali gép processzorán és videokártyáján teszi. Az ellipszis magasságát ugyanarra az értékre állítjuk. hogy a csillagokat tartalmazó elem egy Grid.Row="1" Margin="12.0"></Canvas> Módosítsuk a kódot is.0"></Grid>--> <Canvas x:Name="ContentPanel" Grid. } } 323 .NextDouble()*3.Fill = new SolidColorBrush(Colors.2 ms.White). (double)x.0.LeftProperty.VerticalAlignment = VerticalAlignment. Ha ezt a sort lecseréljük arra.Height = size. Tapasztalt fejlesztők számára feltűnhet. de egy sok ezerszer végrehajtott ciklus közepén még az ilyen apróságok is számíthatnak.Next(607)). hogy lassan töltődik be a telefonon. Cseréljük hát ki a Grid-et egy jóval egyszerűbb társára. Minden esetben ellenőrizzük az alkalmazás futását egy fizikai eszközön is. ellipse. A fenti kísérletből két fontos tanulságot vonhatunk le.SetValue(Canvas. és így az operációs rendszer „megölte” azt. és ugyanazt az OS-t futtatja. // ellipse.12. Ennek az oka.Lassú betöltődés kezelése A 20000 csillagos értéket telefonon már meg sem tudtuk mérni. és sok mindenre jól használható konténer – ugyanakkor ez a komplexitás nyilván nincs ingyen.Top. hogy ellipse.Height = ellipse. Ne vonjunk le következtetéseket az alkalmazás teljesítményére vonatkozóan abból.Add(ellipse).Width = size.Left tulajdonság állításával kerüljenek a csillagok elhelyezésre: public void CreateStarField(int numOfStars) { Random x = new Random(numOfStars). akkor a telefonon 5000 csillag már 4202 ms alatt megjelenik (szemben az eredetileg mért 4300al). hogy lehet ezen javítani! Az elrendezés (layout) költségeinek csökkentése Figyelmesebben megnézve a MainPage.NET optimalizáló technológiák és a józan ész a Windows Phone fejlesztés során is segítenek. 0). ellipse. // ellipse. x. mint a telefoné. ellipse.Row="1" Margin="12. // ellipse.Margin = new Thickness(x.0. for (int i = 0. mint a szélességét (ami egy véletlen érték) .  Az emulátor performancia-karakterisztikája teljesen más.de ezt a ellipse. egy Canvas-ra: <!--<Grid x:Name="ContentPanel" Grid.

Mi lenne. mint az üres kijelzőt. Ennek az oka az. Figyelem. amíg az első képernyő meg nem jelenik. hogy csak akkor használjunk bonyolult layout rendszereket. a gyerekek számának megváltozása a vizuális fa teljes vagy részleges újraméretezését vonja maga után . így csak a csillagok kirajzolása után fog a gomb az érintésre reagálni. ami el van foglalva a csillagok rajzolásával. A Splash Screen addig látszódik. Ez azonban ne tévesszen meg senkit – az alkalmazás a csillagok rajzolása során nem reagálna az inputra. ha a MainPage.12. annál gyorsabb lesz az alkalmazásunk. a csillagok csak a MessageBox lezárása után jelennek meg. ha a betöltődés után rajzolnánk csak ki a csillagokat? Mozgassuk át a CreateStarField metódust a konstruktorból az OnLoaded eseménykezelőbe: private void OnLoaded(object sender. MessageBox.és minél kevesebb dolgot kell ehhez a CPU-nak végeznie.Row="1" Margin="12. ha az alkalmazás indulása 5 másodpercnél több időt vesz igénybe. Háttérszálak alkalmazása Tegyük hát át a csillagokat egy háttérszálra! Ehhez az OnLoaded eseménykezelőbe kell belenyúlni. hogy a tényleges rajzolás ekkor még nem történt meg..</Button> </Canvas> A gomb megnyomására a gomb inverzbe vált. } Ha így elindítjuk az alkalmazást a telefonon. a Grid-es 4100 ms helyett 3093 ms-ot mértünk! Általában tehát elmondhatjuk.jpg nem tartozik az ízléses kategóriába! A Marketplace előírások meg is követelik a Splash Screen használatát. A Splash Screen másik előnye. ha arra valóban szükség van. hogy a felhasználó – amíg nem vesz a kezébe stopperórát – gyorsabbnak is fogja érezni a betöltődést. és a felhasználói élményt jelentősen lehet javítani hozzáértő módon alkalmazott trükkökkel (lásd később). a fejléc-szöveg villámgyorsan megjelenik.jpg fájlt a WP7 projekt gyökérkönyvtárában és állítsuk a Build Action tulajdonságot a Content értékre! Inicializációs teendők elhalasztása A fenti példaprogramban a betöltést jelentősen lassítja a csillagok kirajzolása.ZIndex="1">I am not doing anything. a felhasználónak sokkal jobb érzés egy ízléses rajzot bámulnia. ha az indulást nem tudjuk 1-2 másodperc alá szorítani.cs-ben elhelyezünk egy gombot: <Canvas x:Name="ContentPanel" Grid. hogy az alkalmazás szinte azonnal elindul. két dolgot vehetünk észre. viszont az üzenet 3093 helyett már csak 2876 ms-ot mutat. Splash Screen A Splash Screen a program indítását követően megjelenő egész képernyős ábra. Teljesítmény 5000 csillaggal futtatva az alkalmazást. mivel a UI szál a csillagokkal van elfoglalva. Ezt könnyen ellenőrizhetjük.Show("Startup time: " + stopwatch.0. Azonban ez a raszterizálás az UI szálon történik.0"> <Button Canvas. Splash Screent igen könnyű az alkalmazásba építeni – helyezzünk el egy SplashScreenImage. Minden átméretezés.. hogy a stopperes üzenet megjelenésekor még nem látszanak a csillagok. A másik jelenség az. illetve egy új. BGCreateStars metódust létrehozni: 324 . A Splash Screen nem gyorsít a beöltődésen – ugyanakkor. mivel valami történik a kijelzőn.xaml. Ezt az érzést szubjektív teljesítménynek hívjuk. a WP7 alkalmazássablonban található SplashScreen. RoutedEventArgs routedEventArgs) { CreateStarField(5000).13. Az egyik.ElapsedMilliseconds + " ms").

A programot futtatva már igen kellemes felhasználói élményben van részünk: az indulási idő minimális. szinte olyan.BeginInvoke(() => CreateStarField(10)).ElapsedMilliseconds + " ms"). MessageBox. t. Ehhez a projektben el kell helyezni a fájlt (pl. a program azonnal reagál a gombnyomásra. 13-3 ábra: A starsBG. de mi van. } } A BGCreateStars 500-szor lefuttatja a CreateStarField metódust 10 csillaggal. hogy fusson. private void BGCreateStars() { for (int i = 0. A CreateStarField azonban az UI szálon kell.Sleep(30). így nincs értelme.Start().Lassú betöltődés kezelése private void OnLoaded(object sender. Előre elvégzett munka Ez mind szép. A csillagok pedig szépen lassan jelennek meg. // // } CreateStarField(5000). ha nekünk a teljes csillagmezőre van szükségünk. Ezért az UIDispatcher. a Copy to Output Directory pedig Copy if newer. i < 500.ben pedig a ContentPanelt a következőre cseréljük: 325 .png néven). és minden futás után pihen 30 ms-ot. t.BeginInvoke híváson keresztül kell elérni a CreateStarField metódust. mert az még a csillagok kirajzolása előtt megjelenne. Thread.Name = "Stars".Show("Startup time: " + stopwatch. mintha az alkalmazás egyesével rajzolgatná őket. mert az UI-t manipulálja. A fentiek alapján módosított alkalmazásból kivettük a MessageBox hívását is.png A MainPage. ábra). starsBG. A MainPage. RoutedEventArgs routedEventArgs) { Thread t = new Thread(BGCreateStars). a betöltődés után azonnal? Ebben az esetben is van megoldás – egyszerűen készítsünk egy screenshotot a kívánt csillagmezőről. i++) { UIDispatcher.cs tartalmát teljes egészében visszaállíthatjuk az eredetire (a konstruktorban egy InitializeComponent hívás marad csak).xaml. és a tulajdonságait beállítani: a Build Action legyen Content. és tegyük be a ContentPanel háttérképének (13-3.xaml .

13. Teljesítmény

<Canvas x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Canvas.Background> <ImageBrush Stretch="None" ImageSource="/starsBG.png"/> </Canvas.Background> <Button Canvas.ZIndex="1">I am not doing anything...</Button> </Canvas>

Tádááám! Az alkalmazás fél másodpercen belül elindul még 5000 csillaggal is! Ha mégis szükségünk lenne a véletlenszerű csillagmezőre, egyszerűen készítsünk 10 különböző képet, és azok egyikét állítsuk be kódból háttérnek.

Kis összefoglalás
A fenti alapelvek persze „valódi” alkalmazásoknál is használhatók. Az iniciális teendők elhalasztására jó példa a SurfCube 3D Browser alkalmazás 4.0 változata. Mivel az app indulása túllépte az 5-6 másodpercet, egyre több felhasználó panaszkodott. Volt, aki egyenesen azt gondolta, hogy a Splash Screen az ő bosszantásukra van ott, és csak azért tettük oda, mert tetszett nekünk a logó. Ezt mind el is fogadta volna, de az már felháborította, hogy az alkalmazás megvásárlása után is túl sokáig volt látható a Splash Screen! A SurfCube 4.0-ban ezért a kocka oldalait már eleve „Collapsed” állapotban töltjük be. Az első forgatáskor váltunk át innen „Visible”-re. Ez kicsit kényelmetlen talán (bár némi loading… felirattal és animációkkal ellensúlyoztuk a dolgot), de lehetővé tette, hogy az indulás 3.5 másodpercre rövidüljön. A másik dolog, ami sokat segíthet, ha a ritkán használt funkciókat külön assembly-be tesszük. Ekkor, amíg az assembly-re nem történik hivatkozás a kódban, azt nem tölti be az operációs rendszer. Az előre elvégzett munkára pedig jó példa a „Névnap” alkalmazásom. Itt egy SQL CE adatbázis tartalmazza a névnapokat. Ez az adatbázis egy szöveges fájl alapján, az első futtatás során jön létre – a lapkák és az alkalmazás későbbi futása már az SQL CE-t használják. Még jobb megoldás ilyen esetben, ha a (csak olvasásra szánt) SQL adatbázist már a fejlesztés során a XAP fájlba helyezzük, így a legelső futás is gyors lehet.

Akadozó animációk okai, megoldása
Windows Phone Silverlightban többféle módon lehet animációt létrehozni. Kezdjük a legritkábban használatos, de a teljesítmény szempontjából a legkritikusabb megoldással – az ún. procedurális animációval! Az animációval azt akarjuk szimulálni, hogy mit lát egy részeg, sokszemű űrhajós, akivel szembe jön a csillagos űrben egy TIE figther. Ehhez először is elkészítettem egy TIEFighter.xaml user controlt. Ennek kódját felesleges lenne ide bemásolnom – elérhető a könyvhöz tartozó letölthető anyagok között (13-4 ábra).

13-4 ábra: a TIEFighter.xaml Expression Blend-ben

326

Akadozó animációk okai, megoldása A procedurális animáció lényege, hogy minden képkockában (frame) újraszámoljuk az objektumok helyzetét. A teljes kód a fejezethez mellékelt kódban elérhető, itt csak a lényeget emelném ki. Ahhoz, hogy a ProceduralAnim példa induljon el, a Properties/WMAppManifest.xml fájlban a DefaultTask NavigationPage értékét módosítani kell:
<DefaultTask Name ="_default" NavigationPage="ProceduralAnim.xaml"/>

Maga az animáció a ProceduralAnim.xaml.cs fájlban, a CompositionTargetOnRendering eseménykezelőben történik. Ez a CompositionTarget osztály Rendering eseménye, amely minden alkalommal lefut, amikor az UI szál egy új képkocka rajzolására készül. Az eseménykezelő a következőképpen néz ki:
private int frameCount = 0; private void CompositionTargetOnRendering(object sender, EventArgs eventArgs) { if (frameCount >= 100) frameCount = 0; for (int i = 0; i < Ties.Count; i++) { var tieFighter = Ties[i]; CompositeTransform tr = (CompositeTransform) tieFighter.RenderTransform; tieFighter.Opacity = frameCount/100.0; double scale = 1 + frameCount/100.0; tr.ScaleX = scale; tr.ScaleY = scale; tr.Rotation = frameCount / (i+1.0); } frameCount++; }

A Ties egy TIEFighter objektumokat tartalmazó lista. A fenti függvény nem csinál mást, mint végigmegy az összes TIE Fighter-en, és mindegyiknek átállítja az átlátszóságát, méretét és elforgatását. A 13-5 ábra mutatja, hogy három TIE Fighter esetén (vagyis ha a részeg űrhajósnak három szeme van nyitva) milyen animációt láthatunk.

13-5. ábra: három TIE fighter animációja Az ábrák jobboldalán látható számok az ún. frame rate counter-ek – érdemes itt kitérni rájuk. 327

13. Teljesítmény

Frame Rate Counters
Az App.xaml.cs fájlban a konstruktorban a következő sorokat találhatjuk:
// Show graphics profiling information while debugging. if (System.Diagnostics.Debugger.IsAttached) { // Display the current frame rate counters. Application.Current.Host.Settings.EnableFrameRateCounter = true; // Show the areas of the app that are being redrawn in each frame. //Application.Current.Host.Settings.EnableRedrawRegions = true; // Enable non-production analysis visualization mode, // which shows areas of a page that are handed off to GPU with a colored overlay. //Application.Current.Host.Settings.EnableCacheVisualization = true; // Disable the application idle detection by setting the UserIdleDetectionMode property of the // application's PhoneApplicationService object to Disabled. // Caution:Use this under debug mode only. Application that disables user idle detection will continue to run // and consume battery power when the user is not using the phone. PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled; }

Láthatjuk, hogy még két eszköz áll rendelkezésre a grafikai teljesítmény analizálásához - a redraw regions (újrarajzolt területek) és a cache visualization (cache vizualizáció). Ezekről később lesz szó. A fenti sorok határára, ha egy alkalmazást debug módban indítjuk (F5-el), a képernyő oldalán megjelenik néhány számláló (ezeket hívjuk Frame Rate Counter-eknek), amint az a 13-6 ábrán is látható.

13-6. ábra - Frame Rate Counters Mit is jelentenek ezek a számok? Az egyes Frame Rate Counterek jelentését az alábbi táblázat foglalja össze, amely a számokat balról jobbra sorolja fel: Counter Composition szál frame rate Magyarázat Azt mutatja meg, hogy másodpercenként hányszor kerül a képernyő frissítésre. Ha ez a szám 60-nál (egyes eszközökön 50nél) kisebb, az animációk veszítenek folyamatosságukból. Ha 30 alá csökken, a felhasználók is észreveszik a problémát, és a szám pirosra vált. Az UI szál az, ahol a raszterizáció (renderelés) történik, és ahol az általunk írt kód fut (hacsak nem indítunk új szálat). Ezért, az alacsony UI szál frame rate azt jelenti, hogy az alkalmazás nem

UI szál frame rate

328

Akadozó animációk okai, megoldása

Counter

Magyarázat válaszol időben az inputra. Előfordulhat, hogy ekkor a Composition szálon és a GPU-n továbbra is folyamatosan futnak az animációk, de a felhasználói élményt igencsak rosszul érinti, ha az UI szálat leterheljük. Azt mutatja, hogy a textúrák mennyi videó- és rendszermemóriát használnak Az explicit felületek számát mutatja, amellyel a GPU dolgozik. Ha egy FrameworkElement példányon a CacheMode tulajdonságot BitmapCache értékre állítjuk, vagy a Composition szálon futtatunk egy animációt, a számláló értéke megnő. A GPU által használt implicit felületek számát mutatja (lásd később) A GPU-k egyik legfontosabb teljesítmény-mutatója a Fill Rate. A GPU-k egy másodperc alatt csak bizonyos számú pixelt tudnak megrajzolni. A Windows Phone 7 esetén a kijelző 800x480 pixelt tartalmaz, és ezt egy első generációs hardver GPU-ja képkockánként kb. 2.5-szer tudja megtölteni. A Fill Rate 1-es értéke azt jelenti, hogy a GPU egy képernyőnyi pixelt rajzol fel frame-eknént. Ha ez a szám 2.5 fölé emelkedik, a GPU szűk keresztmetszetté válik. Ha a számláló 3 fölötti értéket mutat, pirossá válik, mert az animációk elvesztik folyamatosságukat a frame rate csökkenésével. Figyeljünk oda arra, hogy ha az alkalmazásnak megadunk egy háttérszínt, ez önmagában 1-el növeli a Fill Rate-et, mert a GPU-nak először ezt a hátteret kell megrajzolnia. Ezért célszerű a hátteret átlátszónak hagyni, ha a rendszer témáját használjuk.

Textúra-memória használata Explicit felületek (surface) száma

Implicit felületek (surface) száma Fill Rate

A fentiek alapján látható, hogy három vadászgéppel az emulátor kb. 15 FPS-el tudja futtatni az UI szálat. (A telefonom12-13 fps-t mutat). A problémát nem a magas Fill Rate okozza, mivel az fixen 1. A telefon még 1 TIE esetén is könnyen lemegy 20-30 FPS környékére. Mi lehet ennek az oka?

Redraw Regions
Ha bekapcsoljuk a Redraw Region opciót, hozzáértő szem számára rögtön nyilvánvalóvá válik a probléma. A 13-8 ábrán látható, hogy mit okoz a bekapcsolása.

329

13. Teljesítmény

13-8. ábra: Redraw Regions A Silverlight a nagyobb sebesség érdekében spórol a rajzolással. Így csak azokat a területeket rajzolja újra, amelyek változnak két képkocka között. A Redraw Region ezeket az újrarajzolt területeket minden egyes frame esetén különböző színnel megfesti (ez némi CPU időbe telik, így ne végezzünk FPS méréseket, ezzel az opcióval). Az ábrán jól látszik, hogy a képernyő jelentős részét újra kellett rajzolni, ahogy a TIE Fighter elhalad a csillagok fölött és a kezelőszervek alatt. Ráadásul maga a TIE Fighter is újrarajzolásra kerül, mivel folyamatosan változik a mérete és az elforgatása. Ezt a raszterizálást minden frame-ben a CPU végzi – így nem csoda, ha nem képes másodpercenként 20-25-nél többször új képkockát készíteni. Korábban említettem, hogy a GPU sok olyan feladatot képes hatékonyan ellátni, amire itt is szükség van. Kompozíció, forgatás, átméretezés, stb… hát akkor:

Használjuk a GPU-t!
Az Enable GPU Acceleration gomb bekapcsolásával a helyzet drámaian megváltozik. A Redraw Region abbahagyja az őrült villódzást. 3 vadászgép esetén a telefon még érezhető lassulás nélkül animál. Még tíz TIE Fighternél sem esik 20 FPS alá a sebesség. Ugyanakkor az emulátor egy erős videokártyával mindennemű lassulás nélkül elvisel tíz vadászgépet, de hát az a videokártya ugye egész más kategória, a Call Of Duty MW 3-ra van méretezve… Mi is történik ilyenkor?

330

Akadozó animációk okai, megoldása

private void enableGPU_Click(object sender, RoutedEventArgs e) { foreach (var fighter in Ties) fighter.CacheMode = GetTIECacheMode(); } private CacheMode GetTIECacheMode() { bool enabled = enableGPU.IsChecked.Value; return enabled ? new BitmapCache() : null; }

A TIEFighter vezérlők CacheMode tulajdonságát állítjuk attól függően, hogy a GPU gyorsítást a felhasználó be- vagy kikapcsolta éppen. Kikapcsolt esetben null értéket kap, míg bekapcsolva a BitmapCache osztály egy új példányát. A BitmapCache kifejezés mindent el is mond arról, hogy mit jelent a GPU gyorsítás. Azt jelenti, hogy az adott UIElement raszterizált változata a GPU-ban eltárolásra kerül (cache). Ezután a GPU végzi az így tárolt textúra mozgatását, átlátszóságának változtatását, a többi textúra alá- vagy fölé helyezését, forgatását, átméretezését, perspektivikus torzítását, vagy akár négyszögletes vágását (clipping). Amennyiben az így eltárolt elem textúrája változik (pl. más színe lesz), akkor a Silverlight Runtime automatikusan frissíti a GPU textúra-memóriájában az elemhez tartozó képet. Ez persze azt is jelenti, hogy bizonyos animációk gyorsabban futnak, mint mások. A CPU animálja pl. a nem téglalap alakú vágásokat, a szín-animációkat, a layout-ot, gradienseket, stb. Ha ilyen animációkat használunk, tegyük azt inkább kis méretben – így a CPU-nak nem kell annyi pixelt átszámolnia, és így fenntartható a magas FPS érték. A GPU működésének nyomon követésére még egy opció szolgál, ismerjük meg most ezt!

Cache vizualizáció
A cache vizualizáció opciót bekapcsolva a 13-9 ábrán látható eredményt kapjuk.

13-9: ábra: cache vizualizáció és GPU gyorsítás

331

Ha ezt megnyomjuk. Valóban. és a 2-es érték mutatja a számlálók között.xml fájlban a DefaultTask-ot: <DefaultTask Name ="_default" NavigationPage="StoryBoardAnim.xaml"/> Ha így elindítjuk az alkalmazást. a telefon szépen be is pirosította nekünk. Így nyomon követhető az. Ez csak GPU használatával lehetséges – amit mi sehol nem kapcsoltuk be. az UI szál szóhoz sem jut: a gomb „benyomva” marad jóval az elengedése után is (1310 ábra). A Fill Rate 11. hogy bár nem adtuk meg a háttérképnek és a kezelőszerveknek a BitmapCache értéket. De akármennyi trükközést csinálunk is. és félig átlátszóvá tesz minden textúrát. Ezeket a felületeket implicit surface-nek nevezzük.xaml fájlban található – sőt néhány Easing-gel megbolondítva sokkal természetesebb eredményt kapunk. A futtatáshoz a már ismert módon írjuk át a WMAppManifest. StoryBoard-ok segítségével. Semmi háttérszál és egyéb varázslat. bár esetünkben ezen sokat javít az.xaml oldal nem tartalmaz csillagokat. 332 . nem hagytunk időt arra. és 3. Teljesítmény A cache vizualizáció kékkel fest meg.13. Compositor és Input szálak A StoryBoardAnim. így lehetővé válik azok kiküszöbölése. nem vészes Textúrák száma – a GPU jelenleg 12 textúrával dolgozik. azokat a Silverlight automatikusan a GPU-n tárolja. Érdemes megjegyezni. még öt TIE Fighterrel is. amit a GPU megjelenít. mivel a screenshot emulátoron készült. Ebből 10 a TIE Fighter-eké (mindegyikre jut egy). A kódot megvizsgálva azonban láthatjuk. A magas fill rate-et természetesen a sok (és egyre növekvő méretű) vadászgép okozza. hogy ez a megközelítés hosszú másodpercekre teljesen lefoglalja az UI szálat. Fill Rate – A probléma forrása itt keresendő.5 fölött elkezd csökkenni a frame rate. a Silverlight futtatókörnyezete automatikusan bekapcsolja a GPU-t. A legtöbbször nem is kell ezen gondolkozni. mivel előttük és mögöttük cache-elt textúrák találhatók. A fejezet elején leírtakból tudhatjuk. egy a háttéré és egy a kezelőszerveké. amennyiben StoryBoard animációt használunk procedurális helyett. A Fill Rate az új generációs telefonokban az erősebb GPU-nak hála már magasabb értéknél kezd lassítani – azonban még jó darabig figyelembe kell vennünk az első generációs telefonok sebességét. egy jelentős részük kimegy a képernyőről. pár másodperccel később megjelenik a 6000 csillag. Az eredmény a StoryBoardAnim. előbb-utóbb elérjük a hardver teljesítőképességének a határát – 50 teljes méretű vadászgépet már egyik telefon sem fog élvezhető sebességgel mozgatni. Ez igen magas szám − az első generációs telefonokon már 2. És valóban. hogy mire megnőnek. Érdemes újra végigvenni a Frame Rate Counter-eket:    UI és Composition thread FPS – ezek jóval magasabbak a telefonon tapasztalhatónál. Van azonban egy „Add 6000 stars” gomb a képernyőn. Könnyen ellenőrizhetjük ezt az állítást az Enable GPU Vis opció bekapcsolásával – jól látható. Beépített animációk és a GPU A fenti animáció persze jóval egyszerűbben reprodukálható Blend-ben. hogy minden vadászgép saját GPU textúrát kapott. hogy a nem benyomott állapotot kirajzolja. hogy mely felületeket tárolja a GPU. ez ám a kényelem! UI.  A cache vizualizáció megmutatja a feleslegesen használt GPU textúrákat.6 értéke azt jelenti.5 környékén már bántóan elkezd akadozni az animáció. hogy ennek a gombnak az eseménykezelőjében egyszerűen csak meghívjuk a CreateStarField metódust 6000-es számmal. feltűnhet. mivel az UI szál a csillagok kirajzolásával van elfoglalva. így nem engedhetjük meg magunknak az ellustulást. hogy az animáció tökéletesen folyamatos. hogy a GPU minden frame-ben 11. Használt textúra memória – 8 Mbyte.6 képernyőnyi pixelt rajzol ki.

Hosszú válaszidő kezelése 13-10 ábra . Ez és néhány további hangolás a WP7 első kiadásában tapasztalható legtöbb. hogy a UI szál (amely Mango előtt az inputot is kezelte) el volt foglalva a folyamatosan érkező elemek raszterizálásával. 333 . (A mozgatáshoz és forgatáshoz használt RenderTransform a layout után kerül alkalmazásra. vegyük elő az alkalmazás-indítás optimalizálásánál leírtakat. Mondanom sem kell. de újabb érintésre (pl. A legfeltűnőbb probléma a listák görgetésekor jelentkezett – a görgetett lista animációja folyamatos volt. A jó hír. Az elkerülhetetlen várakozást pedig könnyebbé tehetjük. Ha hosszú számítást kell végeznünk. Ha bonyolult UI-t kell megjelenítenünk. használjunk háttérszálakat. Hosszú válaszidő kezelése A hosszú válaszidőnek számos oka lehet. hogy ez igen kellemetlen felhasználói élményt okozott. hogy a fentiekben bemutatott technikák a gyorsabb alkalmazás betöltésre és a folyamatosabb animációk elérésére a legtöbb esetben segíthetnek itt is. amit a Mangóban (WP7. hogy az elemeket újraraszterezze az UI szál. Ez mindaddig így van. hogy az animációk egy külön szálon. rossz válaszidejű szituációt megoldja.5) szerencsére már javítottak a külön szálon futó input-kezelés bevezetésével. a Compositor szálon futnak (és a GPU-n kerülnek megjelenítésre). amíg olyan animációkat alkalmazunk. akár a BackgroundWorker osztály segítségével is. A Mangoban egy új. így az elrendezést nem befolyásolja). amikhez nincs szükség arra. még a gomb is benyomva maradt. esetleg az elrendezés (layout) változása miatt a vizuális fát újra kelljen számolni. és így csak későn észlelte az érintés eseményt.A UI szálat teljesen blokkolja a 6000 csillag kirajzolása. Ennek oka. Ugyanakkor az animáció egy pillanatra sem lassult le a nagy csillaggyártás közben! Ennek az az oka. ha a felhasználót tájékoztatjuk a folyamat állásáról (lásd a szubjektív teljesítmény résznél). harmadik szál is bevezetésre került az input kezelésére. ha a gördülés megállításához megérintettük a kijelzőt) néha csak másodpercnyi késleltetéssel reagált.

mint a tulajdonságot közvetlen állítása (pl. „blanking” – vagyis. Teljesítmény Általános tippek Számos további tipp található a neten. A jpg dekódolása gyorsabb. hogy semmi nincs ingyen – a Grid fejlett layout képességeinek ára.FirstName). ahol érdemes a kód karbantarthatóságából áldozni. A képek dekódolása alapértelmezésben az UI szálon történik. Ez a funkció a leghasznosabb listáknál (pl. A ScrollViewerben (és listákban) az animációkhoz hasonlóan automatikusan GPU cacheelésre kerülnek az elemek. Nincs értelme például órákat ölni abba. implementáljuk az INotifyPropertyChange interfészt az entitásokban. mivel a layout és raszterizáció nem képes lépést tartani a gyors görgetéssel.        Listák Mérvadó vélemények szerint a Windows Phone 7. hogy az alkalmazás indulása 200 ms-al gyorsabb legyen. 334 . gyorsabb lesz annak indulása. ha már nincs rá szükség – még akkor is. Használjunk jpg-t. ami Supermant legyengítette) a listák teljesítménye volt. A legfontosabb annak megértése. hogy a görgetés közben kevesebb legyen az ún. FirstNameTextbox. hanem Content-ként helyezzük az alkalmazásba. de szinten minden esetben érdemes megfontolni a használatát (talán az egyetlen kivétel a Panorama háttere – a Panorama vezérlőt csak a kép betöltődése után érdemes megjeleníteni). a Fill Rate-et 2. mint a png-é. deklaratív UI leírás ára a XAML interpretálásának költsége. mint a Panorama.ProgressIndicator -t (bár ez csak a képernyő tetején jelenik meg).Text = Person. azt nyugodtan megteheted holnap is (lásd a folyamatos csillag kirajzolás az első példákban a gyorsabb alkalmazás-indulás érdekében). az adatkötés rezsije. ha a vezérlő nem látszik a képernyőn! Még jobb. hacsak nincs szükségünk a png átlátszóságára (vagy vonalas grafikákon a jóval kisebb fájlméretre). a könnyű. A CreateOptions="BackgroundCreation" beállításával ez háttérszálra tehető.5 alatt! Ha határozatlan ProgressBar-t (IsIndeterminate=True) alkalmazunk. ahol lehet! Listákban a DataTemplate-eknél ez különösen hasznos lehet. ritka. Adatbázis használatakor definiáljuk a Version oszlopot. amivel a teljesítményt javítani lehet. ha a Mango-ban megjelent SystemTray. Lássunk tehát néhány ilyen tippet a részletes példák mellőzésével:       A Pivot vezérlő gyorsabb. Szerencsére a Mangóban számos javításon esett át a listakezelés.13. Facebook ismerősök listázása). esetleg a Silverlight for Windows Phone Toolkitból a PerformanceProgressBar vezérlőt használjuk. hogy sokat kell számolni az elemek elhelyezésén. A Compositor szálat lehetőleg tartsuk 60 fps körül. és használjunk előre fordított lekérdezéseket (compiled queries). Egyszerűsítsük a layoutot . amikor üres elemek jelennek meg. Ha a képeket nem Resource-ként. hogy meg kell találni azokat a pontokat. Ugyanakkor egy hosszú listában az elemek kirajzolását akár 30ms-al is hasznos lehet megrövidíteni annak érdekében. így megrövidítve a betöltési időt! Az adatkötés lassabb. és többek között a fentebb már említett Input szálnak köszönhetően nagyságrendeket javult az interaktivitása. Az alkalmazásunkat daraboljuk több DLL-re.0 kriptonitja (a zöld ásvány. kapcsoljuk ki ezt a beállítást.használjunk StackPanel-t. hogy ilyen drasztikus változtatásokra van szükség! Az UI szálat hagyjuk szabadon – a hosszabb műveleteket háttérszálon végezzük. Canvas-t Grid helyett. Amit ma megtehetsz. és lehetőleg ugyanitt kommunikáljunk a felhővel is. plusz munkát befektetni a szemmel látható eredmény érdekében. Ne kezdjünk el azonban megszabadulni minden adatkötéstől. A teljesítmény-optimalizálás művészete abban áll.

aminek az ItemTemplate-je tele van „teljesítménygyilkos” elemekkel. ezért üres pixelek jelennek meg). kép (13-11 ábra). ritkán fogunk problémába ütközni. nehezen számolható elrendezés. Egy-két lassú ValueConverter vagy hatalmas képek picire lekicsinyítve. esetleg némi gradiens a háttérben már gondot okozhatnak. Nemegyszer a szubjektív teljesítmény fontosabb a felhasználónak. Egy olyan listát. hogy a könyvhöz készítettem egy „állatorvosi lovat”. jött a meglepetés – nem volt tapasztalható semmi probléma! Az animáció 60 fps-el döngetett. De ha rendeltetésszerűen használjuk a listákat és odafigyelünk a Fill Rate-re. hogy az UI szálnak az újabb elemeket nincs ideje kirajzolni. sok szöveg. Természetesen a Mangóban is lehet rosszul teljesítő listákat készíteni. 13-11 ábra . a lista azonnal reagált a mozdulatokra. 335 . „Blanking” sem volt tapasztalható (az a jelenség. Összetett. mérhető sebességgel. mint a valóságos. amikor olyan gyorsan pörög egy lista.Összetett ItemTemplate Amikor kipróbáltam a telefonon. Szubjektív teljesítmény Szubjektív teljesítmény alatt az alkalmazás sebességének az érzetét értjük. szemben a valódi.Szubjektív teljesítmény Olyannyira így van ez.

Teljesítmény Már a fejezet elején is volt arról szó. hogy az interakció közvetlensége miatt a teljesítmény-elvárások nagyobbak egy érintőképernyős alkalmazással szemben. hogy „megnyomtam? Nyomjam meg még egyszer?” – ami a taktilis visszajelzés hiánya miatt amúgy is gyakori az érintőképernyők használóinál. elengedés után pedig visszaugranak a helyükre. Tilt effektus A tilt (bedöntés) effektus elsősorban a visszajelzést segíti. A bedöntés működése jól látható a Start képernyőn (13-12 ábra). Akár egyetlen kódsorral az egész PhoneApplicationPage-re engedélyezhetjük az effektust. 13-12 ábra: a tilt (bedöntés) effektus segíti a visszajelzést A hatás létrehozásához a Silverlight for Windows Phone Toolkit-ban található TiltEffect osztályt használhatjuk (lásd még http://www. sokkal gyorsabbnak érezzük.13. ezt a kis pluszmunkát mindenképpen megéri. Ez a Metro nyelv egyik jellegzetes eleme – az aktiválható elemek az érintés helyétől függően 3D-ben bedőlnek.com/articles/Silverlight-for-WP7Toolkit-TiltEffect-in-depth). amíg dolgozik.windowsphonegeek. mint egy egeres-billentyűzetes programnál. 336 . Ráadásul elmúlik az a bizonytalan érzés. Használatával már a lenyomás pillanatában tudathatjuk a felhasználóval. Ha a program azonnal reagál. esetleg egy kis animációval szórakoztat. hogy vette az utasításunkat. és jelzi. hogy a telefon „vette” az érintést.

vagy egy másodperces számítást is azonnalinak lát a felhasználó.ProgressIndicator -t. ha a folyamat időtartama bizonytalan (pl. pörgő kör. hogy az alkalmazás dolgozik. vagy saját megoldást. Határozatlan esetben használhatunk még saját animációt is (pl. Hosszan tartó folyamatoknál fontos még. egy szerver válaszára várunk) a ProgressBar használata kerülendő.Szubjektív teljesítmény A folyamat jelzése Hosszan tartó folyamatoknál (pl. vagy egy animáció (pl. hogy a folyamatban nagyjából hol tartunk. és így az animáció végén az új információ azonnal megjelenhet (vagy beúszhat). mint ahogy a Pictures Lab készítője tette (1313 ábra). A figyelem elterelésével leplezzük a lényeget és átverjük az érzékeket. hogy hol tart a számítási folyamatban (engedéllyel használva) Köztes animációk Akár egy fél. ahol a böngésző található. egy könyvjelző kiválasztása után a kockát vissza kell forgatni az első oldalára. Például egy lapozás vagy fade animáció közben megtörténhet a betöltendő oldal layout-számítása és raszterizálása. Ha tudjuk. hosszas számítások) érdemes a felhasználónak jelezni. hogy a munkát háttérszálon végezzük. Jó példa lehet erre a SurfCube böngészőben a könyvjelzőre való navigálás. A WP7 animációi ideálisak erre a célra.ami még rosszabb. Erre bevált módszer a ProgressBar használata. mozgó pöttyök) megjelenítése. Azonban a böngésző vezérlő a CPU-t lefoglalja (főleg navigáció elején). a Toolkit-ből a PerformanceProgressBar vezérlőt. ha GPU-optimalizáltan tudjuk őket végrehajtani. megőrizve ezzel az UI szál válaszképességét. érdemes határozott folyamatjelzőt választanunk. és így a visszaforgató animáció nem látszódik . mert a másik két megoldással szemben túlságosan lefoglalja az UI szálat. 13-13 ábra: a Pictures Lab képszerkesztő program saját design-nal jelzi. amennyiben az a GPU-n fut. a SystemTray. ábra). Erre használhatjuk akár a ProgressBar-t. Az objektív gyorsaság érdekében a könyvjelző megérintése után azonnal elindítottuk a betöltődést és a forgatást. Azonban. ha a kérdéses másodperc alatt történik valami a képernyőn. Amikor a lassabb gyorsabb(-nak tűnik) A szubjektív teljesítmény optimalizálása némileg hasonlít egy bűvészmutatványhoz. egy kör forgatása). a könyvjelző lenyomásáról csak pár tized másodperc késéssel 337 . Mivel a könyvjelzők a kocka tetején helyezkednek el (13-14. szerverre várakozás. főleg.

és csak a fordulás után kezdi meg az oldal betöltését (engedéllyel használva) Memória-optimalizálás A memória takarékos használata a szűkös erőforrások mellett már csak azért is fontos. és a böngészőt most már csak a forgatás animáció befejeztével irányítjuk át az új címre. hogy az alkalmazás sokat gyorsult. Teljesítmény értesül a felhasználó. mert a Marketplace az alkalmazás befogadásakor igen szigorúan ellenőrzi a memória használatát.NET-ben megszokott optimalizáló fogások Windows Phone-on is működnek. 90 Mbyte-ot használhat a program. 338 . 13-14 ábra: a SurfCube visszafordul az első oldalra a könyvjelző kiválasztása után. Érdemes azonban áttekinteni néhány platform-specifikus területet.13. nagyobb memóriával rendelkező készülékeken ennél többet is. A szabály az. Így a teljes oldal-betöltődési idő (az érintéstől számítva) ugyan néhány tized másodperccel megnőtt. de az azonnali reakció miatt a felhasználók egyértelműen (de tévesen) úgy érezték. Természetesen a Silverlight-ban és a . Ezért változtattunk a működésen. hogy 256 Mbyte-os telefonon max.

de a szerverről 500x500-as képet kapunk. Egy lista esetén a látható elemeken kívül még néhány további is renderelésre kerül.Windows Phone Performance Analysis A memória foglalás kijelzése Sajnos a fentebb már részletezett teljesítmény-mérő eszközök között nem szerepel a használt memória kijelzése. Próbáljuk ki a fejezet első mintapéldáján. A már messzire elgörgetett elemek ugyan törlődnek a memóriából. gördíthető listát tartalmaz. aminek segítségével folyamatosan megjeleníthető az alkalmazásunk memóriahasználata. de szerencsére viszonylag ritka.FromMilliseconds(500). Az alapértelmezett Panorama alkalmazás például 28 Mbyte memóriát eszik. miközben csak a MemoryDiagnosticsHelper bekapcsolása okozta a gondot. Ha ez nem lehetséges. de a helyükre a görgetés során új elemek kerülnek (ezt hívjuk virtualizációnak. nomeg a dekódolási sebesség érdekében is) érdemes a képeket a végleges méretükben kezelni. egyetlen sorral elindítható: MemoryDiagnosticsHelper. Optimalizálás Ha a fenti kódot a fejezet elején található példaprogramba beírjuk. Windows Phone Performance Analysis Egy bonyolultabb alkalmazásban nem egyszerű megtalálni a teljesítmény-problémák okát. mint 1. az 5000 csillagot kirajzoló programon! A tesztelést minden esetben a fizikai eszközön végezzük.Assertel is jelzi.aspx).5 Mbyte) foglal a memóriában. hogy képek lennének a listákban. ha a szerveren készítünk 100x100-asat is.cs fájlt hozzáadtuk az alkalmazáshoz.Start(TimeSpan. Nyilvánvaló tehát. hogy több ezer vagy tízezer elem található a fában. true). A képeknél ezért (és a letöltési. Könnyen elképzelhető. mivel az emulátor – a már említett okok miatt – hamis eredményt fog adni.DecodeJpeg(sourceStream. majd a Visual Studio Debug menüjében található „Start Windows Phone Performance Analysis” menüponttal indítsuk el a WPPA-t! A 13-15 ábrán látható képernyő jelenik meg. amely pont ebben segít. A legnagyobb memória-falók természetesen a képek. A pontosabb mérés érdekében váltsunk Release konfigurációba. a MemoryDiagnosticsHelper még egy Debug. akkor a kép dekódolásakor már a végső méretet adjuk meg: PictureDecoder. Szerencsére a Windows Phone SDK része a Windows Phone Performance Analysis (WPPA) eszköz. ha egy 100x100-as thumbnail-t jelenítünk meg. láthatjuk. Jómagam is jó néhány felesleges órát eltöltöttem korábban folyamatosan működő animációk akadozása után nyomozva. hogy túlléptük a 90 Mbyte-os limitet. majd a Launch Application megnyomása után 339 .msdn. hogy egy sokelemes panoráma. Hiába csak 100Kbyte-os egy 800x480 pixeles fénykép jpg formában – a telefonnak minden egyes pixellel kell számolnia. 100. ahol minden elem egy vagy több további. így az 800x480x4 byte-ot (több. akkor legjobb. Tehát. hogy 500 csillag esetén kb. A MemoryDiagnosticsHelper – ami a fenti példában 500 ms-onként fut és a Garbage Collector-t minden alkalommal működteti – hátrányosan befolyásolja az alkalmazás teljesítményét: akadozhatnak az animációk. és a ListBox vezérlőben ez az alapértelmezett működés). Ráadásul a megjelenített vezérlők szintén bitmap formában vannak jelen. 9Mbyte-ot foglal az alkalmazás. anélkül. már igen komoly memóriát felemészthet. lassabbak lehetnek a számítások. Amennyiben az alkalmazást debuggerrel futtatjuk. így ennek hatása elhanyagolható. Egy Panorama háttere ennek többszöröse is lehet. Szerencsére Peter Torr készített egy MemoryDiagnosticsHelper osztályt (http://blogs. 100). Miután a MemoryDiagnosticsHelper. és a pixeljei a memóriában tárolódnak. míg 5000-nél 16-ot.com/b/ptorr/archive/2010/10/30/that-memory-thing-i-promisedyou. hogy a vizuális fa mérete befolyásolja a memória-használatot.

A zöld szín az UI szálat. majd a Select All-t a grafikonon). majd állítsuk le az adatgyűjtést! 13-15 ábra: A Windows Phone Performance Analysis indítóképernyője Némi számolás után a 13-16 ábrán látható eredményt kapjuk (nyomjunk egy jobb gombot. Jellemzően 30 és 60 közötti értékeket szeretünk itt látni. az esetenként megjelenő lila pedig a az alkalmazás nem UI szálait (beleértve a Compositor és a háttér-szálakat). Alatta a Frame Rate azt mutatja. amíg megjelennek a csillagok. ezért nincs itt sok értékelhető adat. Teljesítmény elindul az alkalmazás a telefonon. A CPU-használatot mutató grafikonon a fehér szín azt jelzi. 340 . Várjuk meg. Mit jelent mindez? 13-16 ábra: Az analízis eredménye A felső skála a másodpercekben mért időt mutatja. amikor a CPU nem csinál semmit. Mivel a csillagok kirajzolása után az alkalmazás nem csinál semmit. a szürke a rendszer-szálat jelenti. hogy egy másodperc alatt a képernyő hányszor került újrarajzolásra.13.

Láthatjuk.Windows Phone Performance Analysis A memória-használat grafikonja egyértelmű. képkocka megrajzolásához milyen függvényhívásokat hajtott végre a rendszer. mi került egy másodpercbe a 4-es képkocka kiszámításánál! Ehhez válasszuk ki a 4-es kockát. és láthatjuk az 5000 ellipszist. az alsó részben a tipikus teljesítményproblémákra hívja fel a figyelmünket a program. és a 13-18 ábrán látható eredményből le is vonhatjuk a következtetést: a legtöbb időt a MeasureOverride és ArrangeOverride – tehát az elrendezéshez szükséges feladatok veszik el. Például az első sorban azt jelzi. ekkor a 13-17 ábrán látható eredményt kapjuk! 13-17 ábra: Az alkalmazás első 5 képkockájának adatai Látható. illetve a CPU-használatot. Ha a Performance Warnings melletti kis nyilacskára kattintunk. Alatta a program által indított StoryBoard-ok (piros – CPU. Először válasszuk ki a Frames-t. Az Inclusive samples-re kétszer kattintva. Legvégül pedig a Garbage Collector eseményei. Még látványosabb. 341 . képkocka elkészítéséhez szükséges függvényhívások De mi a helyzet az ellipszisek megrajzolásával? Ehhez a Frames melletti háromszögből válasszuk az Element Types lehetőséget. Ezt több mint 1 másodpercig rajzolta a telefon (Duration és CPU time). majd a Frames szövegtől jobbra található kis háromszögre kattintva válasszuk a Functions menüpontot. amikor Grid helyett Canvas-t használtunk. Nézzük meg. hogy az adott függvényből hívott további függvények is beleszámítanak. az exclusive pedig. hogy magas CPU használatot mért az UI szálon – olyan CPU használatot. lila – nem CPU) és képbetöltések találhatók – ezek ebben az alkalmazásban nem fordulnak elő. 13-18 ábra: A 4. csökkenő sorrendbe rendezhetjük a hívásokat. hogy a 4. hogy csak a függvény saját idejét számítjuk. Látható még az adott frame Fill Rate-je és a textúrák száma is. Ha fent kijelölünk egy legalább fél másodperces időtávot. hogy az alkalmazás a futása során 5 képkockát készített (0-tól számozva). ha a Visual Tree for Frame 4 opciót választjuk (13-19 ábra). Ezt az időt rövidíthettük le. amikor az ellipsziseket kirajzoltuk. megtekinthetjük a frame-eket. ami nem feltétlenül a rajzolással van összefüggésben. Ebből az ötödik (utolsó) kocka az. Az Inclusive azt jelenti.

Mi történt vajon a 3-as kocka vége és a 4-es eleje között. hogy melyik elemmel mennyit foglalkozott a telefon. Teljesítmény 13-19 ábra: A 4. hogy az ApplicationTitle TextBox kezelése egy tized másodpercbe került. míg a második TextBox-nál már erre nem volt szükség. hogy a 4-es kockát a program indítása után 6. A jelenség oka. majd a Performance Warnings . 342 . Ennyire lassan rajzolna szöveget a futtatókörnyezet? A PageTitle viszont csak 5 ms. Visszatérve a képkockákra (13-17 ábra).Functions nézethez navigálunk (13-20 ábra). közel 6 másodpercig? Erre a kérdésre a választ úgy kaphatjuk meg. éles szeműek észrevehették. képkocka vizuális fája és az egyes elemek megrajzolásához szükséges idő Itt fában kibontva látható. hogy az első szöveg kirajzolásánál a környezetnek még a TextBox osztályt is be kellett töltenie és értelmezni.13.767 másodperccel kezdte csak el a telefon számolni. Talán meglepő lehet.CPU Usage . csak magára az elrendezésre és a rajzolásra. ha a diagramon kijelöljük a 3-as és 4-es képkocka közötti területet.

a memóriafoglalás minimalizálásának módjairól és a mindezeket elemezni képes Windows Phone Performance Analysis eszközről is. de az egyik leghasznosabb eszköz lehet a fejlesztés során a teljesítmény-problémák azonosításában.Összefoglalás 13-20 ábra: A CreateStarField vitte el a 3-as és 4-es frame közötti idő 88%-át. Ez a fejezet csak az út elejét tudta megmutatni – a CPU és GPU használatát. a lassú betöltődés és navigáció. Szó volt a szubjektív teljesítményről. Látható. az akadozó animációk lehetséges okait és megoldását. hogy a telefon az ideje jelentős részét a MainPage konstruktorában. Összefoglalás Egy egész könyvet lehetne írni arról. 343 . sőt azon belül a CreateStarField metódusban töltötte. és persze saját alkalmazásokkal is! A Windows Phone Performance Analysis elsajátítása nem egyszerű. hogy miképp készítsünk gyors. Érdemes kísérletezni még a többi lehetőséggel. kitűnő teljesítményű Windows Phone alkalmazásokat.

Sign up to vote on this title
UsefulNot useful