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

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

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

amit a program fel tud dolgozni. és a felhasználó különböző parancsokat futtathat. Ha ezek után fut az alkalmazás. De gyorsan szembe kerülünk azzal az igénnyel. a link már jól fog működni – ha megérintik. hogy megkönnyíthessék a felhasználói adatbevitelt. A Silverlight számos speciálisabb vezérlőt kínál a fejlesztőknek. megnyílik az Internet Explorerben a megadott weblap. hanem ő maga adhasson meg valamilyen bemenetet. hogy ne csak a felkínált lehetőségek közül választhasson. 3-29 ábra – Osztott nézetben egyszerre látjuk a tervezőfelületet és a hozzá tartozó XAML-t Szövegbeviteli vezérlők Szövegeket kiírni már tudunk. 58 . Alkalmazásfejlesztés Windows Phone-on 3-28 ábra: A tervezőfelület jobb felső sarkában található nézetváltó gombok A XAML-ben meg kell keresni a Hyperlink elemet. és TargetName tulajdonságának a „_blank” értéket kell adni.3. vagy éppen választhat lehetőségek közül. de legáltalánosabb adatbeviteli vezérlő mindig is a TextBox marad.

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

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

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

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

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

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

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

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

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

3. Ezzel véletlenszerű mintaadatokkal feltöltött adatforrásokat hozhatunk létre. majd annak jobb felső sarkában a „Create data source” gomb alatt válasszuk a „Create Object Data Source…” pontot (3-47 ábra)! 3-47 ábra: Adatforrás létrehozása a Data panelen A Data panel tetején találunk egy másik gombot is.} public Character() { Name = "Hubert Farnsworth". set. és megjelenik. a „Create sample data” nevűt. vagy hiányzik a program szerelvénye a listából. Hasznos a fejlesztésnek abban a fázisában. Alkalmazásfejlesztés Windows Phone-on Több vezérlő kötése egyazon forráshoz Tekintsük az alábbi osztályt: public class Character { public string Name {get. A megjelenő ablakban válasszuk ki a Character osztályt. illetve adjuk meg az adatforrás nevét! (Ha még nem jelenne meg az osztály. ahol a tényleges adatok még nem állnak rendelkezésre. és jelenítsük meg mindkét tulajdonságát egy-egy TextBlockban (3-46 ábra)! 3-46 ábra: A program felülete Ehhez kattintsunk a Data panelre. set.) 68 .} public string City {get. } } Hozzunk létre egy példányt ebből az oldalon. fordítani vagy futtatni kell. City = "New New York".

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

115

5. Az alkalmazás életciklusa

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

116

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

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

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

117

5. Az alkalmazás életciklusa

Esemény Launching Activated Deactivated Closing OnNavigatedFrom OnNavigatedTo

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

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

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

118

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

  

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

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

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

119

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

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

120

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

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

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

121

5. Az alkalmazás életciklusa

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

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

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

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

122

Állapotok kezelése

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

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

123

5. Az alkalmazás életciklusa

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

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

124

Folyamatok a háttérben

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

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

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

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

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

125

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

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

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

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

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

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

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

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

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

hogy semmilyen esetben se veszhessenek el a felhasználó munkafolyamataihoz tartozó adatok. Az új multitasking környezet számos új dolgot tesz lehetővé a fejlesztőknek. 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. és arról gondoskodnak. 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. melyek az alkalmazást segítik beilleszkedni a Windows Phone életciklus modelljébe. Az elméleti bevezetést követően gyakorlatban is láthattuk azokat a lépéseket. 135 .Összefoglalás Összefoglalás A fejezetben láthattuk. Láthattuk. ahol a megfelelő objektumok végrehajtják az általunk megvalósított feladatok logikáját. hogy nem végezhetünk akármit szabadon a háttérben.

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Kamera használata taszk nélkül

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

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

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

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

153

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

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

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

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

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

154

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

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

155

6. Alapvető telefonos funkciók használata

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

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

156

Kamera használata taszk nélkül

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

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

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

157

6. Alapvető telefonos funkciók használata

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

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

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

158

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful