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

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

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

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

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

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

.

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

.

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

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

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

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. Cserébe a publikációs lehetőségen túl számos szolgáltatást kapunk a portálon. ingyenes Visual Studio 2010 változat. Az induláshoz csupán a Windows Phone SDK 7. a http://create. nem szolgál rossz célt. Bevezetés a „Windows Phone” platform-ba  Közösségi hálózatok: A Windows Phone nagyon fontos részét jelentik a közösségi hálózatok és az integrált élmény biztosítása az ún. ennek segítségével feltölthetjük a Windows Phone alkalmazás boltba. Alkalmazások közzététele Az alkalmazások. Szerencsére elmondhatjuk. Az éves fejlesztői díj 99 dollár.92). amellyel üzleti célra is fejleszthetünk alkalmazásokat.aspx. ahol a fejlesztői vezérlőpulton értékes információkhoz. és amelyen keresztül értékesíthetik azokat. az alábbi címről: http://www. A Microsoft Expression Blend 4. ahova a fejlesztők elkészült alkalmazásaikat tölthetik fel. hubokon keresztül.0 termék kizárólag Windows Phone projektek kezelésére alkalmas.msnd. amely egy Live ID segítségével az ún. hogy az alkalmazásunk stabil. hogy a fejlesztési infrastruktúra költsége gyakorlatilag nulla. egy tanúsítványt kap. A fejlesztőeszközök is erről a portálról tölthetők le közvetlenül.com/download/en/details. feltöltésüket követően. egy hitelesítési folyamaton mennek keresztül.1-es változatot kell letölteni. Soha ne felejtsük el. vagy akár otthoni Xboxunkat is vezérelhetjük telefonunkról. amely során a Microsoft egy szigorú tesztsorozat futtatásának segítségével meggyőződik arról.com címen található portálon végezhető el. A felhasználók számára ez hatalmas piactér. 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. de teljes értékű változata. üzeneteket küldhetünk nekik. továbbá egy Windows Phone készülék sem árt. A Marketplace-en keresztül történik a számlázás és a frissítések kezelése is. A dokumentum a következő címen érhető el: http://msdn. így nyomon követhetjük barátainkat.  A Marketplace portálszolgáltatásai A Windows Phone Marketplace egy központi portál. 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. hogy a telefon egy kliens. Miután az alkamazásunk sikeresen átment a teszteken. továbbá kielégíti az alkalmazások által követendő szabályokat. bár ez utóbbi nem kötelező.1.com/enus/library/hh184843(v=VS. ahol a különböző tartalmak és alkalmazások közül válogathatnak. Ezek a szabályok az Application Certification Requirements for Windows Phone című dokumentumban kerültek rögzítésre. App Hub-on. és ennek eredményeképpen saját alkalmazásokat tudunk rá telepíteni a Visual Studio 2010 segítségével.microsoft. ahol az ár és a régiók kiválasztása után az alkalmazás széles közönség számára válik elérhetővé. csupán erősen ajánlott. statisztikákhoz juthatunk alkalmazásainkat illetően. és segítségükkel rendkívül gazdag és értékes információhalmazt biztosítani. 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. amely a telefon legtöbb képességét képes emulálni. amely szolgáltatások ezreihez képes csatlakozni. A fejlesztőeszközök a Windows Phone fejlesztők számára ingyenesen elérhetők.   18 . Xbox Live szolgáltatások: A Windows Phone képes a felhőben futó Xbox Live szolgáltatásokhoz is kapcsolódni.microsoft. Windows Phone Emulator: Fejlesztési időben használható Windows-on futó emulátor. összehasonlíthatjuk elért eredményeiket a miénkkel. Természetesen egy Windowst futtató PC-re szükség lesz. 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 Windows Phone fő alkalmazásfejlesztési platformja a 7. Ennek következtében nem tudott megfelelni az új igényeknek. A megvalósítás során hamar belefutunk abba a rendkívül kellemetlen ténybe. a webes és intranetes környezetekben is komoly szerepet kaptak. attribútum. A sors különleges fintora. így nem felhasználói felület specifikus. A XAML (eXtensible Application Markup Language) egy kiterjeszthető alkalmazásleíró nyelv. hogy a Windows Forms ListView vezérlője nem támogatja a ProgressBart. majd abba egy DataGridet helyezhetünk el. 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. kiforrott és rendkívül produktív volt. 19 . A WPF megjelenését követően a Microsoft hamarosan úgy ítélte.NET keretrendszer egyik kulcstechnológiájának. ahol különböző folyamatokat és annak státuszait kell megjeleníteni. Ezt a technológiát később Silverlightként ismerte meg a világ. mint alkalmazás leíró nyelv. Gondoljunk csak a HTML-re. és a webre is célszerű lenne elkészíteni egy WPF-hez hasonló technológiát. mint például a szélességét vagy magasságát.és a vezérlőmodell. Legújabban pedig különböző mobil. melyet nem sokkal később Windows Presentation Foundation (WPF) néven ismert meg a világ a . mint egy cella lehetséges elemét. A WPF számos új koncepció mellett egy nagyon fontos újdonságot hordozott magában − az új vezérlőmodellt. XAML szintaktika – értékadás A XAML alapvetően az XML szintaktikai előírásait követi. de nagyon jól példázza a modell rugalmasságát. esetleg a tartalmát. illetve terjeszti ki. játékterét. melyet reprezenáljunk egy ProgressBarral. 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. A XAML alapú rendszerek komoly sikertörténetet tudnak magukénak. 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.NET 3. ez pedig a felhasználói felület deklaratív leírása. illetve hordozható eszközökön fejleszthetünk alkalmazásokat XAML alapokon. Annak érdekében. 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.0 keretrendszer megjelenésekor. Premium. A Windows Forms maradiságának okán a technológia leváltására a Microsoft elindította az Avalon projektet. A gondolat nagyon egyszerű volt. Ismerkedés a XAML-lel Az új modell mellé egy másik fontos koncepció is párosult. 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. képzeljük el. A technológia hatékony.0 változatban és a 7. a státuszt pedig minden sorban jelölje egy százalékos érték. aminek természetesen túl sok értelme ugyan nincs. XAML nyelvet választotta. Meghódították az asztali PC-k világát. 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 . Ultimate) a fejlesztőeszközök beépülnek a telepített változatba. Az XML egyfajta kiterjesztése egy különleges XAML Parser-rel. izgalmas és jól használható felhasználói felületek helyezkedtek el. melynek feladata a XAML értelmezése és a leírt objektumgráf felépítése. Ha XAML-ben leírunk egy elemet (pl <Button/>). komplexebb értékadásoknál az utóbbi mechanizmust alkalmazzuk. Az alkalmazás. a Windows Forms-nak a segítségével fejlesztették ki. A folyamatokat egy táblázat sorai reprezentálják. a vezérlők alapvetően tartalom jellegű vezérlők (ContentControl) és bármit tartalmazhatnak. Ez lett a WPF legjelentősebb újdonsága. hogy érezzük ezt a kötöttséget. A Button egyéb tulajdonságait. akkor abból futásidőben egy Button példány fog elkészülni. hogy a XAML alapú felületek jelentik a jövőt. 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. amelyeknek középpontjában a modern. Míg az előbbi egyszerű értékek beállítása esetén elegendőnek bizonyulhat. hogy olyan alkalmazást fejlesztünk.1-ben is a Silverlight. Sajánlatos módon további sorsát megpecsételte saját képességeinek erős korlátozottsága. Ennek köszönhetően egy Button vezérlőbe egy másik Buttont. illetve tulajdonság szintaxissal lehet meghatározni.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

illetve 1024x800-as felbontásban. a görgetés során pedig egészen egyedi animációval és tulajdonságokkal rendelkezik. illetve horizontális mozgatással lehetséges. és biztosítja a navigációt közöttük. Háttérképként jellemzően JPEG ajánlott 480x800-as. 40 . A navigáció a menüelemek fejlécét érintve. valamint az átméretezés elkerülését. Felhasználói élmény tervezése Windows Phone-on 2-18 ábra: A Panorama vezérlő A Panorama vezérlő messze túlnyúlik a látható területen. A vezérlő önálló. amelyek magukban is görgethetők horizontális irányban! Teljesítmény megfontolások miatt szorítkozzunk maximum négy különböző nézetre egyetlen Panorama vezérlőben! A Panorama címe célszerűen sima szöveg legyen! A Pivot vezérlő A Pivot vezérlő a Windows Phone saját Tab vezérlője. A Panorama vezérlővel ellentétben nem egyetlen nagy téren helyezkednek el az egyes szekciók. dinamikus parallaxszerű effektust eredményezve. Az animáció során a tartalom és a feliratok különböző sebességgel. Map vezérlők). ezáltal rendkívül látványos. 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.2. időben eltolódva hajtódnak végre. Toggle. elkülönített nézeteket helyez el egymás mellett. Ez biztosítja a jó teljesítményt és a gyors betöltést. A vezérlő használatakor néhány dolgot célszerű szem előtt tartani:       A hátteret célszerű egyetlen színnel vagy egy óvatosan választott háttérképpel kitölteni. A 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. 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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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. 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. 3-31 ábra A TextBox tulajdonságainak beállítása a Properties panelen 59 . a MaxLength csak a felhasználói adatbevitelt szabályozza. hogy legfeljebb hány karaktert írhasson be a felhasználó a szövegdobozba. A MaxLength tulajdonsággal megszabhatjuk.Alapvető WP7 vezérlők Szövegbevitel a TextBoxszal A TextBox. 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 Toolboxon Nem meglepő módon a TextBox vezérlő Text tulajdonságán keresztül érhetjük el. avagy szövegdoboz segítségével a felhasználó a telefon virtuális vagy fizikai billentyűzete segítségével adatokat vihet be az alkalmazásba. Programozottan ennél többet is meg lehet adni.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

és az Image vezérlő forrását erre kötjük rá a TemplateBindinggal. amelynek egy plusz ImageSource tulajdonságot adunk.A vezérlők kinézetének testreszabása vezérlősablonokkal 3-66 ábra: Vezérlősablon tulajdonságának a vezérlőhöz kötése a TemplateBinding segítségével A Content tulajdonság kiválasztása után meg is jelenik az adatkötést jelző sárga keret. érdemes saját vezérlőt készíteni. hogy a sablon már a gombtól veszi a feliratát (3-67). É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). csupán a képeik térnek el. ez pedig elengedhetetlen. mert a Blendben sajnos nem tudjuk Build Action tulajdonságukat átállítani. 77 . 3-67 ábra: A vezérlősablon átveszi a vezérlőtől az értéket Ugyanezeket a lépéseket eljátszva. 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. illetve a tervezőfelületen látszik.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

115

5. Az alkalmazás életciklusa

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

116

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

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

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

117

5. Az alkalmazás életciklusa

Esemény Launching Activated Deactivated Closing OnNavigatedFrom OnNavigatedTo

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

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

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

118

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

  

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

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

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

119

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

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

120

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

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

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

121

5. Az alkalmazás életciklusa

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

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

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

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

122

Állapotok kezelése

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

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

123

5. Az alkalmazás életciklusa

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

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

124

Folyamatok a háttérben

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

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

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

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

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

125

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

ábra: A projekt struktúrája Következő tennivalónk a zenefájlok átmásolása az Isolated Storage-ba. 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. 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. hogy az AudioPlayerAgent csak Isolated Storage-ban és távoli elérési úton elhelyezett audio fájlokat tud lejátszani. amiket szeretnénk majd lejátszani! Jelöljük ki a zenefájlokat.193.40.18.cs fájlban helyezzük el az alábbi metódust. 127 .0" VerticalAlignment="Top"> <Button Content="prev" x:Name="prevButton" Height="140" Width="140" Click="prevButton_Click"/> <Button Content="play" x:Name="playButton" Height="140" Width="140" Click="playButton_Click"/> <Button Content="next" x:Name="nextButton" Height="140" Width="140" Click="nextButton_Click"/> </StackPanel> <TextBlock x:Name="txtCurrentTrack" Height="75" HorizontalAlignment="Left" Margin="12.Folyamatok a háttérben <StackPanel Orientation="Horizontal" Width="420" Margin="18. Fontos megemlíteni. ehhez hasonló eredményt kell kapnunk.xaml. a Zune gyűjteményünkhöz nincs hozzáférése. é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.0. ábrán látható. így Zune-on keresztül a telefonra másolt zenéket ne is próbáljuk meg elérni! Az App.

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

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

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

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

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

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

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

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

.

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

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

logika.1-es verziót. Ilyen adatforrás például a SampleData MainViewModelSampleData. hogy ezt a forrást a tervező eszközök meg is jelenítsék. és kihasználja a Silverlight által biztosított adatkötési mechanizmust. 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 . 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. Ahhoz. mivel a taszkok egy része csupán a Mango frissítéssel vált elérhetővé! A sablonból generált projekt felépítését (6-3 ábra) érdemes tüzetesebben átvizsgálni. A ViewModels mappa fogja össze azokat az osztályokat. ami XAML formátumban rögzít néhány tesztbejegyzést a tervezésidejű megjelenítéshez (a Blend és a Visual Studio design felülete is ezt használja). megjelenítési felületek által elvárt formában tárolják az egyéb adatforrásból származó információt. hogyan tudjuk az MVVM modellnek megfelelően szervezni kódunkat. mivel példát mutat arra. amelyek az egyes oldalak.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.xaml állománya. megjelenítés).

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

IsNullOrEmpty(directoryName_in) && myIsolatedStorage.CreateDirectory(directoryName_in).hu/wp7.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. } } catch (Exception ex) { // Kivétel } } public void DeleteDirectory(string directoryName_in){ try { IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile. 8-4 Az elkészített jegyzetelő alkalmazás 196 .DirectoryExists(directoryName_in)) { myIsolatedStorage. Adatkezelés public void CreateDirectory(string directoryName_in) { try { IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.DeleteDirectory(directoryName_in).8. akik korábban Silverlight alatt használták ezt a funkciót.GetUserStoreForApplication(). Ráadásul. Az alkalmazás felhasználói felülete előre el van készítve. A projekt kiindulási anyagát a következő oldalról tölthetjük le: http://devportal. if (!string. } } catch (Exception ex) { // Kivétel } } { Láthatjuk. if(!string. Isolated Storage gyakorlat A következő gyakorlatban egyszerű jegyzetelő alkalmazást fogunk elkészíteni (8-4 ábra). 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.

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

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

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

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

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

hogy a gépünkről töltsünk fel adatokat a telefonon futó alkalmazásunk könyvtárába. sőt. amely szintén lehetőséget biztosít arra. hogy adatokat töltsünk le a telefonunkról (vagy emulátorunkról a számítógépünkre). mint az Isolated Storage esetén − nem oszthatjuk meg a többi alkalmazással! Linq To SQL A Linq To SQL egy ún. hogy kódunkban beágyazva fogalmazzunk meg lekérdezéseket. Ezt Microsoft SQL Server Compact Edition (CE) teszi lehetővé. amely a Visual Studio-ba épül be. azt –ugyanúgy. Ezt a kiegészítőt a következő oldalról tölthetjük le: http://visualstudiogallery. és így objektumorientált módon kezelhetjük adatainkat.NET Framework tartalmaz. Az SQL Servernél megszokott Transact SQL segítségével közvetlenül nem érhetjük el az adatbázist. amelyet a . az alkalmazásba beépülő módon működő relációs adatbázis-kezelő. amely egy fájl alapú. Ilyen eszköz például az Isolated Storage Tool (8-9 ábra). az 202 . Az adatbázist csak saját alkalmazásunk írhatja és olvashatja. hogy ez működjön. és azokat lefuttassuk az adott adatbázismotoron. ORM (Object Relational Mapping) keretrendszer.0 –ás) változatában nem volt beépített lehetőség.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. illetve lehetőséget biztosít arra is.microsoft.8. Ezt az adatbázist csak a Linq To SQL API segítségével érhetjük el.msdn. Ahhoz. a Mango frissítéssel viszont az Isolated Storage-ben az alkalmazásunk elhelyezhet relációs adatbázist is. olyan eszköz is létezik. A Linq To SQL lehetőséget biztosít arra. Adatkezelés ISETool.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 DataContextnek nevezzük (8-10 ábra). tulajdonságainak leírásához. Minden Table objektum entitásokból épül fel. amelyek speciális attribútumokkal van ellátva. Minden entitás egy „Plain Old CLR Object” (azaz POCO). ami megvalósítja a kapcsolatot az adatbázissal és az egyéb specifikus funkciókat is elvégzi. hogy ez az osztály tulajdonképpen az adatbázis egy táblájának reprezentációja lesz.Lokális adatbázisok használata Windows Phone 7-en adatbázisok világát közelebb kell hoznunk az objektumorientált világhoz. Ezekkel az attribútumokkal definiáljuk. 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 . azt speciális attribútumokkal kell ellátnunk az adatbázis speciális megkötéseinek. Ezt a két világot meg kell feleltetni egymásnak. A megfeleletésen kívül szükségünk lesz egy proxy objektumra is. Mapping A mapping maga a megfeleltetés egy adattábla és az azt reprezentáló objektum között. Ezt a táblát a DataContext-ben egy User osztály reprezentálja. akkor az adatbázisban található tábla neve az lesz. hogy az adott objektum milyen módon reprezentálja az adatbázist. A Table attribútumnál egy Name tulajdonságot is megadhatunk. 8-10 ábra: Lokális adatbázisok DataContext A DataContext egy proxy objektum. Ha nem adunk meg nevet. Ha megadjuk. amit megadtunk. hogy van egy ilyen osztályunk. amely az adatbázis tábláit reprezentálja. amelyek pedig a táblák oszlopait írják le. Ezt a megfeleltetést nevezzük mappingnek. Az osztályt ellátjuk egy Table attribútummal. amelyekben sorok és oszlopok találhatók. amelynek két tulajdonsága van: a Name és az Age. Azon kívül. míg egy objektumorientált programban entitások és tulajdonságok vannak. hogy dolgozni tudjunk az adatokon. Egyszerű POCO (Plain Old CLR Object) objektumokat és tulajdonságaikat speciális jelzésekkel – attribútumokkal – jelölhetünk meg. A DataContext Table típusú objektumokat tartalmaz. ugyanis az adatbázisoknál táblák vannak. ezek a tulajdonságok képzik az adatbázis oszlopait. akkor automatikusan az osztály neve lesz adatbázis táblájának a neve. hogy jelezzük. amely az adatbázist reprezentálja. melynek van egy Name és egy Age oszlopa. Az osztály tulajdonságait pedig a Column attribútummal látjuk el. Nézzünk egy példát. Ennek megértéséhez képzeljük el az alábbi példát: Van egy Users táblánk. ezzel jelezve.

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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. és másoljuk ki az ott megjelenített értéket (9-14 ábra)! 9-14 ábra: Access Control szolgáltatásunk menedzsment-jelszava 242 .9. Kattintsunk a Password elemre. majd válasszuk a Management Client elemet a Management Service Accounts listából! Megjelennek az Access Control szolgáltatásunk menedzseléséhez használható hitelesítési adatok.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

és kapcsoljuk ki a Frame rate számlálókat is! Ha ez megtörtént.1 SDK-ja óta ez a funkció már az emulátor mellett is megtalálható (12-13 ábra). majd a nagyítási beállításokat (nagyító ikon) állítsuk 100%-ra. akkor indítsuk el az 310 . de a Windows Phone 7.12. 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. 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. hogy legalább egy 480x800-as képernyőkép legyen az alkalmazásunkról mellékelve. A méretnek pontosnak kell lennie. és a képet nem szabad módosítanunk semmilyen grafikai eszközzel! A képernyőkép készítéséhez persze elég sokféle eszközt tudunk felhasználni: például Snipping tool. 12-13 ábra: Screnshot készítése Nézzük meg használat közben! Indítsuk el az alkalmazást.

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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