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

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

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

aláhúzott) betűformázási lehetőségeket is megkapjuk (3-21 ábra). amelynek nem kell szöveget megjelenítenie.Alapvető WP7 vezérlők 3-19 ábra: Parancsvezérlők a felületen Szövegmegjelenítési vezérlők Nagyon kevés olyan program van. A Silverlightban erre elsősorban két vezérlőt használunk: egyszerű szövegmegjelenítésre a TextBlockot. Egyebek között átállíthatjuk a betűtípust. 55 . Egyszerű szövegmegjelenítés a TextBlockkal Ahogy korábban láttuk. illetve a szokásos (félkövér. a Windows Phone Application sablon rögtön két TextBlockot is beépít alkalmazásunk felületébe. a betűk méretét. 3-20 ábra: A TextBlock szövegének beállítása A Text csoportban található tulajdonságok segítségével szabhatjuk testre a szöveg kinézetét. Vegyük szemre a PageTitle nevűt! A TextBlock által megjelenített szöveget a Text tulajdonság segítségével adhatjuk meg (3-20 ábra). dőlt. bonyolultabban formázott megjelenítésre pedig a RichTextBoxot.

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

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

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

A MaxLength tulajdonsággal megszabhatjuk. illetve kódból itt állíthatjuk be a szövegdoboz szövegét. avagy szövegdoboz segítségével a felhasználó a telefon virtuális vagy fizikai billentyűzete segítségével adatokat vihet be az alkalmazásba. ahogy a két előző vezérlőnket is a szövegvezérlők csoportjában találjuk a Toolboxon (3-30 ábra).Alapvető WP7 vezérlők Szövegbevitel a TextBoxszal A TextBox. hogy legfeljebb hány karaktert írhasson be a felhasználó a szövegdobozba. a Toolboxon Nem meglepő módon a TextBox vezérlő Text tulajdonságán keresztül érhetjük el. 3-31 ábra A TextBox tulajdonságainak beállítása a Properties panelen 59 . 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. 3-30 ábra – A TextBox helye a szövegvezérlők között. a MaxLength csak a felhasználói adatbevitelt szabályozza. A TextBoxot.

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

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

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

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

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

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

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

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

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

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). 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. szép. és létrejön az adatkötés (3-50 ábra). nem lehetne egy kicsit központosítani az adatkötést? Természetesen lehet. de ha sok tulajdonságot szeretnénk egyazon objektumról megjeleníteni.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

115

5. Az alkalmazás életciklusa

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

116

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

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

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

117

5. Az alkalmazás életciklusa

Esemény Launching Activated Deactivated Closing OnNavigatedFrom OnNavigatedTo

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

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

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

118

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

  

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

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

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

119

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

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

120

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

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

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

121

5. Az alkalmazás életciklusa

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

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

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

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

122

Állapotok kezelése

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

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

123

5. Az alkalmazás életciklusa

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

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

124

Folyamatok a háttérben

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

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

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

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

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

125

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful