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

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

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Add(insName). a felhasználó csak számokat tud majd beírni ebbe a szövegdobozba (3-34 ábra). tbTitle.InputScope = ins.Alapvető WP7 vezérlők 3-33 ábra: Az InputScope kiválasztása egy TextBoxnál Ha például a Number beállítást választjuk. InputScopeName insName = new InputScopeName().Names. 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(). ins. insName.NameValue= InputScopeNameValue. 61 .

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

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

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

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

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

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

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

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

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

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

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

hogy sablont szerkesztünk Itt ugyanúgy rakhatjuk össze a felületet. Sokszor viszont több adatot is szeretnénk megjeleníteni egy elemről. 3-58 ábra – Az új adatsablon nevének és helyének megadása 3-59 ábra – A tervezőfelület tetején látható „breadcrumb” jelzi. a 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. Ilyenkor használhatunk adatsablonokat (data template). Ezen belül elsőre csak a „Create Empty…” választható. 73 . A ListBoxban lévő elemek sablonját úgy változtathatjuk meg. hogy jobb gombbal a ListBoxra kattintunk. majd az „Edit Additional Templates” menüpont alatt az „Edit Generated Items (ItemTemplate)” parancsot választjuk. mint ahogy az oldalakét is tettük. 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. gyakran elég lehet. hol jöjjön az létre (az erőforrások létrehozásából már ismerős lehet). ezzel hozhatunk létre új adatsablont (3-57 ábra).

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

csupán a tartalomnak beállított szöveget mutatják az adott pozíción. Content = "C#" }). Az így kapott jelöléseink végtelenül egyszerűek. csupán koordináták és kiírandó szöveg megadásával használható vezérlő. Ennek eszköze a szintén a Maps vezérlő névtérhez tartozó Pushpin osztály.63876. de akár dinamikus listákat is köthetünk a vezérlőhöz. amint azt a 4-6 ábra is mutatja. címek. 4-6 ábra: Egyszerű Pushpinek a térképen 89 . viszont szükség esetén a Silverlightban megszokott könnyedséggel testre is szabhatjuk azt.639655. 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. Ez egyszerűen. -122.Children.GeoCoordinate(47.12862). Ezeket a pushpineket akár egyesével.-122.Device.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.Location. megjelölt pozíciók nélkül.Add(new Pushpin { Location = new System.Térképek kezelése 4-5 ábra: A térkép pozicionálva és nagyítva Aerial módban Pushpinek Egy térkép mit sem érne kiemelt információk.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.0.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.png" Margin="6" Background="#FF008000" GroupTag="TileGroup" Notification="Noti" Message="Microsoft Minősített Szerviz Partner project"> <toolkit:ContextMenuService.place additional content here--> <toolkit:WrapPanel x:Name="ContentPanel" Grid.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.12. 110 .ContextMenu> </toolkit:HubTile> <toolkit:HubTile Name="hirekTile" Tap="hirekTile_Tap" Title="Hírek" Source="Images/news.Row="1" Margin="12.png" Margin="6" Background="#A500FF" GroupTag="TileGroup" Notification="Noti" Message="Microsoft Minősített Szerviz Partner project"> </toolkit:HubTile> </toolkit:WrapPanel> </Grid> A fenti kód pedig (természetesen a képek Images mappába másolása után) a 4-27 ábrán látható megjelenést eredményezi.png" Background="#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.4.0"> <toolkit:HubTile Tap="hirekTile_Tap" Title="Minden" Source="Images/all.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

9. 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 . 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.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

13. Teljesítmény

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

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

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

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

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

326

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

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

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

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

13. Teljesítmény

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

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

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

UI szál frame rate

328

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

Counter

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

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

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

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

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

329

13. Teljesítmény

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

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

330

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

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

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

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

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

331

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful