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

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

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3-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 . 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. illetve az „X” gombbal törölhetünk egy elemet (3-39 ábra).3. Az egyes elemek sorrendjét az ablak alján lévő nyilakkal változtathatjuk meg. amit átírhatunk. melyben szerkeszthetjük a ListBox tartalmát. Az „Add another item” gombra kattintva kiválaszthatjuk a ListBoxhoz hozzáadni kívánt elem típusát. az Object Collection Editor ablak jelenik meg. Egy stringet hozzáadva (az mscorlib|Systemben találjuk) a szerkesztőablak jobb oldalán megjelenik a karakterlánc.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Row="1" Margin="12.0.ContextMenu> <toolkit:ContextMenu> <toolkit:MenuItem Header="Menü 1" Click="MenuItem_Click" /> </toolkit:ContextMenu> </toolkit:ContextMenuService.12. Haladó alkalmazásfejlesztés Windows Phone-on </StackPanel> <!--ContentPanel .png" Margin="6" Background="#FF008000" GroupTag="TileGroup" Notification="Noti" Message="Microsoft Minősített Szerviz Partner project"> <toolkit:ContextMenuService.4.png" Background="#297FD5" Margin="6" GroupTag="TileGroup" Notification="2 új hír" DisplayNotification="True" Message="Microsoft Minősített Szerviz Partner project"> </toolkit:HubTile> <toolkit:HubTile Tap="hirekTile_Tap" Title="Esemény" Source="Images/calendar.png" 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="#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.ContextMenu> </toolkit:HubTile> <toolkit:HubTile Name="hirekTile" Tap="hirekTile_Tap" Title="Hírek" Source="Images/news.place additional content here--> <toolkit:WrapPanel x:Name="ContentPanel" Grid.0"> <toolkit:HubTile Tap="hirekTile_Tap" Title="Minden" Source="Images/all.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.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.

ezek között a kiemelt pozíciók jelölésével.Összefoglalás 4-27 ábra: HubTile-ok WrapPanelbe csomagolva Összefoglalás A fejezet elején részletesen megismerkedhettünk a Bing Maps szolgáltatás felhasználási lehetőségeivel. Végül a Silverlight Toolkit előnyeit ismerhettük meg. 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. 111 . 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. azokon belül pedig a Panorama és Pivot vezérlőket. az egyszerű címkereséssel és az útvonaltervezéssel.

.

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

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

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

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

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

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

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

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

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

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

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

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

minden feladatnak speciálisan a hozzá illeszkedő feladat kategóriába kell kerülnie. 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. hogy semmilyen esetben se veszhessenek el a felhasználó munkafolyamataihoz tartozó adatok. 135 . 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. hogy nem végezhetünk akármit szabadon a háttérben. amelyre eddig csak nagyon nehézkesen vagy esetleg egyáltalán nem találhattunk megoldást. ahol a megfelelő objektumok végrehajtják az általunk megvalósított feladatok logikáját. Az elméleti bevezetést követően gyakorlatban is láthattuk azokat a lépéseket. és arról gondoskodnak.Összefoglalás Összefoglalás A fejezetben láthattuk. Láthattuk.

.

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

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

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 .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. amelyek az egyes oldalak. hogyan tudjuk az MVVM modellnek megfelelően szervezni kódunkat. és kihasználja a Silverlight által biztosított adatkötési mechanizmust. hogy ezt a forrást a tervező eszközök meg is jelenítsék. megjelenítés). Ilyen adatforrás például a SampleData MainViewModelSampleData.1-es verziót.xaml állománya. 6-3 ábra: A sablon által generált projekt Ez a megközelítés a lehető legjobban elválasztja a különböző felelősségeket (adatszolgáltatás. 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. 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). A ViewModels mappa fogja össze azokat az osztályokat. logika. Ahhoz. mivel példát mutat arra. megjelenítési felületek által elvárt formában tárolják az egyéb adatforrásból származó információt.

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

0" Style="{StaticResource PhoneTextSubtleStyle}"/> </StackPanel> </DataTemplate> </ListBox.0" Style="{StaticResource PhoneTextExtraLargeStyle}"/> <TextBlock Text="{Binding LineThree}" TextWrapping="NoWrap" Margin="12.0. private void MainPage_Loaded(object sender. egyet a launcherek és egyet a chooserek számára.A példaalkalmazás létrehozása <TextBlock Text="{Binding LineOne}" TextWrapping="NoWrap" Margin="12. fejezete tökéletes kiindulópontot jelent a tanuláshoz. Alakítsuk át a projektet a taszkok teszteléséhez szükséges formába! A Pivot két lapot tartalmazzon.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. } // Adatok betöltése.0. this.IsDataLoaded) { App. Az oldal kontextusát a MainPage konstruktora állítja a megfelelő ViewModelre: // Constructor public MainPage() { InitializeComponent(). Minden taszk indítására vegyünk fel külön gombot. amint elkészült az oldal. 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 .-6. hiszen ezzel biztosítható az. hogy a panel görgethetővé válik.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.ViewModel. RoutedEventArgs e) { if (!App.ViewModel.0.ViewModel. akkor a Silverlight 4: A technológia.LoadData(). } } A generált projekt megvizsgálásával egy kis betekintést nyerhettünk az MVVM architekturális minta használatába. // Adatkötés DataContext = App. viszont ha komolyan érdeklődünk a téma iránt. és ami mögötte van című könyv 10.

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

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

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

akkor meg kell adnunk. mpl. ami teljes testreszabhatóságot biztosít számunkra. Jó példa erre az Orchard keretrendszerben elkészített HTML 5-öt használó https://devportal.vo. A példában egy internetes videót választottam.Uri = new Uri("http://www.msecnd. ezt pedig a MediaPlayerLauncher Location tulajdonságán keresztül tehetjük meg. } 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.Launcherek webBrowserTask. //mpl. webBrowserTask. UriKind. mpl.Absolute).Data. Az egyik a Toolboxban megtalálható MediaElement vezérlő. ami lehet lokális vagy távoli. Ha a telefonon található tartalmat szeretnénk lejátszani.Location = MediaLocationType. így most abszolút címzést alkalmazunk.Show().devportal. 6-7 ábra: A https://devportal.wmv".Show(). internetről származó is. hogy az alkalmazással telepített vagy az Isolated Storage-be mentett médiát címzünk meg. a másik pedig a pár kódsorral paraméterezhető MediaPlayerLauncher taszk (6-8 ábra).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.Controls = MediaPlaybackControls. Ennek megfelelően ki kell választanunk.Media = new Uri(@"http://mschannel9.hu/wp7 oldal. private void btnMediaLauncher_Click(object sender. UriKind.net/o9/mix/09/wmv/key01. így a generált oldal teljesen megegyezik a számítógépeken megszokottal. mpl. Választásunkat követően az oldal betöltődik az Internet Explorer 9 mobilos változatába.Absolute).hu/wp7". hogy relatív vagy abszolút címzésről van szó. } 145 . A böngésző a Mango frissítésnek hála teljes HTML 5 támogatással rendelkezik. RoutedEventArgs e) { MediaPlayerLauncher mpl = new MediaPlayerLauncher().All. ami a 6-7 ábrán látható. 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 beviteli mező jobb szélén található mikrofon gombra kattintva akár diktálva is. A keresőszót a taszkon belül módosíthatjuk. FastForward.SearchQuery = "pizza". és a többi találat előtt ajánlja az illeszkedő alkalmazásokat. Ez a mező a MediaPlaybackControl enumeráció (All. aminek hála a keresés a Marketplace alkalmazásait is megvizsgálja. Skip. A Mango újdonsága az ún.6. Rewind. 6-8 ábra: MediaPlayerLauncher taszk egy videó lejátszása közben. minden beépített vezérlővel SearchTask Kereső funkciót megvalósító taszk. RoutedEventArgs e) { SearchTask searchTask = new SearchTask(). Pause. A találatok egy Pivot vezérlőn jelennek meg. de ha engedélyeztük a Location Servicest. App Connect. aminek lapjait a 6-9 ábra mutatja. hogy milyen előre definiált vezérlők jelenjenek meg a médialejátszóban. akár képek között. searchTask. None. akkor a pozíciónk körüli kiemelt helyek között is.Show(). Alapvető telefonos funkciók használata A Controls tulajdonságon keresztül kiválaszthatjuk. A 6-8 ábrán az összes elem együttes használata látható. } 6-9 ábra: A SearchTask találatainak listája 146 . Stop) egy értékét veheti fel. private void btnSearchTask_Click(object sender. Segítségével a megadott kulcsszó alapján kereshetünk a weben. searchTask.

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

é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. Kattintsunk a Password elemre. 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.9.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Windows Phone Marketplace Test Kit A Windows Phone 7. amivel megvizsgálhatjuk. ahol különböző teszteket futtathatunk le: Nézzük meg. 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. 311 . akkor a tesztünk sikertelen lesz. ha bezárjuk az alkalmazást? Stb. A tesztek lefuttatásához egy Release konfigurációval történő fordításra is szükségünk van. Mit is árul el ez az eszköz alkalmazásunkról?              Megfelelőek-e a képek és a képernyőképek a követelményeknek? Megfelelő-e az XAP fájl mérte (maximum: 225 MB)? Elég gyorsan indul-e az alkalmazásunk? Nem használ-e túl sok memóriát? Rendeltetésszerűen működik-e a Back gomb? Nem használ-e olyan API-t. ikonokat és képernyőképeket. é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. 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 egy Backround Agenttel? Nincs-e váratlan hiba.Publikálás alkalmazást. ami nem engedélyezett a számunkra? Használ-e olyan API-t. Az Applicaton package mezőbe az XAP fájl útvonala található. hogy az alkalmazásunk megfelel-e a Marketplace követelményeinek. 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. amiről a screenshotokat szeretnénk elkészíteni. és navigáljunk arra az oldalra. Application Details Automated Tests Monitored Tests Manual Test A Test Kit felhasználói felületén négy fül található. az alkalmazásunkhoz tartozó képeket.1 SDK –val érkezett egy hasznos eszköz (Marketplace Test Kit) is. az alapbeállítás szerint a Bin\Release mappában található XAP-ra mutat. Ha nem adjuk meg ezeket a képeket.

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Alatta a Frame Rate azt mutatja. 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. Mit jelent mindez? 13-16 ábra: Az analízis eredménye A felső skála a másodpercekben mért időt mutatja. a szürke a rendszer-szálat jelenti. Várjuk meg. A CPU-használatot mutató grafikonon a fehér szín azt jelzi. 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).13. 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. amíg megjelennek a csillagok. 340 . Jellemzően 30 és 60 közötti értékeket szeretünk itt látni. ezért nincs itt sok értékelhető adat. amikor a CPU nem csinál semmit. majd a Select All-t a grafikonon).

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

CPU Usage . Talán meglepő lehet.Functions nézethez navigálunk (13-20 ábra). Ennyire lassan rajzolna szöveget a futtatókörnyezet? A PageTitle viszont csak 5 ms. 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. csak magára az elrendezésre és a rajzolásra. é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). 342 . ha a diagramon kijelöljük a 3-as és 4-es képkocka közötti területet. Mi történt vajon a 3-as kocka vége és a 4-es eleje között. Teljesítmény 13-19 ábra: A 4. hogy a 4-es kockát a program indítása után 6. hogy melyik elemmel mennyit foglalkozott a telefon. míg a második TextBox-nál már erre nem volt szükség. 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ó.13. majd a Performance Warnings . A jelenség oka.767 másodperccel kezdte csak el a telefon számolni.

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

Sign up to vote on this title
UsefulNot useful