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

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

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

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

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

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

.

valamint Velvárt András (13. akik saját alkalmazásokat szeretnének készíteni. Olyan eszközök. és egyúttal betekintést is adnak annak működésébe és használatába. Olyan magyar nyelvű könyvet hoztak létre. és 7. és 11. 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. fejezet) mindannyian rengeteg energiát fordítottak arra. amelyben személyes tapasztalataikon. amelyeken internetet is elérő alkalmazásokat tudunk futtatni. 2011. akik maguk is gépeket építenek. Novák István Budapest. december 13 . akik korábban már megmutatták. fejezetek).hu oldalon. Ugyanígy az okostelefonok felhasználói között is többen akadnak. Ez a könyv az alkalmazásfejlesztőknek készült. és 2. fejezetek). nekem kellett előkeresni a számokat a noteszomból és bepötyögni azokat egy-egy telefonhívás során. Az autók szerelmesei között vannak olyanok. Komjáthy Szabolcs (4.Előszó Amikor első hordozható telefonomat 18 évvel ezelőtt megkaptam. Olyan szakemberek írták. hogy ismereteiket megosszák a fejlesztőközösséggel. és a telefonálás lehetősége csupán egyike tucatnyi képességeiknek. Fár Attila Gergő (5. és 6. Még csak telefonkönyve sem volt. hogy értenek a platform használatához és programozásához. és 10. amelyek segítenek a Windows Phone fejlesztésbe frissen bekapcsolódó érdeklődőknek megismerni a platform legfontosabb alapelemeit. 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. és ezek piaci sikeréből akár meg is élni. 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. fejezetek). akik szeretik gépjárművüket maguk bütykölni. fejezetek). Egyetlen dolgot lehetett vele csinálni: telefonálni. Ebben a könyvben azokat az ismereteiket is átadják. és 12. Fülöp Dávid (3. Farkas Bálint (9. fejezetek). Turóczy Attila (8. az még egy kisebb diplomatatáska méretével egyezett meg. a platformhoz kapcsolódó élményeiken keresztül mutatják be a Windows Phone alkalmazásfejlesztés alapvető eszközeit és fogásait. fejezetek). Árvai Zoltán (1. A repülőgépmodellek megszállottjai között vannak olyanok.

.

a Windows Phone-nal jelent meg a piacon. csupán mobil operációs rendszert fejleszt. amely az előírt hardver követelményeket maradéktalanul kielégíti. 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. digitális identitásunk egyfajta kiterjesztéseként gondolunk rájuk.1. azzal a gondolattal. hol vagyunk. Nem csoda hát. 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. hogy az asztali Windows-t vihetjük a zsebünkben. mikor hol kellene lennünk. 1-2 év alatt meghatározó szereplőkké nőtték ki magukat. illetve az okoskészülékek piacán. Az a telefon lehet Windows Phone. 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. hogy a Twitter. amely évről évre csak nő. akik a semmiből. sokszor kényszerülnek olyan döntéseket hozni. és alapjaiban új operációs rendszerrel. de a Windows Phone újabb ilyen lehetőséget jelent! A Microsoft. illetve a könyv írásának pillanatáig nem sokat foglalkozott. A telefonok tudják. és újabb lehetőségeket kínál. mit szeretünk csinálni és kivel. É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. a Windows Phone és saját alkalmazásboltja (Marketplace) megjelenésével új piacot nyit a vállalkozó szellemű fejlesztők számára. Ez a mobil operációs rendszer azonban elsősorban üzleti használatra készült. A Windows Phone Platform A Windows Phone megjelenésében merőben újszerű. bármikor elérhetővé válik. hogy bizonyos kategória alatt nem támogatnak telefonokat. 15 . 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. Habár saját eszközt nem dobott a piacra. az alkalmazást hány különböző eszközre és hardver konfigurációra kell elkészíteni. hogy újabb sikertörténetek születhessenek. Az elmúlt években számos mesébe illő sikertörténetet hallhattunk olyan cégekről. A Microsoft valahol a kettő közötti utat választotta. hogy a Microsoft készüléket nem. az eddigi mobil operációs rendszerektől eltérő dizájnnal és szellemiséggel rendelkezik. A Microsoft . kik a barátaink. A Google ezzel a kérdéssel nem nagyon foglalkozik. új igényekhez igazítva tervezték. Sokszor társként. és maximálisan igyekeznek minket kiszolgálni. 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. Ezt a terméket a megváltozott. 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. A gyakorlott fejlesztők ezeket a sorokat olvasva biztosan felhördülnek és elgondolkodnak. életünk. új lehetőségeket. A Windows Mobile termékcsalád hosszú utat járt be – még ha ez az út igencsak rögös is volt. gyakorlatilag a nulláról indulva. A Microsoft egyike volt az elsőknek az okostelefonok piacán. Így nem csoda.ezt a tényt felismerve szemmel láthatólag nem erőltette tovább ezt a vonalat. hogy ez vajon mekkora fragmentációt jelenthet a készülékek piacán. a fogyasztói piacnak azonban ezek az elvek és ez a termék nem tudott megfelelni. hanem a fejlesztőcégek számára is. kik vagyunk. A Windows Phone különlegessége. a Facebook. A világot helyezik kezünkbe. Az új igényeknek. hogy az okostelefonok megjelenésével egyfajta fejlesztői „aranyláz” tört ki. Sajnos az idő előrehaladtával egyre nehezebb sikertörténeteket írni. bármi. a konkurrens termékekkel nem volt képes felvenni a versenyt.

valamint Wi-Fi-t kell támogatnia. 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. Fejlesztőeszközök Futtatókörnyezet A Windows Phone alkalmazások izoláltan. ezt a futtatókörnyezet szigorúan ellenőrzi. Kezdő oldal gomb (Home): A Start képenyőre navigál bárhonnan. Műholdas navigáció tekintetében Assisted-GPS támogatás szükséges.1. illetve futó taszkok közötti váltást szolgálja. illetve XNA. 16 . elsősorban biztonsági okok miatt.) Adatok tárolásra minimum 8GB-os flash tárolóegységgel kell rendelkeznie a készüléknek. amelyek szorosan kapcsolódnak az operációs rendszer és a navigációs mechanizmus működéséhez. A készüléknek hálózati kommunikáció tekintetében mobil adathálózatok kezelését. 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. döntésének és egyéb pozícióinak követésére gyorsulásmérőt kell beépíteni. Marketplace portál szolgáltatások 4. Saját termékek fejlesztése során két platform közül választhatunk: Silverlight. Integráció a felhővel 3. Az alkalmazások ennek köszönhetően nem férhetnek hozzá kontrollálatlanul tetszőleges erőforráshoz. Futtatókörnyezet 2. 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. sandboxban („homokozó”) futnak. Kereső gomb: Minden esetben a beépített Bing keresőt hozza fel. 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.     Kijelző:    A kijelzőnek legalább 800 x 480-as felbontással kell rendelkeznie. Hálózati jellemzők:   Memória:     Navigáció:  Mozgásérzékelés: A telefon mozgásának. ún. Operatív memória tekintetében legalább 256 MB memóriával kell rendelkeznie a készüléknek. Vissza gomb (Back): Az alkalmazáson belüli navigációt.1-ben ez a viselkedés nem módosítható. bármely alkalmazásból. 7.

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

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

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

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

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

A következő lépésben a Visual Studio megkérdezi tőlünk. 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. hogy számos különböző projektsablon áll rendelkezésünkre.1. Ezekkel a későbbi fejezetek során részletesebben is megismerkedünk majd. 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. mint különböző alkalmazás típusok. Készítsük hát el első Windows Phone alkalmazásunkat! 1. Hozzunk létre egy új Windows Phone alkalmazást! Kattintsunk a File menüre. Egyelőre gondoljunk ezekre úgy. 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. Vegyük szemügyre a Visual Studio által létrehozott elemeket! A Solutions Explorer ablak tartalma az 1-3 ábrán látható. illetve különböző felépítéssel rendelkező alkalmazások speciális változatai.1 van kiválasztva. 1-3 ábra: A projekt felépítése 22 . 1-2 ábra: Új projekt létrehozása 2. hogy el ne készítse rá a dedikált Hello World alkalmazását. hogy melyik operációs rendszer változatra szeretnénk fejleszteni. hogy a Windows Phone OS 7. majd kattintsunk az OK gombra! 3. Győződjünk meg róla.

0.microsoft.0" Genre="apps.xml fájl megér külön egy kis magyarázatot: <Deployment xmlns="http://schemas.Hello Windows Phone A HelloWindowsPhone projekt elemeinek tartalmát az alábbi táblázat mutatja be: Elem neve Properties References App.xaml. Ezeknek a gyerekelemeknek a felvételével határozhatjuk meg.xaml (MainPage. az ikon.normal" Author="HelloWindowsPhone author" Description="Sample description" Publisher="HelloWindowsPhone"> <IconPath IsRelative="true" IsResource="false">ApplicationIcon.png Background.xaml. az alkalmazás felirata. stb.png MainPage. A legérdekesebb szekció azonban a Capabilities elem és gyerekei.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.png Induláskor megjelenő.xaml (App.cs) ApplicationIcon. töltési idő alatt látható kép A Properties alatt található WMAppManifest.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.0. hogy az alkalmazásunk a telefon 23 . hogy az alkalmazás alapbeállításai itt kerülnek meghatározásra: a háttérkép.1"> <App xmlns="" ProductID= "{9bb8c371-293f-4726-a4ba-5b2e2efb152d}" Title="HelloWindowsPhone" RuntimeType="Silverlight" Version="1.com/windowsphone/2009/deployment" AppPlatformVersio n="7.png</BackgroundImageURI> <Count>0</Count> <Title>HelloWindowsPhone</Title> </TemplateType5> </PrimaryToken> </Tokens> </App> </Deployment> A fenti XML kódrészletben jól látható.xaml"/> </Tasks> <Tokens> <PrimaryToken TokenID="HelloWindowsPhoneToken" TaskName="_default"> <TemplateType5> <BackgroundImageURI IsRelative="true" IsResource="false">Background.

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

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

Betekintést nyerhettünk a platform legfontosabb építőelemeibe. valamint megírtuk életünk első Windows Phone alkalmazását. amelynek során részletesen megvizsgáltuk. a Silverlight és a XAML nyelv alapjaiba. 26 . beállításai. melyek a legfontosabb elemei. A következő fejezetekben ezt a tudást mélyítjük el. 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. hogy végül professzionális alkalmazásokat tervezhessünk és fejleszthessünk. hogyan is épül fel egy Windows Phone projekt. Bemutatásra került a fejlesztőeszköz.1.

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

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

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

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

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

sok mindent gondosan meg kell terveznünk.2. A legfontosabb dolog. Teszteljünk minél többet. egészen az apró részletekig. előbb-utóbb nem vesszük észre benne a finomságokat. kérjük ki mások véleményét. folyosó tesztek: kapjunk el valakit a folyosón és kérjük meg. Ez igen tág témakör. hogy hajtson végre valamit az alkalmazásunkkal. nem elegendő. figyeljük a felhasználóink „ügyetlenkedését”. ha maradandó élményt nyújtunk! Sok mindenre sajnálhatjuk az erőforrásainkat. a használhatóság biztosítása. 32 . esztétikus alkalmazás. 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. é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. hogy a felhasználó fejével gondolkodjunk. a kiemelkedő vizuális élmény. hanem az értékből. Rendkívül sokat segíthetnek az ún. grafikonokat. Ha elég sokat foglalkozunk a saját termékünkkel. hogy tesztelje le. mi a legértékesebb információ! Miután ez a tudás már a birtokunkban van. melyek a legfontosabb elemek. rosszabb esetben a nagyobb bajokat sem. az információból! Döntsük el. nekiállhatunk megtervezni. hogy gondosan elemezzük. annak kell ragyognia. é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. Felhasználói élmény tervezése Windows Phone-on odafigyeléssel mi magunk is kellemes élményt alakíthatunk ki. ezért létfontosságú. 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. hogy a Metro dizájn elveit betartjuk. hogy miként reprezentálhatjuk ezt látványosan. A fogyasztói termékek piacán azonban elengedhetetlen a szép. Ezért a legfontosabb a kezdő ergonómus számára. amelyben a vizuális hierarchiától kezdve a navigáción át. hogy a tartalom megfelelően tálalva. Az alkalmazás középpontjában a tartalom van. infografikákat! Végig tartsuk szem előtt. melyeket láttatni kell a felhasználóval. Használjuk bátran a vizuális eszközöket. Szintén sok ötletet meríthetünk egyéb sikeres alkalmazásokból. a vizuális dizájnra nem. amit csinál. A weben tömegével megtalálható infografikai példák komoly segítséget nyújthatnak. Ne essünk tévedésbe! Az a gyakorlat. amelynek ki kell emelkednie. és egy fekete-fehér alkalmazást készítünk. a tartalom az. A középszerűségből csak úgy emelkedhetünk ki. hogy mit és hogyan mutatunk meg a felhasználónak! Ne a vizualitásból induljunk ki.

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

A felhasználói felület végleges kialakításában. Sketchflow-s Projekt sablon a Blend-hez (http://wp7sketchflow. Az Expression Blend egyéb változataiban lehetőségünk van ún. dinamikus prototípusok készítésére alkalmasak. Ez a fejlesztőeszköz Windows Phone fejlesztéshez ingyenesen elérhető. Tervezés Sketchflow-val A Microsoft Expression Blend for Windows Phone termék rendkívül hatékony eszköz.com/). mint például az Expression Blend Sketchflow. 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. Windows Phone fejlesztéshez elérhető a Codeplex-en.codeplex. használhatunk erre specializálódott eszközöket is. Sketchflow projektek létrehozására is.2. Ezek a projektek kizárólag sketchek. a hatékony és gyors munkában elengedhetetlen szerepe van. (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 . melynek segítségével Windows Phone alkalmazások prototípusát készíthetjük el.

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

mint objektumok folyamatos átpozicionálásáról. a nem. személyes. annál nagyobb sikerre számíthatunk! 2-14 ábra: Személyes alkalmazás (Facebook) Hasznos. Jól integrálódik az operációs rendszer megszokott jellemzőivel (pl. sokkal sikeresebbek. sima és könnyed animációk ezt az érzetet keltik. jól használható. 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. 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. a felhasználó számára értékes funkcionalitással bír. személyre szabott. hogy a felhasználói interakciónak virtuális értelemben vett fizikai hatása van. nehézkes. A korosztály. Azok az alkalmazások. A Windows Phone alkalmazások felhasználói felületén alkalmazott mozgásokat két részre érdemes bontani: 36 .és hírközpontú alkalmazások. 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. újdonság szolgáltatása nélkül szinte lehetetlen a felhasználóinkat visszavonzani. amelyek róla szólnak. Windows Phone esetén a mozgás és az animáció a legfontosabb visszajelzése annak. amelyek úgy tesznek. az ő igényeiről. a közös jellemzők meghatározása jelentősen leegyszerűsítik a tervezés folyamatát. A gyors. mintha szinte csak neki íródtak volna. Nagyon jó példa erre az Amazon alkalmazása. 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. Minél inkább a felhasználó képére tudjuk formálni az alkalmazást. amelyek vele foglalkoznak. könnyen használható és egyszerűen tanulható. navigáció). jó érzés használni. illetve weboldala: releváns. Friss és értékes tartalom. A mozgás és az animáció minősége és jellege határozza meg elsősorban. míg a lassú. és kívánatos. 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. netán akadozó animációk nagyban rontják a felhasználói élményt. hogy a felhasználó mennyire érzi folyamatosan válaszra késznek az alkalmazást.2. kívánatos A tökéletes alkalmazás hasznos.

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

Az ennél nagyobb vagy kisebb képek átméretezésre kerülnek. gyengén megtervezett és megrajzolt lapkával rendelkező alkalmazás azt is kockáztatja. felfelé vagy lefelé. JPEG vagy PNG formátumban. színes belső képekkel 2-16 ábra: Helytelen háttérszínek használata lapkáknál 38 . Ezenfelül az alkalmazás listába érdemes külön 63x63 pixeles képet biztosítani. melyek a megfelelő Windows Phone témák esetén „transzparens” háttérként funkcionálnak (2-16 ábra) Transzparens háttereket. hogy a Marketplace-ből kisebb eséllyel kerül letöltésre. vágáshoz vezethet. árnyékok alkalmazását Lekerekített lapkákat Fekete vagy fehér háttereket.2. Fontos. 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ű. ami torzításhoz. 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. ellenkező esetben az alapértelmezett lapka kerül átméretezésre. hogy megragadja a szemet! A lapka képeknek 173x173 pixel méretűeknek kell lenniük.

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

Az animáció során a tartalom és a feliratok különböző sebességgel. 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. 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. valamint az átméretezés elkerülését. A vezérlő önálló. 40 .2. 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. 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 görgetés során pedig egészen egyedi animációval és tulajdonságokkal rendelkezik. 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. A navigáció a menüelemek fejlécét érintve. és biztosítja a navigációt közöttük. elkülönített nézeteket helyez el egymás mellett. illetve 1024x800-as felbontásban. dinamikus parallaxszerű effektust eredményezve. ezáltal rendkívül látványos. időben eltolódva hajtódnak végre. Ez biztosítja a jó teljesítményt és a gyors betöltést. Toggle. illetve horizontális mozgatással lehetséges. Map vezérlők). Háttérképként jellemzően JPEG ajánlott 480x800-as. A Panorama vezérlővel ellentétben nem egyetlen nagy téren helyezkednek el az egyes szekciók. 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.

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

azaz „félrenyom”. interaktív területet is célszerű nagyobbnak választani a vizuális elem területénél. A fenti szempontok figyelembevételével ennek a kockázata jelentős mértékben csökkenthető. 42 . 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. 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. Az ideális méret. Ezenfelül az érinthető. örömteli perceket szerezhetnek. amelyen már a vizuális visszajelzés (lenyomás animáció) is érzékelhető 10-15mm2 között mozog. Ezeket az elveket betartva olyan stabil termékek születhetnek. minimum 4. mind a felhasználóink számára élvezetes. itt a minimum korlát a 7mm-es magasság. valamint a dizájnvezérelt tervezés módszerével. amely két célobjektum között helyezkedik el. A helyzeten tovább javít az ún. Bár a holt területet célszerű arányaiban megállapítani. 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. a használhatóság vonatkozásában! Összefoglalás Ebben a fejezetben megismerkedtünk a Metro Design legfontosabb elveivel.2mm2-esnek kell lennie. melyek mind számunkra. a 2mm-es minimum jó alsó határértéknek tekinthető. amely érintésre reagál. A helyes interkaciós modellek megválasztása és támogatása kulcsfontosságú szereppel bír a felhasználói élmény.2. holt terület helyes meghatározása. és semmilyen interakcióval nem rendelkezik. Holt területnek nevezzük azt a szabad területet. amelyet szándékozott. Ennél kisebb területet a felhasználók nem fognak interaktívnak tekinteni. 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. tipikusan listák esetében.

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. 43 . illetve stílusok segítségével változtathatjuk meg. A fejezet során végig az Expression Blend 4 segítségével hozzuk létre és szabjuk testre a felületeket. 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. sok minden megegyezik az „asztali” Silverlighttal. áttekintő összefoglalást kíván adni. Ennek a fejezetnek az első részében ezekkel az építőelemekkel ismerkedünk meg. Ahogy a Silverlight „asztali” verziójában is. illetve a keretrendszer UIhoz kapcsolódó szolgáltatásaiban. és az ezekben leírtak komolyabb változtatások nélkül alkalmazhatók Windows Phone 7-fejlesztésben is. Az Expression termékek elsősorban a dizájnereknek készültek – ahogy a Silverlight elődjét. összetett felhasználói felületek (a továbbiakban UI – User Interface) kialakításának támogatása. amelyek a felületek építéséhez elengedhetetlenek. könnyen használhatóvá teszik a vezérlőket. 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. 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. Mivel már rengeteg könyv megjelent Silverlight 4 témában. 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. hogy segítsék a dizájnerek és a fejlesztők együttműködését. A Visual Studio 2010 elsősorban a fejlesztőknek készült. Az adatkötésirendszerrel és az adatsablonok használatával pedig rengeteg kódot megspórolva építhetünk dinamikus. Többek között a VS ezen gyenge pontját ellensúlyozandó hozta létre a Microsoft az Expression termékcsaládot. és lehetőséget adnak arra. illetve saját vezérlőket hozzunk létre.3. viselkedést adjunk nekik –. 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. akár a teljes felület bizonyos helyzetekben felvett megjelenítését írhatjuk le központi. 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. de korábban megszerzett tudása azonnal és közel száz százalékosan átvihető WP7-re. Ebben a fejezetben ezeket a témaköröket nézzük meg közelebbről. Ezek azok az alapvető építőelemek. ezenfelül pedig könnyedén animálhatjuk azokat. ezért. a Windows Presentation Foundationt is azzal a céllal hozták létre. adatfüggő felületeket. Azonban a felületek kialakítása egyes esetekben eléggé fájdalmas tud lenni a VS használatával. akár több már meglévő elem együttes használatával. amelyek testre szabhatóvá. A vezérlők kinézetét egy nagyszerű vezérlősablonrendszerrel. é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 –. amelyek segítségével a legegyszerűbbtől a legbonyolultabb üzleti alkalmazásokig bármilyen felhasználói felületet átlátható. amelyekkel akár az egyes vezérlők. ahogy látni is fogjuk. 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. 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. Előbbiben értelemszerűen a vezérlőket találjuk. izgalmassá. az is találhat néhány új dolgot (például az InputScopeok). Különböző vizuális állapotokat hozhatunk létre. hogy kiterjesszük azokat – új tulajdonságokat. Alkalmazásfejlesztés Windows Phone-on Az eredetileg RIA fejlesztésre kialakított Silverlight keretrendszer talán legfontosabb alapgondolata a gazdag tartalmú. kézre álló módon felépíthetünk. ez a fejezet csak egy gyors.

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

Ismerkedjünk meg a felülettel. A toolbox legalsó eleme jelen pillanatban egy dupla.Alapvető WP7 vezérlők Tartsuk észben. a harmadik csoportban találjuk a primitív vezérlőket szimbolizáló egyszerű négyszöget. Azoknál az ikonoknál. négy részre osztott négyzet ikon). szerkeszteni). Lejjebb. Lejjebb. mint a Visual Studio. 7. Ha kiválasztunk valamit az Asset Library-ban. jobbra mutató nyíl.10. ahonnan egyéb. Az OK gombra kattintva a Blend létrehozza a projektet.5-ösként reklámozott OS belső verziószáma 7. Ha közelebbről megnézzük. 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. hogy a Blend alapbeállításként nem ugyanabban a könyvtárban hozza létre a projekteket. néhány ikon jobb alsó sarkában egy kis nyilat vehetünk észre – ez azt jelenti.1-es OS verzió ne tévesszen meg senkit! A Mangóként ismert. 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. Asset Library-t. a kéz ikonnal tudjuk egyszerűen görgetni a tervezőfelületet. a toolboxon nem szereplő vezérlőket és egyéb felhasználható típusokat érhetünk el. A nagyító ikon segítségével nagyíthatunk a felület egy részére. hanem minden a felület kialakításával kapcsolatos eszközt tartalmaz. a szövegvezérlők (keretes T betű). annak ikonja a duplanyíl alatt jelenik meg. hanem egy csoportról. amelyeknél van ilyen nyíl. Erre kattintva érjük el az ún.7720. illetve egyéb gyakran használt vezérlők (gomb ikon). a 45 .68. Alatta találhatók az elrendezés-vezérlők (Grid. hogy nem egy eszközről van szó.

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

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

Itt két dologról is érdemes szót ejteni. látható. akkor a tulajdonság az alapértelmezett értékén áll. hogy sok tulajdonságtól jobbra egy kis négyzet található. amelyeket elsőre könnyű nem észrevenni. ahogyan azt a 3-6 ábra mutatja. valamilyen adatkötésből kapja az értékét. hat egyforma cellára bontják a felületet. A másik.3. amelyek nélkül nincs élet a Silverlightban! 48 . ha fehér. akkor kézzel állították be valamilyen értékre. Visszatérve a ContentPanelre. hogy a tervezőfelületen is megjelennek a cellák határoló vonalai. és így tovább. Az egyik. ha hozzáadunk a RowDefinitions és a ColumnDefinitions tulajdonságokhoz két oszlopot és három sort. 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. ha sárga. 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.) A gomb színe is jelentőséggel bír: ha szürke. illetve egyebek mellett alapértelmezett értékre is visszaállíthatjuk a tulajdonságot. hogy a csoportok alján található egy lefelé mutató nyíl. Ez nemcsak dizájnelem. (Az adatkötésről és az erőforrásokról a későbbiekben lesz szó. ezzel érhetjük el a ritkábban használt tulajdonságokat. 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.

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

hogy valamilyen kód lefusson. (Esetünkben ez btnOne lesz. 50 . a Blend átvált az aktuális oldal mögöttes kódjára. amikor a felhasználó megnyomja a gombot. Alapértelmezés szerint nem kell. viszont ha hivatkozni szeretnénk rájuk a mögöttes kódban. 3-10 ábra: A Margin alaphelyzetbe állítása az Advanced options Reset parancsának segítségével 3-11 ábra: Gomb. Marginok nélkül Azt is észrevehetjük. széltében kitölti a cellát (3-11 ábra).) Ahhoz. Itt kapcsolhatjuk azt a kódot a felülethez. é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). A Properties panel tetején válthatunk át eseménynézetbe. a gomb szélesebb lesz. a Button Click eseményéhez kell hozzárendelnünk egy eseménykezelő metódust. 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 –. amellyel megvalósíthatjuk az elvárt működést. 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).3. hogy nevet kapjanak a vezérlők. akkor érdemes nevet adni nekik.

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

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

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

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

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. aláhúzott) betűformázási lehetőségeket is megkapjuk (3-21 ábra). a betűk méretét. Egyszerű szövegmegjelenítés a TextBlockkal Ahogy korábban láttuk. amelynek nem kell szöveget megjelenítenie. 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. a Windows Phone Application sablon rögtön két TextBlockot is beépít alkalmazásunk felületébe. 55 . A Silverlightban erre elsősorban két vezérlőt használunk: egyszerű szövegmegjelenítésre a TextBlockot. dőlt. Egyebek között átállíthatjuk a betűtípust. 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). bonyolultabban formázott megjelenítésre pedig a RichTextBoxot.

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

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

megnyílik az Internet Explorerben a megadott weblap. 58 . hogy ne csak a felkínált lehetőségek közül választhasson. de legáltalánosabb adatbeviteli vezérlő mindig is a TextBox marad. hanem ő maga adhasson meg valamilyen bemenetet. De gyorsan szembe kerülünk azzal az igénnyel. és TargetName tulajdonságának a „_blank” értéket kell adni. 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. a link már jól fog működni – ha megérintik.3. hogy megkönnyíthessék a felhasználói adatbevitelt. vagy éppen választhat lehetőségek közül. és a felhasználó különböző parancsokat futtathat. 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. amit a program fel tud dolgozni. A Silverlight számos speciálisabb vezérlőt kínál a fejlesztőknek. Ha ezek után fut az alkalmazás.

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. 3-31 ábra A TextBox tulajdonságainak beállítása a Properties panelen 59 . 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. 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 tulajdonsággal megszabhatjuk. A TextBoxot. a Toolboxon Nem meglepő módon a TextBox vezérlő Text tulajdonságán keresztül érhetjük el. hogy legfeljebb hány karaktert írhasson be a felhasználó a szövegdobozba. illetve kódból itt állíthatjuk be a szövegdoboz szövegét.Alapvető WP7 vezérlők Szövegbevitel a TextBoxszal A TextBox. 3-30 ábra – A TextBox helye a szövegvezérlők között. a MaxLength csak a felhasználói adatbevitelt szabályozza. Programozottan ennél többet is meg lehet adni.

hogy esetleg megakadályozzuk a felhasználót érvénytelen adatok bevitelében.Text = tbTitle. Alkalmazásfejlesztés Windows Phone-on Amikor a TextBox szövege megváltozik. Ezt az InputScope tulajdonsággal tehetjük meg (3-33 ábra). } 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 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. private void tbTitle_TextChanged(object sender. TextChangedEventArgs e) { PageTitle. a Silverlight for Windows Phone 7 lehetővé teszi. 60 . 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. Ahogy gépel. az oldal címe automatikusan frissül. mint egy teljes értékű és méretű fizikai billentyűzeten tenni ugyanezt. elkaphatjuk a TextChanged eseményt. illetve. hogy a felhasználó egy szövegdobozba csak számokat fog gépelni. hogy néhány kattintással pontosan beállíthassuk a TextBox vezérlők virtuális billentyűzetét. Ha például tudjuk.3.Text.

így akár futás közben is változtatható egy TextBoxhoz rendelt billentyűzet: InputScope ins = new InputScope(). a felhasználó csak számokat tud majd beírni ebbe a szövegdobozba (3-34 ábra).NameValue= InputScopeNameValue.Names.Number. tbTitle. 61 . insName.InputScope = ins. ins. 3-34 ábra: Number InputScope-úra beállított TextBox Ugyanezt természetesen kódból is beállíthatjuk.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. InputScopeName insName = new InputScopeName().Add(insName).

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

(3-38 ábra) 63 . Mindössze annyit tud. (Az elemek törlése már feláras funkció. Az Items listán keresztül adhatunk elemeket a ListBoxhoz. a SelectionMode-dal pedig megadhatjuk. hogy több elem is kijelölhető legyen-e. a -1 azt jelenti. végletekig egyszerűsített tennivaló-listát valósítjuk meg. hogy hányadik elem legyen alapértelmezetten kijelölve.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ó. A SelectedIndex segítségével állíthatjuk be. A számozás 0-tól indul. nincs kijelölt elem.) 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. hogy a TextBoxba írt szövegeket a gomb megnyomásával a ListBoxhoz rendeli.

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 Object Collection Editor ablak jelenik meg.3. melyben szerkeszthetjük a ListBox tartalmát. Egy stringet hozzáadva (az mscorlib|Systemben találjuk) a szerkesztőablak jobb oldalán megjelenik a karakterlánc. 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). amit átírhatunk. 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.

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

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

illetve a Silverlightban. létrehozva ezzel az erőforráshoz kötést (3-44 ábra). 67 . A kész erőforrás innen azonnal. drag-and-drop módszerrel áthúzható egy felületi elemre. 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-44 ábra: Az adatforrások a Resources panelon Ugyanezt elérhetjük. 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. hanem egy erőforráshoz kötöttük hozzá (3-43 ábra). hogy a Blend nagyon szépen jelzi. hogy egy tulajdonság nem lokálisan kap értéket. ha nem egy előre elkészíthető erőforráshoz akarunk kötni. például egy CLR-objektumhoz. 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. ott is megtalálható az erőforrások között az újonnan létrehozott string. ha átváltunk a Resources panelra. hanem valami máshoz.Adatkötés Az is észrevehető. hogy a tulajdonság egy erőforrásból kap értéket Továbbá. 3-43 ábra: A zöld keret és pötty jelzi. Mi a helyzet akkor.

vagy hiányzik a program szerelvénye a listából. set. és megjelenik. a „Create sample data” nevűt.} public Character() { Name = "Hubert Farnsworth".3. 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. illetve adjuk meg az adatforrás nevét! (Ha még nem jelenne meg az osztály. ahol a tényleges adatok még nem állnak rendelkezésre. fordítani vagy futtatni kell. é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. set.} public string City {get. } } Hozzunk létre egy példányt ebből az oldalon. Ezzel véletlenszerű mintaadatokkal feltöltött adatforrásokat hozhatunk létre. 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.) 68 . A megjelenő ablakban válasszuk ki a Character osztályt. Hasznos a fejlesztésnek abban a fázisában. City = "New New York".

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. Vezérlőink DataContext tulajdonsága szolgál 69 . de ha sok tulajdonságot szeretnénk egyazon objektumról megjeleníteni. szép. é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. nem lehetne egy kicsit központosítani az adatkötést? Természetesen lehet.

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

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

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

3-57 ábra: Adatsablon létrehozása a ListBox elemeihez Ha a következő ablakban (3-58 ábra) megadjuk a sablon nevét. Ezen belül elsőre csak a „Create Empty…” választható. 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. mint ahogy az oldalakét is tettük. Sokszor viszont több adatot is szeretnénk megjeleníteni egy elemről.Az adatok megjelenésének testreszabása adatsablonokkal Mivel a mobilképernyő alapvetően kicsi. hol jöjjön az létre (az erőforrások létrehozásából már ismerős lehet). ha egyetlen tulajdonságot jelenítünk meg. 73 . ezzel hozhatunk létre új adatsablont (3-57 ábra). Ilyenkor használhatunk adatsablonokat (data template). 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. hogy sablont szerkesztünk Itt ugyanúgy rakhatjuk össze a felületet. gyakran elég lehet. hogy jobb gombbal a ListBoxra kattintunk. a tervezőfelület sablonszerkesztési módba vált (3-59 ábra). és azt.

Data Context. A korábban megismert adatkötési eljárással ez is könnyedén megoldható. tehát a fent elkészítettet átadhatjuk egy másik oldal másik ListBox objektumának is. Data Binding…. Egy gomb mindössze.) 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. (Advanced options. 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ó. a vezérlőt leíró osztály csupán a működést definiálja. Azonban ha ez nem elég. A vezérlők kinézetének testreszabása vezérlősablonokkal Adatok megjelenését már testre tudjuk szabni. 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. Appearance és Layout csoportokba a Properties panelen. akár teljesen ki is cserélhetjük megjelenésüket. a kinézetet nem. „valami.3. A Silverlight (illetve eredetileg a WPF) vezérlői „kinézetmentes” (lookless) vezérlők. custom expression. Tartozik hozzá egy alapértelmezett kinézet – 74 . hogy két TextBlock van a sablonban. amire rá lehet kattintani” — esetünkben tapintani.

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

a Text tulajdonság melletti Advanced optionsre kattintva a Template Bindingot kell választani.kell egy kép az Image-nek. melyre adatkötést lehet létrehozni (3-66 ábra). ugyanúgy működik. 76 . Az első probléma egyszerűen megoldható. amelyre éppen alkalmazzák – elvégre egy sablont több gombra is rá lehet majd húzni. Két dolog maradt már csak hátra:   . Ehhez a TemplateBindingot használjuk fel. A TextBlock kijelölése után. A projektbe fel kell vennünk a megjelenítendő képet. esetleg egyszerűen csak nem akarjuk a vezérlősablonban rögzíteni. vagy többnyelvűvé tenni. 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ó. ha a gomb szövege meg is jelenne. A TextBlocknak meg kell mondani. illetve .szeretnénk. mert előre rendelkezésre állt a kép. A megjelenő listában a sablon célvezérlőjének (esetünkben a Button) összes olyan tulajdonságát láthatjuk. Mi a helyzet a felirattal? Azt esetleg változtatni szeretnénk. 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).3. mint a korábbi adatsablon létrehozása. hogy Text tulajdonságában annak a Button vezérlőnek a Content tulajdonságát jelenítse meg.

77 . hogy a sablon már a gombtól veszi a feliratát (3-67). ez pedig elengedhetetlen. 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. 3-67 ábra: A vezérlősablon átveszi a vezérlőtől az értéket Ugyanezeket a lépéseket eljátszva. amelynek egy plusz ImageSource tulajdonságot adunk. 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). Érdemes a képeket Visual Studióban hozzáadni a projekthez. érdemes saját vezérlőt készíteni.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. és az Image vezérlő forrását erre kötjük rá a TemplateBindinggal. illetve a tervezőfelületen látszik. csupán a képeik térnek el.

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). az egyik kép tűnik elő. amelyek két képhez kapcsolódnak olyan módon. próbáljuk meg elkerülni. a másik kép. Ezzel központosíthatjuk a felületleírást. ami a felület megjelenését közvetlenül befolyásolja. Emellett pedig a megnyomott gomb letiltottá válik. hogy olyan kódot írjunk. hogy ha a felhasználó megnyomja az egyik gombot. melyekben leírhatjuk a felület elvárt állapotát bizonyos helyzetekben. 3-69 ábra: A VisualState-eket bemutató program kinézete és szerkezete Ezt az egyszerű logikát leírhatjuk kódban is. ezért először egy csoportot kell létrehozni (3-70 ábra). 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. 78 . Ehelyett a States panelen hozzunk létre két állapotot! VisualState-jeink csoportokba rendezhetők. Vegyük példának az alábbi egyszerű alkalmazást! Két gombból áll. ha a másikat. tehát az alkalmazás egy VisualStateGroupnak egyszerre csak egy VisualState-jében lehet. de ha egy mód van rá.3. és az egyes állapotok közötti váltás is jelentősen leegyszerűsödik a korábbi módszerekhez képest. Az egy csoportban lévő állapotok kölcsönösen kizárják egymást. a másik pedig engedélyezetté (3-69 ábra).

Meg kell oldani. a GoToStateActiont aggathatjuk rá a gombra. akkor más módszerre lesz szükség. hogy egy gomb valamilyen eseménye hatására (nem kell feltétlenül a Clicknek lennie) egy állapotváltást végezzen. amikor ebbe az állapotba lép az alkalmazás. A Behavioröket az Assets panel Behaviors listájában találjuk (3-74 ábra). a vezérlő eltűnik (3-73 ábra). 79 . 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. hanem csak akkor. átadva neki a célállapot nevét). vagyis bármit változtatunk a felületen. hogy deklaratív módon szeretnénk a felületet leírni. A Behaviorök segítségével meglévő vezérlőkhöz rendelhetünk hozzá extra viselkedéseket. 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 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). az nem az alkalmazás normál állapotában fog megjelenni. a tervezőfelület állapotszerkesztési módba vált. de ha tartjuk magunkat ahhoz. Ha például arra van szükségünk. hogy a gombnyomás hatására lefusson az állapotváltás. illetve tilthatjuk. Ha egy állapot szerkesztése közben 0%ra állítjuk az Opacity értékét. 3-73 ábra: Az Opacity beállítása A gombokat az IsEnabled tulajdonság állításával engedélyezhetjük.

miután rádobtuk egy gombra A GoToStateActiont kiválasztva a Properties panelen beállíthatjuk. 80 . hogy mely esemény hatására (EventName) mely állapotba szeretnénk átváltani (StateName).3. 3-75 ábra: A GoToStateAction Behavior. Ennek eredményét az Objects and Timeline ablakban is láthatjuk (3-75 ábra). 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-76 ábra: A Behavior beállítása Ha futtatjuk az alkalmazást. amelyet meghatározunk a gomb számára (3-77 ábra). és rákattintunk valamelyik gombra. az alkalmazás felülete rögtön abba a vizuális állapotba vált.

Ezután csak annyit kell tenni.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. Vagyis az animációkat elég XAML-ben megfogalmazni: „milyen tulajdonságot. Szépen. ha például a kép nem egy pillanat alatt váltana át. és utána (gyakran pixelről pixelre) kirajzolni a vezérlőt. Szebb lenne. és a háttérben az erre optimalizált keretrendszer elvégzi helyettünk a bonyolult kód megírását. mindenféle kód nélkül össze tudjuk állítani a felületet a különböző állapotokban. „átúszna” a másik képbe. Mivel ennek az implementálása értékes időt vett el a fejlesztőtől. abban pedig kiszámolni a vezérlő aktuális elhelyezkedését. de érezhetően kicsit fapados a kinézet működése. amit a felhasználó megnyomhat – és a gombok helycseréje se pillanatszerű legyen. hogy mindig az a gomb legyen felül. hogy gyorsan leírható. hogy a megfelelő állapot legyen kijelölve. A XAML előnye pedig. 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. de nem árt arra ügyelni. dragand-drop módszerrel érhető el. menyi idő alatt. milyen végértékre szeretnék hozni”. amikor a változtatásokat végzi az ember. a Microsoft a WPF-fel előtérbe helyezte azt a megoldást.és a végállapot között. 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 az ehhez hasonló látványelemeket ne imperatív kóddal valósítsa meg a fejlesztő. Vagy például szeretnénk azt elérni. 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. animált. kinézetét a kiinduló. Ennek előnye. hogy mit is szeretne elérni. (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. hanem egy másodperc alatt elhalványulna. hogy minden állapotban a másik állapotba váltó. amikor ennyi nem elég. hanem csak írja le (deklarálja). Maga az animáció egy tulajdonság értékének adott idő alatti megváltoztatását jelenti. engedélyezett gomb legyen felül! Ez a tervezőfelületen. gyorsan.) 81 . hanem látványos.

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

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

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

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

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

Térképek kezelése 4-4 ábra: A térkép. csak az utakra összpontosító nézetet kapunk... függetlenül a Center pozíciótól. " Center="47. ugyanis a térkép Mode tulajdonsága egy olyan objektumpéldányt vár.. 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. és nevezzük is el a térképet! <maps:Map Name="myMap CredentialsProvider="Ajdyq5FaN2RZvzvogm_. A módok közötti váltáshoz egy kicsit többet kell dolgoznunk.. Ez az alapértelmezett mód. AerialMode: Teljes műholdképek.. és XAML kódból a pozíciót leíró koordinátákat is felhasználhatunk az értékadás során. hiszen nem állítottuk még be a nagyítás fokát."/> Ennek hatására a figyelmeztetés eltűnik. amelyeken az előző nézet útvonalai természetesen ugyanúgy ki vannak emelve. Ezt a ZoomLevel megadásával változtathatjuk meg: <maps:Map Name="myMap" CredentialsProvider="Ajdyq5FaN2RZvzvogm_.639655. 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ú. ami a MapMode osztályból származik – ez a megjelenítéshez szükséges 87 . A vezérlő viszont még ezt követően is a teljes világtérképet fogja megjeleníteni. 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. és rendesen használhatjuk a vezérlőt.-122. hanem az ezek alapján készített..129404" ZoomLevel="17" /> Az egyszerűbb felhasználás kedvéért és a tesztelés miatt is érdemes megjeleníteni a ZoomBar gombjait.

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

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.Add(new Pushpin { Location = new System.Device. XAML vagy C# kódból hozzáadogathatjuk a térképhez. -122. csupán a tartalomnak beállított szöveget mutatják az adott pozíción.Children. Egy Pushpin felvétele XAML-ben az alábbi módon történhet: <maps:Pushpin Location="47.639655. amint azt a 4-6 ábra is mutatja. csupán koordináták és kiírandó szöveg megadásával használható vezérlő.-122. viszont szükség esetén a Silverlightban megszokott könnyedséggel testre is szabhatjuk azt.GeoCoordinate(47. Content = "C#" }). Ez egyszerűen. Ezeket a pushpineket akár egyesével. megjelölt pozíciók nélkül.63876.12862).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. Az így kapott jelöléseink végtelenül egyszerűek.Location. címek. de akár dinamikus listákat is köthetünk a vezérlőhöz. 4-6 ábra: Egyszerű Pushpinek a térképen 89 . Ennek eszköze a szintén a Maps vezérlő névtérhez tartozó Pushpin osztály.

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

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

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

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

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 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. így a távoli metódusokat egyszerű függvényhívásokkal érhetjük el programunkból. this. és kiolvassa belőle az elérhető interfészeket és azokon belül a felkínált funkciókat. hogy a környezet a mi saját Solutionünkön belül keressen elérhető szolgáltatásokat.4. } Ezeknél a szolgáltatásoknál szintén szükségünk lesz arra az azonosítóra. 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. de mi itt csak kliens alkalmazást fejlesztünk. RouteServiceClient proxy = new RouteServiceClient(). 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. így erre nem lesz szükségünk. ehelyett egy Credential típusú objektumot is létre kell hoznunk: 94 . Ezt érdemes egy külön változóban tárolni.DataContext = this. amit a Bing Maps regisztrációjánál kaptunk. a MainPage osztály elején. A dialógusban lévő Discover gomb lehetőséget biztosít. Ezt követően példányosítással létrehozhatunk egy proxy objektumot. természetesen a RouteService névteret fel kell vennünk egy using taggal a file elején: public MainPage() { InitializeComponent(). Hozzuk is létre ezt a proxyt a MainPage konstruktorában! Ahhoz. Itt már nem használhatjuk a XAML-ben rendelkezésünkre álló egyszerűsített értékadást. amelynek metódusai a szolgáltatást címzik meg. hogy a keretrendszer megtalálja ezt az osztályt.

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

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

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

ami csakúgy. azonban egy probléma még van: a MainPage nyílik meg először. onnan pedig sehova nem tudunk navigálni! A megoldáshoz nyissuk ki a Properties mappát. Ezen az új oldalon adjunk a ContentPanel nevű Gridhez egy StackPanelt. amivel ezt módosíthatjuk(RemoveBackEntry). nekünk viszont most egyszerűbb lesz. az oldal neve pedig legyen MainMenuPage! A többi sablon is ehhez hasonló szerkezetű. ha ezt relatívra cseréljük. Ezek kipróbálására egészítsük ki az előző alkalmazást egy új oldallal. mint weblapok esetében. a NavigationContext-ből és az előbb említett NavigationService-ből.0. } A Navigate függvény egy URI-t vár. 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. azon belül pedig keressük ki a WMAppManifest. Ezzel a paranccsal címezzük meg a fejezet első részében létrehozott MainPage.4. A PhoneApplicationPage navigációs eszköztára két fontosabb részből áll. 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. azon belül pedig helyezzünk el egy gombot: <Grid x:Name="ContentPanel" Grid.Relative)).xml-t (4-14 ábra)! 98 . amely alapértelmezés szerint abszolút. UriKind. de ez a WP7 esetében mindig false értékű lesz.Row="1" Margin="12. Az első segítségével férhetünk hozzá a QueryString-hez. ami egy főmenüt fog tartalmazni. valamint az ehhez kapcsolódó előrenavigálás. 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. 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. RoutedEventArgs e) { NavigationService. mint például a lap orientációja.12. az URL-ben átadható paraméterek kulcs-érték szótárát jelenti. Haladó alkalmazásfejlesztés Windows Phone-on   Source – A jelenleg aktív vagy mindjárt aktívvá váló oldal címe.Navigate(new Uri("/MainPage.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). azaz a GoForward(Uri) függvény kivételt dob. 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. amelyen keresztül elérhetjük a többi lapot.xaml".

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

OnNavigatedTo(e). a gomb eseménykezelője viszont egy kis magyarázatot érdemel. amivel a verem legutóbbi elemét el tudjuk távolítani.Windows.ItemsSource = NavigationService. úgyhogy új objektumra kell állítanunk az ItemsSource-ot! */ icNavigationList.TryGetValue("myParam".12. sőt a visszalépést is egyszerű függvényhívással megvalósíthatjuk. // 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. if (NavigationContext.BackStack. } icNavigationList. /* nem használtunk adatkötést. Az OnNavigatedTo működése magától értetődő. és töltsük ki a gomb eseménykezelőjét is! protected override void OnNavigatedTo(System.QueryString. RoutedEventArgs e) { NavigationService.0.NavigationEventArgs e) { base. } private void btnDelete_Click(object sender. ami erre az oldalra mutat. 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.Windows. BackStack Az alkalmazásunkon belüli lapváltásokat egy verem tárolja. Haladó alkalmazásfejlesztés Windows Phone-on protected override void OnNavigatedTo(System. Ehhez a veremhez mi is hozzáférhetünk.BackStack. amiről a hardveres Back gomb leveszi a legfelső elemet. A DisplayMemberPath tulajdonság beállításával jelezzük. é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.Text = myParam.NavigationEventArgs e) { base. hogy frissült. } Ha felveszünk valahova egy linket. Mi viszont az egyszerűség kedvéért nem használtunk adatkötést.4. hogy az beállítsa a XAML-ben definiált vezérlők hiányzó értékeit. A RemoveBackEntry függvény törli a navigációs verem felső elemét. Hozzunk létre egy új oldalt Navigation névvel.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.Navigation. és visszanavigál erre az oldalra.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. // saját kód string myParam. Ilyenkor nem elegendő az ItemsSource-ot újra a BackStack- 100 .ToList().RemoveBackEntry().OnNavigatedTo(e). már megfigyelhetjük a NavigationService működését. out myParam)) { tbMyParam. azaz a BackStack nem ad magáról értesítést a megjelenítő vezérlőnek arról.Navigation.Row="1" Margin="12.

úgyhogy a vezérlő sem frissül. amikor a BackStack nem üres. mert a UserControl osztály nem tartalmaz NavigationService-t.microsoft. A dolog varázsa az. A Navigation vezérlő egy Hyperlink.com/winfx/2006/xaml" xmlns:d="http://schemas.xaml-re navigál − akár paraméter átadásával −. és nevezzük el vezérlőnket NavigationBar-nak! Ezt a vezérlőt úgy alakítjuk ki.openxmlformats. hiszen a referencia ekkor nem változik. 4-15 ábra: Az elkészítendő navigációs vezérlő Az ehhez tartozó XAML kód: <UserControl x:Class="_04_Advanced_Development. hiszen ugyanezen verem alapján dolgozik az is.com/expression/blend/2008" xmlns:mc="http://schemas. akkor az előtte lévőre fog a gomb visszavezetni. 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.Navigáció re állítani.microsoft. azaz az alkalmazáson belül is tudunk még visszafelé navigálni.NavigationBar" xmlns="http://schemas. hogy bárhonnan a Navigation. A Vissza gomb pedig csupán akkor aktív. Ehelyett egy új példányra. azzal a kiegészítéssel. ami a paraméter nélküli oldalváltást teszi lehetővé. ami a hardveres vissza gombbal megegyező funkcionalitású. valamint felkínál egy gombot.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.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 . hogy a középső TextBox értékét átadja a megcímzett oldalnak.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. Így ha törüljük a legfelső elemet. Ez azért is érdekes téma. 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. hogy ezzel a törléssel a hardveres Back gomb működését is befolyásoljuk. Komplexebb navigáció megvalósításához olyan felhasználói vezérlőt kell készítenünk. A kész vezérlő megjelenítése a 4-15 ábrán látható. Az Adatok gomb ugyanezt valósítja meg. például a BackStack-ből előálló listára kell állítanunk az icNavigationList-et. amely használja a NavigationService-t. Ennek megvalósításához az Add New Item menüben válasszuk a Windows Phone User Control sablont.

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

horizontálisan elnyúló vezérlő.Pivot és Panorama <local:NavigationBar VerticalAlignment="Bottom" /> Próbáljuk ki alkotásunkat úgy. 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. és megnyomjuk a vissza gombokat! Ha minden jól működik. amelyeket ebben a részben ismerhetünk meg. hogyan tudjuk alkalmazásunkat oldalakkal strukturálni. törlünk párat. majd a végén meglátogatjuk a navigációt összegző lapot. 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 . hogy a beépített alkalmazások többsége is ezek felhasználásával készült el. pontosabban a TemplatedItemsControlból származik (4-17 ábra). Mindkettő az ItemsControlból. nem véletlen. hogy bejárjuk az összes oldalt. A WP7 programok kinézetének meghatározó formálói. A Pivot és a Panorama két nagyon hasonló. 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.

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

Silverlight Toolkit for Windows Phone7 Az eddig bemutatott vezérlőkkel már egy gazdag eszközkészletből válogathatunk. Miután telepítettük a csomagot.Background> <ImageBrush ImageSource="Images/bgPanorama. 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. 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. 105 . beágyazásuk pedig a Background tulajdonság hozzáadásával történik (4-19 ábra): <controls:Panorama. így ennek kipróbálására most nem térünk ki. Ilyeneket könnyen találunk az interneten.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.codeplex. Ezek elvégzését könnyíti meg a Silverlight Toolkit.jpg" /> </controls:Panorama. az elérhető a Visual Studio Add Reference dialógusából (4-20 ábra).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. de számos ismétlődő feladat még így is ránk hárul.com.

dll Ahhoz. hogy az elemeket a XAML-ben is elérjük.Controls. 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.assembly=Microsoft. amelyek az egyszerű navigáción túl információt.Phone. 106 .Phone. 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. 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.Controls. üzeneteket is szolgáltatnak a felhasználó számára (4-21 ábra). nagyszerűen használható menük kialakítására. a már ismert módon adjuk hozzá a névteret a leíráshoz: xmlns:toolkit="clrnamespace:Microsoft.4.Phone.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.Toolkit" Fontosabb vezérlők HubTile – A főoldal lapkáihoz hasonló dinamikus vezérlő.Toolkit.1\Toolkit\Aug11 \Bin\Microsoft. hogy a felsorolt elemek közül többet is kiválasszunk (4-22 ábra).

amelynek egy elemét kiválasztva az lenyílik. é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.Expander> <Rectangle Height="80" Width="400" Fill="Blue" /> </toolkit:ExpanderView.Items> </toolkit:ExpanderView> 107 .Expander> <toolkit:ExpanderView. elem" /> <toolkit:MultiselectItem Content="3. elem" /> <toolkit:MultiselectItem Content="2.Items> <TextBlock Text="Alelem 1" /> <TextBlock Text="Alelem 2" /> </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. elem" /> </toolkit:MultiselectList> ExpanderView – Szintén a leveleknél (pontosabban a hosszabb levélváltásoknál) megszokott lista.

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

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

Haladó alkalmazásfejlesztés Windows Phone-on </StackPanel> <!--ContentPanel .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. 110 .png" Margin="6" Background="#FF008000" GroupTag="TileGroup" Notification="Noti" Message="Microsoft Minősített Szerviz Partner project"> <toolkit:ContextMenuService.0.ContextMenu> </toolkit:HubTile> <toolkit:HubTile Name="hirekTile" Tap="hirekTile_Tap" Title="Hírek" Source="Images/news.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.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.4.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.place additional content here--> <toolkit:WrapPanel x:Name="ContentPanel" Grid.0"> <toolkit:HubTile Tap="hirekTile_Tap" Title="Minden" Source="Images/all.Row="1" Margin="12.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.

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. Végül a Silverlight Toolkit előnyeit ismerhettük meg. azokon belül pedig a Panorama és Pivot vezérlőket.Ö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. az egyszerű címkereséssel és az útvonaltervezéssel. ezek között a kiemelt pozíciók jelölésével. 111 . Ezekkel a módszerekkel nemcsak hogy rendkívül egyszerűen valósíthatunk meg komplex alkalmazásokat. Ezt követően átnéztük a tartalmak rendszerezésére szolgáló műveleteket: az oldalak kezelését.

.

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

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

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

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

0" VerticalAlignment="Top" Width="438" TextWrapping="Wrap" /> </Grid> Hozzunk létre egy új mappát és másoljuk bele az MP3 fájlokat.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. a Zune gyűjteményünkhöz nincs hozzáférése.40. ábra: A projekt struktúrája Következő tennivalónk a zenefájlok átmásolása az Isolated Storage-ba. így Zune-on keresztül a telefonra másolt zenéket ne is próbáljuk meg elérni! Az App. amiket szeretnénk majd lejátszani! Jelöljük ki a zenefájlokat.cs fájlban helyezzük el az alábbi metódust.193.0. 5-6. ábrán látható. 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. 127 . é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.xaml. ehhez hasonló eredményt kell kapnunk. Fontos megemlíteni. hogy az AudioPlayerAgent csak Isolated Storage-ban és távoli elérési úton elhelyezett audio fájlokat tud lejátszani.Folyamatok a háttérben <StackPanel Orientation="Horizontal" Width="420" Margin="18.18.

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

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

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

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

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

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

try { // a háttérben beütemezzük a letöltést BackgroundTransferService. ez egy olyan sorként képzelhető el. request. esetleg Wifin keresztül kívánjuk ezt lehetővé tenni. és a HTTP protokoll melyik igéjét szeretnénk hozzá használni.5. Az egyik a BackgroundTransferRequest. Uri transferUri = new Uri( Uri. Uri downloadUri = new Uri( "shared/transfers/" + downloadFile.RelativeOrAbsolute ). 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. így egy olyan helyi elérési útra is szükségünk lesz.DownloadLocation = downloadUri. A BackgroundTransferRequest objektumnak meg kell adnunk. request. és így tovább. Két objektumtípus segít bennünket ezeknek a feladatoknak a megvalósításában. request. amely leírja magát a kérést egyetlen távoli állományra mutatva. hogy milyen beállítások mellett szeretnénk az adatforgalmazást engedélyezni. hogy honnan kell a letöltést végeznie.AllowCellularAndBattery. Azt is megadhatjuk.gl/9dkcY". A következő kódrészlet a Silverlight 4. //megadjuk. BackgroundTransferRequest request = new BackgroundTransferRequest( transferUri ). Ilyen beállítás például az.0 fejlesztőknek című könyv PDF változatát tölti le a háttérben: // Silverlight 4.Add(request). 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.Method = "GET". hanem mondjuk GPRS vagy EDGE módban működünk.0 fejlesztőknek könyv pdf-ben string transferFileName = "http://goo. 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. Ha a beállításokkal végeztünk. } catch(Exception ex) { // ha valami probléma volt } 134 . esetleg várjunk töltő csatlakoztatására.Substring(transferFileName. UriKind. amely egyesével végrehajtja az átadott letöltés-kéréseket.TransferPreferences = TransferPreferences. A másik a BackroundTransferService. ahova ezeket a Windows Phone bemásolhatja.LastIndexOf( "/" ) + 1 ). hogy a letöltések szüneteltetésre kerülnek. hogy hova töltse le a fájlt string downloadFile = transferFileName. akkor ez előfordulhat). hogy csak a celluláris hálózaton. akkor a kivételkezelést figyelembe véve megkezdhetjük a letöltést a BackgroundTransferService objektum segítségével. UriKind.RelativeOrAbsolute ).EscapeUriString( transferFileName ).

hogy semmilyen esetben se veszhessenek el a felhasználó munkafolyamataihoz tartozó adatok. amelyre eddig csak nagyon nehézkesen vagy esetleg egyáltalán nem találhattunk megoldást. 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. és arról gondoskodnak. hogy nem végezhetünk akármit szabadon a háttérben. 135 . 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. 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. Láthattuk. Az elméleti bevezetést követően gyakorlatban is láthattuk azokat a lépéseket.

.

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

amit legegyszerűbben a Windows Phone Pivot Application projektsablon kiválasztásával (6-2 ábra) helyezhetünk el alkalmazásunkban. fejezetben bemutatott Pivot vezérlő. érdemes ezek mentén külön lapokra bontani a megjelenítési felületet is. 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. 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. 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. de a platform többi részével konzisztens megoldást is biztosít. Ez a felhasználó számára sokkal egységesebb rendszerképet és könnyebb kezelhetőséget garantál. 138 . akkor nemcsak egyszerűbb a taszk használata.6. amely feladatát egy-egy beépített vezérlő is képes ellátni. Amennyiben viszont nincsenek egyedi igényeink a funkcióval kapcsolatban.

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. hogyan tudjuk az MVVM modellnek megfelelően szervezni kódunkat. hogy ezt a forrást a tervező eszközök meg is jelenítsék. Ilyen adatforrás például a SampleData MainViewModelSampleData. mivel példát mutat arra. logika.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. 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. A ViewModels mappa fogja össze azokat az osztályokat. 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 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). megjelenítés).1-es verziót. Ahhoz. amelyek az egyes oldalak.xaml állománya. 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 . és kihasználja a Silverlight által biztosított adatkötési mechanizmust.

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

ViewModel.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. és ami mögötte van című könyv 10.0. hiszen ezzel biztosítható az.0. 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 .A példaalkalmazás létrehozása <TextBlock Text="{Binding LineOne}" TextWrapping="NoWrap" Margin="12. egyet a launcherek és egyet a chooserek számára. } // Adatok betöltése. private void MainPage_Loaded(object sender. this.ViewModel.ViewModel. amint elkészült az oldal. hogy a panel görgethetővé válik. Minden taszk indítására vegyünk fel külön gombot. 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.LoadData(). } } A generált projekt megvizsgálásával egy kis betekintést nyerhettünk az MVVM architekturális minta használatába. fejezete tökéletes kiindulópontot jelent a tanuláshoz. akkor a Silverlight 4: A technológia.0. Az oldal kontextusát a MainPage konstruktora állítja a megfelelő ViewModelre: // Constructor public MainPage() { InitializeComponent().0" Style="{StaticResource PhoneTextSubtleStyle}"/> </StackPanel> </DataTemplate> </ListBox. RoutedEventArgs e) { if (!App.-6.0" Style="{StaticResource PhoneTextExtraLargeStyle}"/> <TextBlock Text="{Binding LineThree}" TextWrapping="NoWrap" Margin="12.IsDataLoaded) { App.Loaded += new RoutedEventHandler(MainPage_Loaded). ezek pozicionálását pedig bízzuk egy StackPanelre! A StackPanelt viszont mindenképpen egy ScrollVieweren belül definiáljuk. // Adatkötés DataContext = App.

de vizuális elemeket ez sajnos nem tartalmazhat. némítási lehetőségekkel. // ezt nem kötelező megadni phoneCallTask. a kihangosítási.Show(). csupán az érintett tulajdonság különbözik. fejezet részletesen taglalja. mivel ezeket a 12. 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. RoutedEventArgs e) { PhoneCallTask phoneCallTask = new PhoneCallTask(). de ennek hiánya sem okoz problémát: private void btnPhoneCallTask_Click(object sender. 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).6. hiszen működésük teljesen azonos. de így is megadhatjuk a számot phoneCallTask.DisplayName = "WP7 support". } A Show() metódus elindítja a taszkot. phoneCallTask. majd a hívást összegző üzenetet láthatjuk (6-4 ábra). // a tagolás nem kötelező. 142 . Emellett egy nevet is megjeleníthetünk.PhoneNumber = "00361/123-4567". Launcherek PhoneCallTask Telefonhívás indításakor kötelező megadni a hívandó telefonszámot. A hívás lebonyolítása a megszokott felületen történik. 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. 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.

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

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

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

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

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

MessageBox. RoutedEventArgs e) { PhoneNumberChooserTask phoneNumberChooser = new PhoneNumberChooserTask(). phoneNumberChooser.Format("Név: {0}\nTelefonszám:{1}".DisplayName.Show(string. ami megvizsgálja és az általunk definiált eljárás alapján jelzi a visszatérési értéket. } }.Error == null && result.PhoneNumber. Ha itt kiválasztunk egy partnert. A Completed eseménykezelő második paramétere egy PhoneNumberResult példány. 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. amin keresztül elérhetjük a kiválasztott partner nevét és telefonszámát (611 ábra): private void btnPhoneNumberChooserTask_Click(object sender.Completed += (s.6. number)). Ekkor fut le az általunk definiált eseménykezelő.Show(). name. phoneNumberChooser. 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. akkor a telefonszám mentésére lehetőséget biztosító oldal következik.TaskResult == TaskResult. string number = result. viszont ez a taszk már adatot is szolgáltat a hívó alkalmazás számára. 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. result) => { if (result.OK) { string name = result. A folyamat a 6-10 ábrán tekinthető meg. } 6-11 ábra: A kiválasztott partner neve és telefonszáma 148 . ahonnan a Back gomb megnyomásával térhetünk vissza a taszkot indító alkalmazásba.

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

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. // lehetőséget adhatunk a kamera taszk indítására is egy gomb engedélyezésével photoChooserTask. // dimenziók beállítása photoChooserTask. a Contacts és az Appointments osztály érhető el. Az új fejlesztői készletben megjelent ugyanis a PhoneDataSharingContext osztály.SetSource(result. BitmapImage bmp = new BitmapImage().Show(result.OriginalFileName != null) { MessageBox. és csupán az ezen belül található képrészt adja majd vissza alkalmazásunk számára (6-13 ábra).Completed += (s.Source = bmp. a találatokat pedig generikus listán szolgáltatja a hívó alkalmazásnak. bmp. imgResult.ChosenPhoto). result) => { if (result.6.TaskResult == TaskResult. } }. így a taszk lehetőséget kínál egy ekkora terület kijelölésére. Jelenleg két implementációja.PixelHeight = 50. RoutedEventArgs e) { PhotoChooserTask photoChooserTask = new PhotoChooserTask().Show(). photoChooserTask. 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.ShowCamera = true.OK && result. photoChooserTask.OriginalFileName). Alapvető telefonos funkciók használata private void btnPhotoChooserTask_Click(object sender. 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 . } A példakódban egy 50 pixel magas és 200 pixel széles képet szeretnénk beolvasni. photoChooserTask.PixelWidth = 200. ami egy kijelölt tárterületen képes lekérdezéseket futtatni.

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

SearchAsync("c". A függvény futásának eredménye a 6-14 ábrán látható.Companies. de természetesen a keresés ettől függetlenül felhasználók listáját adja vissza. // csak a nevek között keresünk contacts. ahol a tulajdonságok többsége szintén egy IEnumerable példány.Results. string birthday = contact.Companies. birthday. MessageBox.JobTitle. contacts. // megjelenítés string formatStr = "Name: {0}\nCompany: {1}\nTitle: {2}\n" + "Birthday: {3}\nSignificantOther: {4}\nNote: {5}".DisplayName.SignificantOthers.FirstName. }.).SearchCompleted += (s.Notes. significantOther. bmp. string significantOther = contact. // egyéb adatok string name = contact. note)). FilterKind. company. // felhasználó képének lekérése BitmapImage bmp = new BitmapImage(). name. title.6.Source = bmp.First(). 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.First().First(). sajnos az emulátoron mindig egy üres listát fogunk visszakapni. } A fenti kódban minden listának csak az első elemét kérdeztük le.SetSource(contact. stb.First(). 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. Facebook. string title = contact.CompleteName. null).First().Birthdays.ToShortDateString(). result) => { var contact = result.GetPicture()).CompanyName. string company = contact. Hotmail. viszont mivel ezek az adatok mindenképpen felhasználói fiókhoz kötődnek (Live.First(). imgDataSharing.Show(string. A bejegyzést megtestesítő Appointment osztály főbb tulajdonságai a következő táblázatban láthatók: 152 . RoutedEventArgs e) { Contacts contacts = new Contacts(). string note = contact.Format(formatStr.

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

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

hogy a kamera váltása megtörtént.6. így a MediaLibrary típusú library objektumot a CameraViewModel osztályban deklaráljuk: // Microsoft. A mentés akkor történjen.Frameword dll! MediaLibrary library = new MediaLibrary(). Kép készítésekor a gomb egy időre inaktívvá válik.Xna. majd a feldolgozás végén egy üzenetablakban kapunk értesítést a feladat befejeződéséről (6-18 ábra). Az osztály a Microsoft. amikor a kép már elkészült. amelyen keresztül hozzáférhetünk a telefonon tárolt zenékhez és képekhez. ezt cseréljük most ki az alábbiaknak megfelelően: 160 .Framework szerelvény része. hogy a kapott képpel kezdjünk is valamit. 6-18 ábra: Értesítés a feldolgozás befejeződéséről Már csak annyi maradt hátra. például tároljuk el a készülék médiatárában. ezért hivatkozzunk erre a dll-re projektünkben! A tárolás szintén a ViewModel dolga. Ehhez egy MediaLibrary példányra lesz szükségünk.Xna. amiből tudhatjuk. ahol korábban már egy // TODO: mentés megírása sort hagytunk. A mentés helye a CaptureImageAvailable eseménykezelő. 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. 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.

// mentés a médiatárba library.Show(name + " mentve!"). 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. az előlapon lévő kamera képét ugyanis egy bal oldalra mutató sárga pötty. 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. 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.Összefoglalás Camera. e. Az én emulátoromon például a 6-19 ábra művészeti remekművei készültek. míg a hátlapon lévőét egy felfelé mutató jelképezi. A fejezet végén pedig egy példaalkalmazás írásán keresztül láthattuk.Now.Dispatcher.jpg". Ezt követően megnéztük a partner. Végigvettük az erre kínált taszkokat. Deployment.SavePictureToCameraRoll(name. // újra fotózhatunk IsPhotoEnabled = true.BeginInvoke(() => { // visszajelzés küldése (UI szál) MessageBox. A funkció működését a fejezet korábbi részeiben bemutatott PhotoChooserTask segítségével ellenőrizhetjük.ImageStream).ToShortTimeString() + ". Összefoglalás A fejezet során rengeteg olyan lehetőséggel ismerkedtünk meg.é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. 161 . e) => { string name = DateTime.CaptureImageAvailable += (s. }. }).Current. amelyek egyszerű hozzáférést biztosítanak a telefon valamely funkciójához.

.

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

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

) 7-2 ábra – A Hold (és a Tap) esemény hatása 165 . (Emellett persze továbbra is működik a Tap. tehát ha 1 mp-en belül felengedjük az ujjunkat.. akkor elfordul a négyzet. } Tesztelésnél látható.Height += 20. hogy a négyzet nyomva tartása (Hold) esetén a négyzet nagyobbra nőjön. Oldjuk meg azt is. </Rectangle> Az eseménykezelőben növeljük meg a négyzet méretét! private void rect_Hold(object sender.5.. Így megkímélhetjük magunkat a sok típuskonverziótól. rect. hogy a Hold esemény hatására a négyzet 20-20 képpontonként nő.. egyszerűbb.5"> . GestureEventArgs e) { 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. 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=". ha adunk neki egy nevet az x:Name tulajdonságon keresztül.Width += 20.

További telefonos funkciók használata A DoubleTap megoldása is az előbb leírtakat követi.Angle = 0. 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=". hogy szintén a ManipulationStartedEventArgs része a Complete metódus.RenderTransform). amit megnyomtak.. Ennek ManipulationContainer tulajdonsága megadja.7. ((RotateTransform)rect.Width = 100. Az események második szintje a többpontos (multitouch) érintések kezelését is lehetővé tevő úgynevezett Manipulation események csoportja. az operációs rendszer lezártnak tekinti a manipulációt. A Windows Phone-nal felszerelt telefonokban alapkövetelmény a legalább négy érintési pontot kezelni képes kapacitív kijelző.Height = 100. rect.RenderTransform> <RotateTransform Angle="0"/> </Rectangle. hogy előre megfontolt szándékkal egyszerre több ujjával is megérintse a kijelzőt. amikor a felhasználó megérinti a kijelzőt. 166 . illetve a ManipulationOrigin tulajdonság. nem a ManipulationDelta. hogy mely objektumhoz viszonyítva történik a manipuláció (ez maga a manipulált objektum). 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. hanem a ManipulationCompleted esemény fut majd le. Ehhez nem kell több ujját használnia – már egy érintéstől is kiváltásra kerül az esemény. 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. tehát ha a felhasználó továbbra is a kijelzőn tartja ujját. } Multitouch manipulációk Az előző események egyetlen ujj érintését jelzik vissza felénk. ha többérintéses eseményeket szeretnénk tesztelni – az emulátor nem támogatja a több érintést.5"> <Rectangle.5. Ennek egyik paramétere egy ManipulationStartedEventArgs típusú objektum. Készítsük be a telefont.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. Hasznos lehet még tudni. GestureEventArgs e) { rect. Ha ezt meghívjuk. így elviekben semmi nem gátolja a felhasználót abban.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

ApplicationSettings. object>>. set. Contains(string key). 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 ICollection Keys { get.IO névtérre lesz szükségünk.IO. TryGetValue<T>(string key. "Attila"). amely egy kulcs/érték párost tud tárolni. í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). object>. ICollection. Mivel ez egy Dictionary.Add("UserName". out T value). ICollection<KeyValuePair<string. a második paraméter pedig egy tetszőleges objektum lehet. } public ICollection Values { get. Remove(string key).ArgumentException-t kaphatunk. Ha már létezik a kulcs. ezért a rá vonatkozó szabályok élnek. a 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. IEnumerable { public static IsolatedStorageSettings ApplicationSettings { get. TValue> objektum.IsolatedStorage névtérre. IEnumerable<KeyValuePair<string. ebben az esetben az első paraméter egy kulcs. } public int Count { get. akkor egy System. IDictionary.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. aminek egyedinek kell lennie. object value).IsolatedStorage { public sealed class IsolatedStorageSettings : IDictionary<string. és ezeket az értékpárokat az adott alkalmazás IsolatedStorage-ébe menti el. hogy az IsolatedStorage-et elérjük. object>>. Ahhoz. a fájlművelethez pedig a System. Az 189 .. Az alábbi kódrészlet az IsolatedStorageSettings felépítését mutatja be: namespace System.IO. } public public public public public public } } void void bool bool void bool Add(string key. Clear(). Save(). } public object this[string key] { get.

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

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

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

-7. és mentsük el az értékét! 193 . majd kattintsunk a Start gombra az emulátoron. Ehhez készítsük el a felhasználói felületet.0" Style="{StaticResource PhoneTextTitle1Style}"/> Ha elindítjuk az alkalmazást (6-3 ábra).0. és láthatjuk.6. SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.MainPage" . és a Text tulajdonságát kössük az ApplicationTitle-höz. Mode=TwoWay}" Height="72" HorizontalAlignment="Left" Margin="6.Application Settings <phone:PhoneApplicationPage x:Class="PhoneAppTest.0.. az a háttérben tárolásra fog kerülni.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.. <TextBox Text="{Binding ApplicationTitle. amint azt a 8-3 ábrán láthatjuk. ekkor az alkalmazás háttérbe vonul! Az emulátoron újra indítsuk el az alkalmazást. és a szövegdobozba beírunk valamit. 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. azaz a kötés kétirányú. Írjunk oda egy tetszőleges szöveget.IsVisible="True" DataContext="{StaticResource MySettings}"> Ezt követően az oldalra helyezzünk el egy TextBox-ot. Ebben az esetben a Binding módja TwoWay.

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

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

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

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

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

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

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

exe dir xd d25bf842-f28d-45ff-9a4d-6057e6614321 (Amennyiben fizikai készülékről szeretnénk lekérdezni ezeket az információkat. Keressük ki a ProductID-t a WPAppManifest.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. hogyan másolhatunk fájlokat a telefonról a fájlrendszerünkre! Ezzel a funkcióval lementhetjük az alkalmazásunk mappáját. nézzük meg. Indítsuk el az alkalmazást az alábbi módon: ISETool. az „xd” helyett „de” kapcsolót kell használnunk.) Ne felejtsük el átírni a saját ProductID-nkat! Az eredményt a 8-7 ábrán láthatjuk. például (8-8 ábra): 201 .xml fájlból: <App xmlns="" ProductID="{d25bf842-f28d-45ff-9a4d-6057e6614321}" Title="PhoneApp2" 3. ahová másolhatunk vagy írhatunk fájlokat az IsolatedStorage-ből. Ehhez mindösszesen a következő parancsot kell kiadnunk: ISETool. és a helyi gépünkön szabadon megvizsgálhatjuk azok tartalmát. Listázni már tudunk. 8-7 ábra: Mappák és fájlok listázása emulátoron 6. Nyissunk meg egy parancssort! 4.1\Tools\IsolatedStorageExplorerTool 5. Készítsünk egy egyszerű Windows Phone 7 alkalmazást! 2.exe ts <xd|de> <Product GUID> <desktop-path>.xml) Egy könyvtár a számítógépünkön. 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.

Adatkezelés ISETool.microsoft. azt –ugyanúgy. olyan eszköz is létezik. mint az Isolated Storage esetén − nem oszthatjuk meg a többi alkalmazással! Linq To SQL A Linq To SQL egy ún.msdn. és azokat lefuttassuk az adott adatbázismotoron. Ezt a kiegészítőt a következő oldalról tölthetjük le: http://visualstudiogallery.0 –ás) változatában nem volt beépített lehetőség.NET Framework tartalmaz. amely szintén lehetőséget biztosít arra.8.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. sőt. az alkalmazásba beépülő módon működő relációs adatbázis-kezelő. a Mango frissítéssel viszont az Isolated Storage-ben az alkalmazásunk elhelyezhet relációs adatbázist is.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. hogy adatokat töltsünk le a telefonunkról (vagy emulátorunkról a számítógépünkre). Az SQL Servernél megszokott Transact SQL segítségével közvetlenül nem érhetjük el az adatbázist. hogy ez működjön. hogy kódunkban beágyazva fogalmazzunk meg lekérdezéseket. amelyet a . hogy a gépünkről töltsünk fel adatokat a telefonon futó alkalmazásunk könyvtárába. és így objektumorientált módon kezelhetjük adatainkat. Ezt az adatbázist csak a Linq To SQL API segítségével érhetjük el. Ezt Microsoft SQL Server Compact Edition (CE) teszi lehetővé. amely a Visual Studio-ba épül be. Az adatbázist csak saját alkalmazásunk írhatja és olvashatja. A Linq To SQL lehetőséget biztosít arra. Ahhoz. ORM (Object Relational Mapping) keretrendszer. Ilyen eszköz például az Isolated Storage Tool (8-9 ábra). az 202 . amely egy fájl alapú. illetve lehetőséget biztosít arra is.

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

Válasszuk a Windows Phone OS 7. kézzel írjuk be! Az URL-t jegyezzük meg. majd kattintsunk a Go gombra! (Fontos.1 (vagy valamelyik újabb) változatot! Ahhoz. Referencia felvételéhez kattintsunk jobb gombbal a projekt nevére (WebServiceClientSample) a Solution Explorer ablakban. ha a szerveroldalon Windows Azure-t használunk. é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. és írjuk meg a szervert meghívó Windows Phone alkalmazást! Ehhez nyissunk egy új Visual Studio projektet. Most térjünk át a kliensoldalra.svc elérési útnak viszont szerepelnie kell. hogy használhassuk a webszolgáltatást. és kattintsunk az OK gombra! 221 . fel kell rá vennünk egy referenciát. neve pedig WebServiceClientSample! A projekt létrehozását követően a Visual Studio megkérdezi majd.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. Jelenleg egy ilyet tartalmaz a webszolgáltatásunk: az imént megírt Translate() metódust. E művelet során olvassa majd be a Visual Studio a szerverünk által publikált leíró állományt. hogy webes projektünknek még futnia kell!) A Visual Studio letölti és feldolgozza a megcélzott webszolgáltatás adatait. Adjunk egy nevet a referenciának (SampleServiceReference). amely legyen Windows Phone Application típusú. akkor ellenőrizzük az URL-t! A localhost nevet követő portszám véletlenszerűen generált. ha nincs ott. és készíti el a bevezetőben említett proxy osztályt. 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). hogy a telefon melyik verziójához készítjük a projektet. A /SampleService. és minden gépen más lesz. 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.

amely MainProgressBar névre hallgat és alapértelmezésként nem látható. elég csak ki-be kapcsolnunk). és tulajdonságait elhelyezi egy új fájlban. é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. 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. Most kattintsunk duplán a gombra. Kommunikáció szerverrel 9-3 ábra: A Service Reference-hozzáadó ablak A Visual Studio legenerálja a proxy osztályt. 222 . akkor ebben az állományban kell átírni a webszolgáltatás URL-jét a végleges címre. Ezenfelül.9. bekapcsoljuk a ProgressBar-t: private void TranslateButton_Click(object sender.ClientConfig néven találjuk meg projektünkben. Ezért meghívásához először feliratkozunk arra az eseményre. ami a Windows Phone „mozgó pontjait” generálja.SampleServiceClient client = new SampleServiceReference. hogy belépjünk a Click eseménykezelőjébe! Kódunknak meg kell hívnia a webszolgáltatást. amikor a telefon dolgozik valamin)! A ProgressBar nem látható az eszköztáron. de amint korábban már szó volt róla. client. ezért kézzel kell hozzáadnunk alkalmazásunk XAML kódjához. Ha alkalmazásunkat élesben szeretnénk felhasználni.TranslateCompleted += new EventHandler<SampleServiceReference.TranslateCompletedEventArgs>( client_TranslateCompleted). a webszolgáltatás aszinkron. 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>). hogy épp hány százalékon áll. 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. Ezt ServiceReferences.SampleServiceClient(). ami a kérés befejezését jelzi majd. RoutedEventArgs e) { SampleServiceReference. aztán ténylegesen elküldjük a kérést.

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

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

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

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

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

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

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

Ismerjük meg ezeket részletesebben! 230 . a SharePoint. egymástól több száz kilométerre lévő adatközpontba is szétmásolja.odata. amint később azt látni fogjuk. Mindhárom szolgáltatásra igaz. valamint a protokollal kapcsolatos részletes információk és a fórum. 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. illetve feltölthetünk egyszerű táblajellegű információkat. 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. hogy az Azure a feltöltött adatokat három példányban tárolja. ráadásul két. 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. 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. ráadásul egyszerű objektumorientált API-n keresztül. Az Azure Storage háromféle szolgáltatást nyújt: tárolhatunk benne fájlokat (Blob Storage). Aki szeretné jobban megismerni az OData protokollt. létrehozhatunk benne aszinkron kommunikációra alkalmas várakozási sorokat (Queue Service). Az itt megtanultak alapján már tudunk egy ODatafogyasztásra képes alkalmazást készíteni. hogy mindhárom tárhelyszolgáltatás alkalmas komoly. 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.9. a Netflix és még sokan mások. mert rengeteg Microsoft-termék és számos külső gyártó már most támogatja! Ilyen például az SQL Azure. Érdemes megismerkedni a protokollal. melyre alkalmazásunk egy webszolgáltatáson keresztül tölti fel az anyagokat. az látogasson el a http://www. professzionális alkalmazások kiszolgálására is. így a véletlen adatvesztés gyakorlatilag kizárt. Ez utóbbi nem váltja ki az SQL szervert. egy telefonkönyv (Table Service). mint pl. 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. Ezeket az igényeket természetesen megoldhatjuk egy saját szerverrel. Így elmondhatjuk. az eBay.org weboldalra.

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

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

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

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

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

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

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

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

a teljes API az Azure és a Toolkit honlapjain ismerhető meg. Jelen sorok írásakor a tárhelyszolgáltatás árai a következők:  A feltöltés ingyenes. Így ha használni szeretnénk valamelyik tárhelyszolgáltatást. 9-11 ábra: Entitásunk a Table Service-ben Ezzel megismertük az Azure Storage harmadik szolgáltatását is. tábla vagy fájl) egy hónapig: 14 dollárcent.  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/. A Table Service segítségével költséghatékony. hogy szolgáltatásait önállóan is igénybe vehetjük. 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. 239 .  Egy gigabájt adat letöltése: 15 dollárcent. és jellemzően egyre olcsóbb lesz. amit használunk. majd a már látott módon nyissuk meg a myazurestorage. 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.Adattárolás Windows Azure-ban } catch (Exception ex) { this. 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.ToString())).Dispatcher.BeginInvoke(() => MessageBox.microsoft. Az Azure árazása folyamatosan változik.Show(ex. } } Teszteljük az alkalmazást! Indítsuk el. Árazás A Windows Azure platform fontos jellemzője.com oldalt! A Tables fülön megtaláljuk majd a phonetest1 táblát. és azon belül az elmentett entitásunkat (9-11 ábra).  10 ezer elemi írási/olvasási művelet: 1 dollárcent. rendkívül skálázható módon tárolhatunk táblajellegű információkat.

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

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

Kattintsunk a Password elemre. és másoljuk ki az ott megjelenített értéket (9-14 ábra)! 9-14 ábra: Access Control szolgáltatásunk menedzsment-jelszava 242 . 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.9. 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.

Mellette külön indítsuk el a Windows Phone alkalmazást is: jobb gombbal kattintsunk az AcsSample. hogy az ACS (az Azure többi szolgáltatásához hasonlóan) önállóan is igénybe vehető. hogy projektünket újra be kell tölteni. Érdemes utánaolvasni a Toolkit honlapján és az Azure dokumentumaiban. ráadásul használata meglehetősen olcsó. Ha ez megtörténik. vagy a készülék képességeinél sokkal nagyobb erőforrásigényű feladatokat is elvégezhet. és közösségi szolgáltatásokat nyújthat. így érdemes elgondolkodnunk alkalmazásán! Összefoglalás A fejezetben megismertük. és a Debug almenüből válasszuk a Start new instance menüpontot! A telefonalkalmazás megnyílik.Ö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. 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 . majd kattintsunk az OK gombra! A varázsló létrehozza az alkalmazássablont. í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. Ez egy komplex műveletsor. a Reload gombra kattintva hagyjuk jóvá a műveletet! Alkalmazásunk rögtön kész is a tesztelésre. A kód létrehozása után kaphatunk egy Visual Studio figyelmeztetést. 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.Phone projekt nevére. 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. Indítsuk el az F5 gombbal! Ennek hatására beindul a szerveroldali komponens az Azure emulátorban. és bejelentkezhetünk az általunk választott hitelesítés-szolgáltató segítségével. Vegyük figyelembe.

.

mintha 245 . például minden folyamatban lévő játszmához egy-egy. hanem a telefonon futó alkalmazásunknak akarunk üzenni. A lapkák a telefon kezdőképernyőjén kapnak helyet. hogy egy külső eseményről nem a felhasználót szeretnénk tájékoztatni. Ezek az üzenetek a felhasználó aktuális tevékenységétől függetlenül mindig megjelennek. ahogyan azt a 10-2 ábra illusztrálja.10. fontos eseményekről maradna le. szöveget vagy számot jeleníthetünk meg. 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). melyek tartalmát a fejlesztő szabadon változtathatja – ahogyan azt a 10-1 ábra mutatja. A platform eszközeivel erre is lehetőségünk van. 10-1 ábra: Windows Phone lapkák A lapkákon képeket. 10-2 ábra: Felugró üzenet Végül az is lehet. akkor sokkal gazdagabb élményt kínálhatunk. az alkalmazás futása nélkül is. 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. A fejezetben részletesen megismerkedünk a lapkák és a további értesítési szolgáltatások képességeivel. Ha ezeket jól tudjuk használni. Alkalmazásunkhoz akár több lapka is tartozhat. programozásával. hanem nagyméretű lapkákból. így ha más módon nem tudnánk üzenni a felhasználónak. amelyeket esetleg egy szám megjelenítésével dinamikussá lehet tenni. Frissíthetjük őket az alkalmazás futtatása közben. de akár szerveroldalról. 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. A telefon kezdőlapja nem élettelen ikonokból áll.

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

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

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

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

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

png". akkor a telefon azt átméretezi majd nekünk. é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. A sor végén található UriKind. AppTileBackground néven! Térjünk vissza a Visual Studióba. vagy akár egy képfájlra mutató internetes URL-t is megadhatunk. tileData.. majd az Add menüből válasszuk az Existing Item. UriKind. mint beírni a tileData adatstruktúrába az így létrehozott kép URL-jét. 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. Ez adja meg. 251 . már nincs más dolgunk.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. 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.Relative). hogy a frissen megadott fájlt tartalomként akarjuk használni – ezután tudunk majd kódból hozzáférni. A Solution Explorer-ben jelöljük ki a frissen beszúrt fájlt. hogy az URL relatívként értelmezendő.. Mentsük el a képet PNG vagy JPG formátumban.Relative paraméter nagyon fontos. és a Solution Explorer ablakban kattintsunk jobb gombbal a projekt nevére (LocalTileApiSample). a program hibára fut. Ha ezt nem írjuk be. menüpontot (10-10 ábra)! Tallózzuk ki az imént létrehozott képet. statikus képet is helyezhetünk.BackgroundImage = new Uri("/AppTileBackground.

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

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

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

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

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

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

fix alkalommal vagy határozatlan ideig)? Milyen gyakran történjen meg a frissítés (óránként. Írjunk egy rövid példaprogramot. hogy ehhez még külső szerverre sincs szüksége. a többi tulajdonság ezen az API-n keresztül nem módosítható. Ehhez kódunkat helyezzük a MainPage() konstruktorába.10. hanem egy kiszolgálón állítjuk elő. 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. 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. A ShellTileSchedule arra ad lehetőséget. naponta. 258 . imperatív módon tudtuk frissíteni lapkáinkat. alkalmazásunk leállását követően is.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. azaz nem használhatunk a telefonon lévő helyi erőforrásokat. ha a szükséges tartalmat nem a készüléken. hogy a megjelenítendő információt szerveroldalon készítsük elő. Ha az időzített művelet végrehajtása 3 egymást követő alkalommal sikertelen. óránként szeretnénk frissíteni. közvetlenül az InitializeComponent() metódushívás után! Lapkánkat határozatlan ideig. a telefon pedig egyszerűen csak letöltse azt. 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. hogy a felhasználó a kezdőképernyőre tűzve tartsa alkalmazásunkat. amelyek utána a háttérben futnak majd. Bizonyos esetekben azonban kényelmesebb lehet. Windows Phone OS 7. Használatához (a Background Agent-hez hasonlóan) alkalmazásunk futása közben időzítenünk kell a frissítéseket. szerver igénybevétele nélkül. 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. Egy folyamatosan frissülő lapka pedig jó ok arra. 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. A képfájl maximum 80 kilobájtos lehet. és letöltése nem tarthat 30 másodpercnél tovább. Időzítés beállítása az elsődleges lapkára Korábban megismerkedtünk a lapkák tulajdonságaival. A Background Agent nagy előnye. akkor az időzítést törli a futtatókörnyezet. Mindkét módszer segítségével a telefonon futó kódból. 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.

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

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

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

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

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

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

de ha a Visual Studio Express verzióit használjuk. using System.A Push Notification szolgáltatás Ezt létrehozhatjuk a már megnyitott Visual Studio példányban is. amit megjelenítünk majd a lapkán! A gombbal kezdeményezzük a küldést. 10-19 ábra: A Default.NET Empty Web Application. mert a telefonos fejlesztésre használt Visual C# Express nem támogatja a webfejlesztést. valamint egy címkét ResponseLabel néven! Az első szövegdobozba kerül majd az MPNS által visszaadott URL. a lapkák korábban megismert valamennyi tulajdonságát frissíthetjük. //Előállítjuk az üzenetet. 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.Text + "</wp:Title>" + "<wp:BackBackgroundImage></wp:BackBackgroundImage>" + 265 . ahová üzenetünket küldjük majd.Text. Amint a példakódban levő XML-ből látjuk.aspx néven! A Visual Studio automatikusan megnyitja az űrlap HTML nézetét. kódunk ezért először felépíti ezt az XML struktúrát. Default. egy gombot SendTileButton néven és „Lapkafrissítés küldése” felirattal. a címkébe pedig a visszatérési értéket helyezzük majd el. A fentiek elvégzése után az űrlapnak a 10-19 ábrához kell majd hasonlítania. Ha valamelyik XML tulajdonságot üresen hagyjuk. A projekt típusa legyen ASP. ehhez a Visual Web Developer Express-re van szükségünk.0\" encoding=\"utf-8\"?>" + "<wp:Notification xmlns:wp=\"WPNotification\">" + "<wp:Tile>" + "<wp:BackgroundImage></wp:BackgroundImage>" + "<wp:Count></wp:Count>" + "<wp:Title>" + MessageTextBox. 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 az nem változik a lapkán.Net. string tileMessage = "<?xml version=\"1. A második szövegdobozba írjuk üzenetünket.aspx oldal a vezérlőelemekkel Következik a szerveroldali kód megírása. neve PushNotificationServerSample ! A projekt létrejötte után adjunk ahhoz egy új Web Form típusú elemet. 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. akkor új példányt kell indítanunk. Hozzunk létre az űrlapon két szövegmezőt UrlTextBox és MessageTextBox néven.IO. using System. a többi tulajdonságot változatlanul hagyja.

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

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. Értesítések megjelenítése Push Notification-ök segítségével Nézzük. Ennek hatására a frissítés gyakorlatilag azonnal megjelenik.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. az üzenet elvész. ami rögtön továbbítja azt a telefon felé. Végül térjünk vissza a webalkalmazáshoz. Mindössze azt kell közölnünk a telefonnal. a Push Notification-öknél ez nincs így – ha az alkalmazás épp nincs kitűzve. elküldjük az URL-t a szervernek. ha ékezetes betű van az üzenetben.BindToShellTile(). hogy a Push Notification-ök sajnos nem minden karaktert támogatnak. hogy míg a ShellTile API-n keresztül elvégzett változtatásokat akkor is elmentette a telefon. 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. amint az a 10-21 ábrán látható. A szerveroldalon szintén nagyon kevés változtatásra van szükségünk. Írjuk be a pushChannel. é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. 10-21 ábra: A Push Notification-nel frissített lapka Jó tudni. és kattintsunk a Lapkafrissítés küldése gombra! A webalkalmazás összeállítja az XML-t. Ennek megfelelően a kliensoldali kódban minimális változtatást kell csak végrehajtanunk. hogy ez az XML is tartalmazza a felugró értesítések valamennyi lehetséges tulajdonságát. A lapkákhoz hasonlóan itt is 267 . elküldi az MPNS-nek. sor alá a következő egyetlen sort: pushChannel.BindToShellToast(). a szerverről pedig XML formátumú kéréseket irányítunk a csatornába. ha az alkalmazás lapkája nem volt kitűzve. Szintén fontos. Hibát kaphatunk. é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. é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. és ezeket is kezelje le. hogy a létrehozott csatornán keresztül értesítések is érkezhetnek.

Lapkák és értesítések ügyeljünk.Add("X-NotificationClass". azaz „toast” típusú. akkor ehhez a ShellToastNotificationReceived eseményre kell feliratkoznunk. sendNotificationRequest. és kattintsunk az Értesítés küldése gombra! Az eredmény a 10-22 ábrához hasonlít majd.0\" encoding=\"utf-8\"?>" + "<wp:Notification xmlns:wp=\"WPNotification\">" + "<wp:Toast>" + "<wp:Text1>" + MessageTextBox. mert a 7. 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. és nem fut le a módosított kódunk. így ezúttal egy eseményre kell majd feliratkoznunk. 12 a 450 másodpercen belülit. ami lapkafrissítéshez is beregisztrálná (a BindToShellToast() hívás). string tileMessage = "<?xml version=\"1. amikor alkalmazásunk fut. A raw üzenetek csak akkor fogadhatók.Headers. Így ha most elindítjuk. Helyezzük a következő kódot mindkét pushChannel. Ezután módosítsuk a kérés HTTP fejrészét! Meg kell adnunk. é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. Távolítsuk el tehát a programot a telefonról. sendNotificationRequest. majd másoljuk át az URL-jét a webalkalmazásba. "toast").Text + "</wp:Text1>" + "<wp:Text2></wp:Text2>" + "<wp:Param>/MainPage.ErrorOccurred += kezdetű sor után: pushChannel. és 22 a 900 másodpercen belülit). akkor csak újrahasznosítja a csatornát. Erre azért van szükség.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.xaml</wp:Param>" + "</wp:Toast> " + "</wp:Notification>". A teszteléshez előbb el kell távolítani a kliens alkalmazást a telefonról.Add("X-WindowsPhone-Target". mert korábbi tesztjeink során az már megnyitotta a Push Notification csatornát.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(pushChannel_HttpNotificationReceived). hogy ez egy értesítés. Miután ezzel elkészültünk. 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).Headers.10. 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 . 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. már tesztelhetjük is az alkalmazást. "2").

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

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

aránylag rövid kiadási ciklusokkal. amely magasabb absztrakciójú megoldásokat kínál. Ez azt jelenti. mint azelőtt volt. hogy ezen a téren a Mango frissítés milyen újdonságokat hozott magával. amely a teljes platformnak csak egy darabja). és a Windows a grafikus alrendszer támogatásán kívül mást nem nyújt. Azonban a Windows Phone az ipar számára egy újonnan belépő tagot jelentett. Xbox és most már a Windows Phone is. Windows Phone – a motorháztető alatt A Windows Mobile fejlesztése során a Microsoft rendkívül sok tapasztalatot halmozott fel. ahogy azt megszoktuk. több éve kedvelt és elterjedt technológia. PC-re írt játékok esetében két elterjedt grafikai API létezik: OpenGL és DirectX (pontosabban a Direct3D. 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. Ezek után megnézzük.11. így a választás a Direct3D lehetett volna. így sokkal kényelmesebb megoldásra volt szükség. 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. ezzel elméleti és gyakorlati alapot adva azon Olvasóinknak is. Amikor a platform utódjának fejlesztésébe kezdtek. A Silverlight mint korszerű alkalmazásépítési platform jó választásnak tűnt. skálázási eltérésekre és néhány.NET fejlesztő számára sokkal kevésbé megterhelő. Miután a teljes . á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 . A választás az XNA Frameworkre esett. azonban úgy gondoltuk. Ők nagy valószínűséggel nem fognak egy komplex grafikus rendszert kitanulni.NET Framework számos okból nem vihető át egy mobil eszközre. . A fejezet első részében megismerkedünk az XNA Framework és a grafikus programozás legfőbb mozzanataival. illetve bemutatni. Az XNA a Microsoft játékfejlesztési eszközkészlete és futtatókörnyezete különböző eszközökre. í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. és mikor tudjuk kihasználni az új lehetőségeket. 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. akik eddig még soha nem találkoztak fejlesztői szempontból számítógépes játékokkal vagy grafikus programozással. mint Windows. egy olyan sokkal átgondoltabb és korszerűbb rendszert szerettek volna alkotni. könnyebben tanulható és könnyebben kezelhető. hogy a céleszközök között az alkalmazások átvihetők. Azonban hiába a gazdag médiatámogatás. Miután a Microsoft a nyílt OpenGL-t nem használja saját fejlesztéseihez. 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. Természetesen. amire egy játékprogram esetében szükség lehet (11-1. a fejlesztői modell előnyei és hátrányai jól körvonalazódtak. amely a legújabb technológiákra épít. és tartalmaz mindent. így nemcsak a tapasztalt játékfejlesztőket kellett megcélozni a technológiai támogatásokkal. pontosan mit is jelent a Silverlight és az XNA hibrid megjelenítési rendszere. hogy mindenképpen érdemes adni egy rövid ízelítőt a telefonos játékok fejlesztéséből.NET alapú programozási felülettel rendelkezik. és az arra való áttérés egy .és kezdő fejlesztőket is.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

SetSharingMode(true). és fel kell iratkoznunk az oldal LayoutUpdated eseményére is. public GamePage() { InitializeComponent(). amelynek funkcióját a későbbiekben részletesen megismerjük majd.Flick. GameTimer timer. timer = new GameTimer().UpdateInterval = TimeSpan. Texture2D background.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. SnakeBlock newBlock. mint a textúrák lekérését a tartalomkezelőtől. Szükségünk lesz egy új objektumpéldányára a kígyó osztályunknak.GraphicsDevice.FromTicks(333333).Draw += OnDraw. Ahhoz. hogy ide ne kelljen a későbbiekben visszatérnünk. elhelyeztem egy UIElementRenderer adattagot is. ami a mi esetünkben semmi mást nem jelent. akkor hívhatjuk így is) inicializálása is. } Amikor az oldalra navigálunk (először a MainPage. timer. snake = new SnakeObject( contentManager ). timer. és onnan térünk át a játékoldalra). amellyel az eleséget fogjuk elszórni a pályán.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. Random rand = new Random().Content. protected override void OnNavigatedTo(NavigationEventArgs e) { SharedGraphicsDeviceManager.Current as App). timer. kelleni fog egy háttér textúra és egy véletlen szám generátor. contentManager = (Application. a tartalomkezelő felhasználásával inicializálnunk kell a kígyó objektumpéldányunkat. akkor be kell töltenünk a tartalmakat. private private private private private private private private ContentManager contentManager. SnakeObject snake.Current. 297 . egyelőre elég. UIElementRenderer uiRenderer. amely minden egyes alkalommal le fog játszódni. ha deklaráljuk. Az osztály konstruktorában engedélyeznünk kell az érintésminták használatát. Itt történik meg az első felszedhető szegmens (ha az eleség név tetszetősebb. TouchPanel. amikor a felület frissül.xaml-lel indul az alkalmazás. SpriteBatch spriteBatch. LayoutUpdated += new EventHandler(GamePage_LayoutUpdated).EnabledGestures = GestureType.

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

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

300 . Játékok a Mango világában fejlesztésébe. Megismerkedtünk az XNA Framework alapvető használatával. É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. illetve láttuk a Mangóban újdonságként bevezetett hibrid renderelési rendszer működését és használatát is. Az utóbbira építve elkészítettük egy Snake játéknak az alapjait is. melyet az Olvasó tetszése szerint tovább bővíthet.11.

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

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

majd kikeressük a telepítendő XAP fájlt. Ehhez mindössze a Visual Studio-ban kell a kimenetet átállítani Windows Phone Emulator-ról Windows Phone Device-ra. Alkalmazások telepítése Abban az esetben. Ez mind Visual Studio-ból. hibát tudunk keresni az alkalmazásban. akkor az adott alkalmazás megjelenik a készülék vagy az emulátor alkalmazásai között. akkor ezt az Application Deployment Tool-lal tehetjük meg. ha a fejlesztői környezetből publikáljuk a készülékre az alkalmazást. és megnyomjuk a Deploy gombot (12-5 ábra). Ha minden rendben zajlott. hogy a művelet során a telefon képernyője nem lehet zárolva! 303 . akkor „Access is denied” hibát kapnánk. amelynek kezünkben van az XAP fájlja. 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 –. Abban az esetben. 12-4 ábra: Készülékre történő publikáció Figyelnünk kell arra is. mind Expression Blendből egyszerűen megoldható. Ezt követően az F5-öt megnyomása után már a készülékre kerül fel az alkalmazás. 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.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. Az alkalmazás felépítése nagyon egyszerű: először megmondjuk. Itt is fontos megjegyezni. és ott tudunk hibát keresni (12-4 ábra). a debugger rögtön elindul és ugyanúgy. ahogy az emulátornál. 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.

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

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

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

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

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

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

A neten persze találhatunk erre is jó néhány eszközt. OneNote. majd a nagyítási beállításokat (nagyító ikon) állítsuk 100%-ra. é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. 12-13 ábra: Screnshot készítése Nézzük meg használat közben! Indítsuk el az alkalmazást. hogy legalább egy 480x800-as képernyőkép legyen az alkalmazásunkról mellékelve.1 SDK-ja óta ez a funkció már az emulátor mellett is megtalálható (12-13 ábra). 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. és kapcsoljuk ki a Frame rate számlálókat is! Ha ez megtörtént. akkor indítsuk el az 310 .12. de a legtöbbjük használata legtöbbször kényelmetlen. A méretnek pontosnak kell lennie. de a Windows Phone 7.

Ha nem adjuk meg ezeket a képeket.Publikálás alkalmazást. ikonokat és képernyőképeket. akkor a tesztünk sikertelen lesz. hogy az alkalmazásunk megfelel-e a Marketplace követelményeinek. ahol különböző teszteket futtathatunk le: Nézzük meg. az alkalmazásunkhoz tartozó képeket. Az Applicaton package mezőbe az XAP fájl útvonala található. 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. 311 . az alapbeállítás szerint a Bin\Release mappában található XAP-ra mutat. amivel megvizsgálhatjuk. é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. 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. 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. Application Details Automated Tests Monitored Tests Manual Test A Test Kit felhasználói felületén négy fül található. Ezenkívül ezen a fülön adhatjuk meg az alkalmazások piactérre feltöltendő képeit és képernyőképeit. ami nem engedélyezett a számunkra? Használ-e olyan API-t.1 SDK –val érkezett egy hasznos eszköz (Marketplace Test Kit) is. A tesztek lefuttatásához egy Release konfigurációval történő fordításra is szükségünk van. ha bezárjuk az alkalmazást? Stb. amiről a screenshotokat szeretnénk elkészíteni. ami nem engedélyezett egy Backround Agenttel? Nincs-e váratlan hiba.

akkor a teszt megmondja.12. Az Application Details alatt megadott képeket is itt teszteljük. például az alkalmazás méretét és képeit. hogy az alkalmazásunk számára milyen Capability beállításokat (képességeket) kell meghatároznunk a WPAppManifest. A teszt közben a program által felkínált lehető legtöbb felhasználói esetet hajtsuk végre az alkalmazáson! 312 . 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. tehát csak a fejlesztői zárolás feloldásával ellátott készüléken tudjuk ezt megtenni. A teszt során az alkalmazást egy fizikai készüléken kell kipróbálnunk. 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. Ha lefuttatjuk a tesztet.

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

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

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

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

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

.

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

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

A program működése igen egyszerű. // Constructor public MainPage() { stopwatch = new Stopwatch(). Ha elindítjuk a programot az emulátorban. ellipse. } private void OnLoaded(object sender.ElapsedMilliseconds + " ms"). RoutedEventArgs routedEventArgs) { MessageBox.Top.Margin = new Thickness(x. ellipse.Shapes.Width = size.Left. 0). ellipse. a 13-1 ábrán látható eredményt kapjuk. ami az indulás óta eltelt ezredmásodperceket méri.Windows.HorizontalAlignment = HorizontalAlignment.Phone. ellipse. ellipse. ContentPanel. i++) { Ellipse ellipse = new Ellipse().Height = ellipse. namespace CpuAndGpu { public partial class MainPage : PhoneApplicationPage { private Stopwatch stopwatch.Media. 321 .Next(456). Microsoft.Fill = new SolidColorBrush(Colors. } } } } A Solution Explorer-ben töröljük ki a SplashScreen. for (int i = 0.jpg fájlt.Diagnostics. } public void CreateStarField(int numOfStars) { Random x = new Random(). x.Csillagok. InitializeComponent().NextDouble()*3.White). i < numOfStars.Windows. csillagok… using using using using using using System. A MainPage osztály létrehozása után elindítunk egy stoppert.VerticalAlignment = VerticalAlignment.Children. CreateStarField(100).Start(). double size = x. System. stopwatch. Loaded += OnLoaded.Width. System. 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. 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.Windows. ellipse.Add(ellipse). System.Next(607). System.Show("Startup time: " + stopwatch. 0.Controls. A stopper elindítása után az InitializeComponent függvény a XAML-ben leírtakat értelmezi.

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

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

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

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

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

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

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

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

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

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

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

hogy az alkalmazás sokat gyorsult. 338 . 13-14 ábra: a SurfCube visszafordul az első oldalra a könyvjelző kiválasztása után. é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.NET-ben megszokott optimalizáló fogások Windows Phone-on is működnek. nagyobb memóriával rendelkező készülékeken ennél többet is. é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 256 Mbyte-os telefonon max. de az azonnali reakció miatt a felhasználók egyértelműen (de tévesen) úgy érezték. A szabály az. Természetesen a Silverlight-ban és a . Í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. Ezért változtattunk a működésen. mert a Marketplace az alkalmazás befogadásakor igen szigorúan ellenőrzi a memória használatát. 90 Mbyte-ot használhat a program. Teljesítmény értesül a felhasználó.13. Érdemes azonban áttekinteni néhány platform-specifikus területet.

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

Jellemzően 30 és 60 közötti értékeket szeretünk itt látni. amíg megjelennek a csillagok. ezért nincs itt sok értékelhető adat.13. Alatta a Frame Rate azt mutatja. A CPU-használatot mutató grafikonon a fehér szín azt jelzi. Várjuk meg. 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. Mivel a csillagok kirajzolása után az alkalmazás nem csinál semmit. 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). 340 . Mit jelent mindez? 13-16 ábra: Az analízis eredménye A felső skála a másodpercekben mért időt mutatja. majd a Select All-t a grafikonon). a szürke a rendszer-szálat jelenti. amikor a CPU nem csinál semmit. hogy egy másodperc alatt a képernyő hányszor került újrarajzolásra. A zöld szín az UI szálat. Teljesítmény elindul az alkalmazás a telefonon.

Windows Phone Performance Analysis A memória-használat grafikonja egyértelmű. Ezt az időt rövidíthettük le. képkocka megrajzolásához milyen függvényhívásokat hajtott végre a rendszer. Ha a Performance Warnings melletti kis nyilacskára kattintunk. é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. Az Inclusive samples-re kétszer kattintva. ami nem feltétlenül a rajzolással van összefüggésben. Ebből az ötödik (utolsó) kocka az. hogy magas CPU használatot mért az UI szálon – olyan CPU használatot. é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. 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ó. Legvégül pedig a Garbage Collector eseményei. 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. csökkenő sorrendbe rendezhetjük a hívásokat. Láthatjuk. Ha fent kijelölünk egy legalább fél másodperces időtávot. Látható még az adott frame Fill Rate-je és a textúrák száma is. Ezt több mint 1 másodpercig rajzolta a telefon (Duration és CPU time). 13-18 ábra: A 4. ha a Visual Tree for Frame 4 opciót választjuk (13-19 ábra). 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. amikor az ellipsziseket kirajzoltuk. hogy csak a függvény saját idejét számítjuk. hogy az alkalmazás a futása során 5 képkockát készített (0-tól számozva). Az Inclusive azt jelenti. 341 . megtekinthetjük a frame-eket. 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. Nézzük meg. Alatta a program által indított StoryBoard-ok (piros – CPU. Még látványosabb. Először válasszuk ki a Frames-t. az exclusive pedig. Például az első sorban azt jelzi. lila – nem CPU) és képbetöltések találhatók – ezek ebben az alkalmazásban nem fordulnak elő. illetve a CPU-használatot. hogy a 4. hogy az adott függvényből hívott további függvények is beleszámítanak.

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

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

Sign up to vote on this title
UsefulNot useful