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

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

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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. hogy mely esemény hatására (EventName) mely állapotba szeretnénk átváltani (StateName). é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. Ennek eredményét az Objects and Timeline ablakban is láthatjuk (3-75 ábra). 80 . 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. 3-75 ábra: A GoToStateAction Behavior.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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. az egyszerű címkereséssel és az útvonaltervezéssel. de könnyedén varázsolhatjuk a Metro stílushoz és a Mango felhasználói felület koncepciójához illeszkedő megjelenésűnek azokat.Ö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. 111 . ezek között a kiemelt pozíciók jelölésével. Ezekkel a módszerekkel nemcsak hogy rendkívül egyszerűen valósíthatunk meg komplex alkalmazásokat. Végül a Silverlight Toolkit előnyeit ismerhettük meg.

.

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

megjelenítés). 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. amelyek az egyes oldalak. hogy ezt a forrást a tervező eszközök meg is jelenítsék. hogyan tudjuk az MVVM modellnek megfelelően szervezni kódunkat.A példaalkalmazás létrehozása 6-2 ábra: Windows Phone Pivot Application sablon kiválasztása a projekt létrehozásakor A következő dialógusban mindenképpen válasszuk a Windows Phone OS 7. ami XAML formátumban rögzít néhány tesztbejegyzést a tervezésidejű megjelenítéshez (a Blend és a Visual Studio design felülete is ezt használja). logika. és kihasználja a Silverlight által biztosított adatkötési mechanizmust. csak az alábbi attribútumokat kell hozzáadni a PhoneApplicationPage deklarációjához (természetesen a sablon alapján ezt a VS már megtette helyettünk): 139 .xaml állománya.1-es verziót. mivel példát mutat arra. 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. 6-3 ábra: A sablon által generált projekt Ez a megközelítés a lehető legjobban elválasztja a különböző felelősségeket (adatszolgáltatás. A ViewModels mappa fogja össze azokat az osztályokat.

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

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

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

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

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

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

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

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

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

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

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

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

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

Kamera használata taszk nélkül

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

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

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

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

153

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

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

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

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

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

154

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

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

155

6. Alapvető telefonos funkciók használata

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

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

156

Kamera használata taszk nélkül

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

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

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

157

6. Alapvető telefonos funkciók használata

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

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

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

158

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

tehát csak a fejlesztői zárolás feloldásával ellátott készüléken tudjuk ezt megtenni. hogy az alkalmazásunk számára milyen Capability beállításokat (képességeket) kell meghatároznunk a WPAppManifest. 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. Ha lefuttatjuk a tesztet. 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. 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. akkor a teszt megmondja. Az Application Details alatt megadott képeket is itt teszteljük. Marketplace 12-15 ábra: Application Details (Marketplace Test Kit) Automated Tests Az Automated Tests fülön (12-16 ábra) az általános kritériumokat tudjuk tesztelni.

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

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

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

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

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

.

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

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

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

ábra grafikonján: 13-2 ábra: csillagok kirajzolási ideje emulátoron és telefonon 322 .13. 388 ms A programnak azonban a telefonon kell futnia. De mi történik. 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. ha nem csak 100. Teljesítmény 13-1 ábra: 100 csillag.

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

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

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

13. Teljesítmény

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

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

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

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

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

326

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

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

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

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

13. Teljesítmény

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

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

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

UI szál frame rate

328

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

Counter

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

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

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

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

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

329

13. Teljesítmény

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

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

330

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

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

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

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

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

331

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful