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

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

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

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

a betűk méretét. a Windows Phone Application sablon rögtön két TextBlockot is beépít alkalmazásunk felületébe.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. 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). Egyszerű szövegmegjelenítés a TextBlockkal Ahogy korábban láttuk. amelynek nem kell szöveget megjelenítenie. 3-20 ábra: A TextBlock szövegének beállítása A Text csoportban található tulajdonságok segítségével szabhatjuk testre a szöveg kinézetét. 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. aláhúzott) betűformázási lehetőségeket is megkapjuk (3-21 ábra). dőlt. 55 . Egyebek között átállíthatjuk a betűtípust.

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

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

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

a Toolboxon Nem meglepő módon a TextBox vezérlő Text tulajdonságán keresztül érhetjük el. Programozottan ennél többet is meg lehet adni. Az IsReadOnly tulajdonságával tehetjük csak olvashatóvá a szövegdobozt – ilyenkor a felhasználó nem állíthatja át a beleírt szöveget. ahogy a két előző vezérlőnket is a szövegvezérlők csoportjában találjuk a Toolboxon (3-30 ábra). A TextBoxot. a MaxLength csak a felhasználói adatbevitelt szabályozza. 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.Alapvető WP7 vezérlők Szövegbevitel a TextBoxszal A TextBox. 3-31 ábra A TextBox tulajdonságainak beállítása a Properties panelen 59 . A MaxLength tulajdonsággal megszabhatjuk. hogy legfeljebb hány karaktert írhasson be a felhasználó a szövegdobozba. 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.

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

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

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

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

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

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

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). XAML-ben is megadhatjuk őket. hogy hol kerüljön definiálásra az erőforrás: az oldalon vagy az alkalmazás szintjén. Így még jobban elválasztható a felület leírása a kódban megírt logikától. Alkalmazásfejlesztés Windows Phone-on megtartani a program konzisztenciáját. hogy egy erőforráskönyvtárban (resource dictionary) hozzuk létre. melyeket csak erőforrások tárolására szokás létrehozni. 3-42 ábra: Az erőforrás nevének és tárolási helyének beállítása 66 . melynek egyik eleme a „Convert to New Resource…” névre hallgat (3-41 ábra). Ezeket a közös használatú objektumokat definiálhatjuk kódban. Ez meghatározza azt is. ha a változtatás igénye esetén csak egy helyen kell frissíteni egy adott objektumot. de tekintve. Az ApplicationTitle TextBlockot a Properties panelen kiválasztva a Text tulajdonság mellett található Advanced options gombra kattintva megjelenik a menü. valószínűleg mindegyik ablakban szeretnénk majd felhasználni azt. azokban is elérhető lesz. Alkalmazásaink címe például nem változik. és ha több ablakból áll egy alkalmazás.3. A megjelenő párbeszédablakban beállíthatjuk az erőforrás nevét (Name). A harmadik lehetőség. utóbbinál viszont ha vannak más oldalaink. illetve meghatározhatjuk. amit éppen a Text tulajdonság tartalmaz. hogy hol lesz látható: előbbi esetben csak az aktuális oldalon belül. Az erőforráskönyvtárak különálló XAML-fájlok. 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 a Blend nagyon szépen jelzi. 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. hogy egy tulajdonság nem lokálisan kap értéket. A kész erőforrás innen azonnal. hanem egy erőforráshoz kötöttük hozzá (3-43 ábra). ott is megtalálható az erőforrások között az újonnan létrehozott string. 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. például egy CLR-objektumhoz. illetve a Silverlightban.Adatkötés Az is észrevehető. 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). drag-and-drop módszerrel áthúzható egy felületi elemre. Mi a helyzet akkor. 67 . 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. 3-43 ábra: A zöld keret és pötty jelzi. létrehozva ezzel az erőforráshoz kötést (3-44 ábra). 3-44 ábra: Az adatforrások a Resources panelon Ugyanezt elérhetjük. ha átváltunk a Resources panelra. hanem valami máshoz.

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

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

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

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

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

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

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

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

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

77 .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. hogy a sablon már a gombtól veszi a feliratát (3-67). 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. csupán a képeik térnek el. és az Image vezérlő forrását erre kötjük rá a TemplateBindinggal. Érdemes a képeket Visual Studióban hozzáadni a projekthez. a képet természetesen egy másikra állítva a Hozzáadás gomb is megszépíthető (3-68 ábra). mert a Blendben sajnos nem tudjuk Build Action tulajdonságukat átállítani. érdemes saját vezérlőt készíteni. amelynek egy plusz ImageSource tulajdonságot adunk. 3-67 ábra: A vezérlősablon átveszi a vezérlőtől az értéket Ugyanezeket a lépéseket eljátszva. ez pedig elengedhetetlen.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

115

5. Az alkalmazás életciklusa

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

116

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

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

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

117

5. Az alkalmazás életciklusa

Esemény Launching Activated Deactivated Closing OnNavigatedFrom OnNavigatedTo

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

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

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

118

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

  

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

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

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

119

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

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

120

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

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

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

121

5. Az alkalmazás életciklusa

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

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

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

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

122

Állapotok kezelése

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

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

123

5. Az alkalmazás életciklusa

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

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

124

Folyamatok a háttérben

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

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

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

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

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

125

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

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

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

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

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

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

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

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

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

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

.

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

Amennyiben viszont nincsenek egyedi igényeink a funkcióval kapcsolatban. A példaalkalmazás létrehozása A fejezet első részében a felsorolt taszkokkal fogunk részletesen megismerkedni. érdemes ezek mentén külön lapokra bontani a megjelenítési felületet is. amely feladatát egy-egy beépített vezérlő is képes ellátni.6. fejezetben bemutatott Pivot vezérlő. 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. de a platform többi részével konzisztens megoldást is biztosít. amit legegyszerűbben a Windows Phone Pivot Application projektsablon kiválasztásával (6-2 ábra) helyezhetünk el alkalmazásunkban. akkor nemcsak egyszerűbb a taszk használata. 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. Erre elegáns módszer a 4.

hogyan tudjuk az MVVM modellnek megfelelően szervezni kódunkat. megjelenítés). mivel példát mutat arra.1-es verziót. 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. 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 . megjelenítési felületek által elvárt formában tárolják az egyéb adatforrásból származó információt. logika.xaml állománya. 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). 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. A ViewModels mappa fogja össze azokat az osztályokat. Ilyen adatforrás például a SampleData MainViewModelSampleData. Ahhoz. hogy ezt a forrást a tervező eszközök meg is jelenítsék.A példaalkalmazás létrehozása 6-2 ábra: Windows Phone Pivot Application sablon kiválasztása a projekt létrehozásakor A következő dialógusban mindenképpen válasszuk a Windows Phone OS 7. és kihasználja a Silverlight által biztosított adatkötési mechanizmust. amelyek az egyes oldalak.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

13. 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. Teljesítmény 13-1 ábra: 100 csillag. 388 ms A programnak azonban a telefonon kell futnia. ábra grafikonján: 13-2 ábra: csillagok kirajzolási ideje emulátoron és telefonon 322 . hanem akár több ezer csillagot szeretnénk megjeleníteni? A mérések eredménye jól látszik a 13-2. ha nem csak 100.

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

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

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

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

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

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

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

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

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

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

A szabály az. nagyobb memóriával rendelkező készülékeken ennél többet is. és a böngészőt most már csak a forgatás animáció befejeztével irányítjuk át az új címre. Ezért változtattunk a működésen. Í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.NET-ben megszokott optimalizáló fogások Windows Phone-on is működnek. É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. mert a Marketplace az alkalmazás befogadásakor igen szigorúan ellenőrzi a memória használatát. Teljesítmény értesül a felhasználó. 338 . Természetesen a Silverlight-ban és a . hogy 256 Mbyte-os telefonon max. 13-14 ábra: a SurfCube visszafordul az első oldalra a könyvjelző kiválasztása után.13. é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. hogy az alkalmazás sokat gyorsult. 90 Mbyte-ot használhat a program.

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful