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

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

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Az ennél nagyobb vagy kisebb képek átméretezésre kerülnek. ami torzításhoz. 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ű. melyek a megfelelő Windows Phone témák esetén „transzparens” háttérként funkcionálnak (2-16 ábra) Transzparens háttereket. 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 . ellenkező esetben az alapértelmezett lapka kerül átméretezésre. Fontos. JPEG vagy PNG formátumban. felfelé vagy lefelé. vágáshoz vezethet. hogy a Marketplace-ből kisebb eséllyel kerül letöltésre. Különböző képek használata esetén azonban maradjunk minden esetben konzisztensek! A lapkák tervezése során kerüljük el az alábbiakat:      3D-s lapkák használatát A gradiensek használatát. árnyékok alkalmazását Lekerekített lapkákat Fekete vagy fehér háttereket. Ezenfelül az alkalmazás listába érdemes külön 63x63 pixeles képet biztosítani.2. hogy megragadja a szemet! A lapka képeknek 173x173 pixel méretűeknek kell lenniük.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

NameValue= InputScopeNameValue.InputScope = ins. a felhasználó csak számokat tud majd beírni ebbe a szövegdobozba (3-34 ábra). insName. ins. 61 .Names.Number. 3-34 ábra: Number InputScope-úra beállított TextBox Ugyanezt természetesen kódból is beállíthatjuk.Alapvető WP7 vezérlők 3-33 ábra: Az InputScope kiválasztása egy TextBoxnál Ha például a Number beállítást választjuk. tbTitle.Add(insName). InputScopeName insName = new InputScopeName(). így akár futás közben is változtatható egy TextBoxhoz rendelt billentyűzet: InputScope ins = new InputScope().

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

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

Az egyes elemek sorrendjét az ablak alján lévő nyilakkal változtathatjuk meg. illetve az „X” gombbal törölhetünk egy elemet (3-39 ábra). Az „Add another item” gombra kattintva kiválaszthatjuk a ListBoxhoz hozzáadni kívánt elem típusát.3. 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. melyben szerkeszthetjük a ListBox tartalmát. 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. 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 . amit átírhatunk.

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

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

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

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

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). de ha sok tulajdonságot szeretnénk egyazon objektumról megjeleníteni. 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. Vezérlőink DataContext tulajdonsága szolgál 69 .Adatkötés 3-48 ábra: Az adatforrás típusának kiválasztása A Data panelen megjelenik az új adatforrás (3-49 ábra). szép.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4.Maps. public MainPage() { InitializeComponent().-122. azokat csak példányosítani kell..639655. 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. beállításokat tartalmazza.Mode> <maps:AerialMode /> </maps:Map." Center="47. //.Mode = new AerialMode(). } 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..Mode> <maps:AerialMode /> </maps:Map.Phone..129404" ZoomLevel="17" ZoomBarVisibility="Visible" LogoVisibility="Collapsed" CopyrightVisibility="Collapsed"> <maps:Map.129404" ZoomLevel="17" ZoomBarVisibility="Visible"> <maps:Map. 88 ...-122.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.Controls.Mode> </maps:Map> A kód hatására meg is jelenik egy teljes funkcionalitással bíró térkép. középen a Microsoft főhadiszállásával. például az alábbi módszerrel: using Microsoft. Haladó alkalmazásfejlesztés Windows Phone-on értékeket. myMap. akkor a teljes eddigi kódunk (a névtér definíciója mellett) csupán ennyi: <maps:Map Name="myMap" CredentialsProvider="Ajdyq5FaN2RZvzvogm_..639655.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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. Végül a Silverlight Toolkit előnyeit ismerhettük meg. 111 . azokon belül pedig a Panorama és Pivot vezérlőket. ezek között a kiemelt pozíciók jelölésével.Összefoglalás 4-27 ábra: HubTile-ok WrapPanelbe csomagolva Összefoglalás A fejezet elején részletesen megismerkedhettünk a Bing Maps szolgáltatás felhasználási lehetőségeivel. Ezt követően átnéztük a tartalmak rendszerezésére szolgáló műveleteket: az oldalak kezelését. az egyszerű címkereséssel és az útvonaltervezéssel. Ezekkel a módszerekkel nemcsak hogy rendkívül egyszerűen valósíthatunk meg komplex alkalmazásokat.

.

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

akkor a teszt megmondja. Marketplace 12-15 ábra: Application Details (Marketplace Test Kit) Automated Tests Az Automated Tests fülön (12-16 ábra) az általános kritériumokat tudjuk tesztelni.12. például az alkalmazás méretét és képeit.xml fájlban. Az Application Details alatt megadott képeket is itt teszteljük. 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. 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. 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 . Ha lefuttatjuk a tesztet.

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful