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

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

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

illetve 1024x800-as felbontásban. 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. Toggle. 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. időben eltolódva hajtódnak végre. ezáltal rendkívül látványos. Háttérképként jellemzően JPEG ajánlott 480x800-as. 40 . Map vezérlők). A Panorama vezérlővel ellentétben nem egyetlen nagy téren helyezkednek el az egyes szekciók. Az animáció során a tartalom és a feliratok különböző sebességgel.2. A vezérlő önálló. 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. 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. dinamikus parallaxszerű effektust eredményezve. és biztosítja a navigációt közöttük. elkülönített nézeteket helyez el egymás mellett. A vezérlő használatakor néhány dolgot célszerű szem előtt tartani:      Pivot vezérlőket ne ágyazzunk egymásba! Ne kombináljuk a Pivot és a Panorama vezérlőket! Ne használjunk túl sok Pivot elemet. valamint az átméretezés elkerülését. illetve horizontális mozgatással lehetséges. a görgetés során pedig egészen egyedi animációval és tulajdonságokkal rendelkezik. Felhasználói élmény tervezése Windows Phone-on 2-18 ábra: A Panorama vezérlő A Panorama vezérlő messze túlnyúlik a látható területen. A navigáció a menüelemek fejlécét érintve.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Alkalmazásfejlesztés Windows Phone-on 3-38 ábra: A ListBox tulajdonságainak beállítása a Properties panelen Ha az Items melletti „…” gombra kattintunk. Az „Add another item” gombra kattintva kiválaszthatjuk a ListBoxhoz hozzáadni kívánt elem típusát. Egy stringet hozzáadva (az mscorlib|Systemben találjuk) a szerkesztőablak jobb oldalán megjelenik a karakterlánc. melyben szerkeszthetjük a ListBox tartalmát. az Object Collection Editor ablak jelenik meg. Az egyes elemek sorrendjét az ablak alján lévő nyilakkal változtathatjuk meg. 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 .3. amit átírhatunk. illetve az „X” gombbal törölhetünk egy elemet (3-39 ábra).

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

törlünk párat. Mindkettő az ItemsControlból. 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. és megnyomjuk a vissza gombokat! Ha minden jól működik. nem véletlen. 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. Szorosabban kapcsolódó adatok megjelenítésére vagy egyszerűen látványosabb UI létrehozására is két remek vezérlő áll rendelkezésünkre. 4-17 ábra: A Pivot és Panorama kapcsolata az osztályhierarchia alapján Példák a vezérlők alkalmazására az Office programból: 103 . majd a végén meglátogatjuk a navigációt összegző lapot. horizontálisan elnyúló vezérlő. hogy bejárjuk az összes oldalt. A WP7 programok kinézetének meghatározó formálói. pontosabban a TemplatedItemsControlból származik (4-17 ábra). hogyan tudjuk alkalmazásunkat oldalakkal strukturálni.Pivot és Panorama <local:NavigationBar VerticalAlignment="Bottom" /> Próbáljuk ki alkotásunkat úgy. A Pivot és a Panorama két nagyon hasonló.

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

987-6543". 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.To = "123-4567. de mindkét érték elhagyható: private void btnSmsComposeTask_Click(object sender.Body = "szöveg". A címzetteket a + gombra kattintva kiegészíthetjük. smsComposeTask. smsComposeTask. smsComposeTask.Show(). 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. Természetesen a küldés az emulátoron meg fog hiúsulni. ahogyan az üzenet szövegét is átírhatjuk. RoutedEventArgs e) { SmsComposeTask smsComposeTask = new SmsComposeTask().Launcherek 6-4 ábra: Telefonhívás lebonyolítása alkalmazásunkból SmsComposeTask Sms küldésekor lehetőségünk van megadni a címzettek listáját és az üzenet szövegét is.

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

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

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

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

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

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

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

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

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

Kamera használata taszk nélkül

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

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

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

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

153

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

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

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

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

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

154

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

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

155

6. Alapvető telefonos funkciók használata

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

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

156

Kamera használata taszk nélkül

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

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

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

157

6. Alapvető telefonos funkciók használata

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

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

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

158

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Megismerkedtünk az XNA Framework alapvető használatával. Játékok a Mango világában fejlesztésébe. melyet az Olvasó tetszése szerint tovább bővíthet. Éppen csak a felszínt érintve áttekintettük a számítógépes grafika elméleti hátterét és ennek kapcsán a játékokat alkotó grafikus megoldásokat is. 300 . Az utóbbira építve elkészítettük egy Snake játéknak az alapjait is.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.

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

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

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

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

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

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

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

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

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

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

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

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

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

com/windowsphone/2009/deployment" AppPlatformVersion="7. a beállításokat a WMAppManifest.png</IconPath> <Capabilities> <Capability Name="ID_CAP_CONTACTS"/> <Capability Name="ID_CAP_APPOINTMENTS"/> </Capabilities> <Tasks> <DefaultTask Name ="_default" NavigationPage="MainPage. hogy melyik lapot töltse be az alkalmazás indulásakor. Marketplace az alkalmazáshoz.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. File Méret (Pixel) Fájl típus PNG Project File Példa Small app icon 62 x 62 ApplicationIcon. milyen legyen a háttere (Background) vagy éppen az ApplicationIcon neve és elérhetősége.0" Genre="apps. Ebben a részben áttekinthetjük. hogy mi legyen az alkalmazás címe (Title).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. és hogyan is használhatjuk fel azokat. Marketplace Task Az előző fejezetekben már foglalkoztunk a launcherekkel. Ehhez négy taszk áll a rendelkezésünkre:   MarketplaceHubTask MarketplaceDetailTask 314 .xml fájlban testreszabhatjuk. Az alkalmazásunkból elindíthatjuk a Marketplace alkalmazást. akkor láthatjuk.xaml"/> </Tasks> <Tokens> <PrimaryToken TokenID="MarketPlaceSampleToken" TaskName="_default"> <TemplateType5> <BackgroundImageURI IsRelative="true" IsResource="false">Background.0. melyek ezek.12. hogy itt az alkalmazásunkkal kapcsolatban speciális tulajdonságokat adhatunk meg. 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.png 173x173 PNG <Deployment xmlns="http://schemas.0.microsoft.png Large app tile Background. Leírhatjuk.

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

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

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

.

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

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

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

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

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

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

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

13. Teljesítmény

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

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

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

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

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

326

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

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

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

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

13. Teljesítmény

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

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

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

UI szál frame rate

328

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

Counter

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

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

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

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

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

329

13. Teljesítmény

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

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

330

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

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

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

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

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

331

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

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

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

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

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

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

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

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

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

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

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

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