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

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

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

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

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

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

.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

40 . Toggle. dinamikus parallaxszerű effektust eredményezve. Felhasználói élmény tervezése Windows Phone-on 2-18 ábra: A Panorama vezérlő A Panorama vezérlő messze túlnyúlik a látható területen. A vezérlő használatakor néhány dolgot célszerű szem előtt tartani:      Pivot vezérlőket ne ágyazzunk egymásba! Ne kombináljuk a Pivot és a Panorama vezérlőket! Ne használjunk túl sok Pivot elemet. Ez biztosítja a jó teljesítményt és a gyors betöltést. Háttér meghatározásakor gondoskodjunk a megfelelő kontrasztról a fontok és a háttér között! Ne menjen a design az olvashatóság kárára! Ne használjunk olyan egyéb vezérlőket a Panorama egyes nézeteiben. A vezérlő önálló. illetve horizontális mozgatással lehetséges. 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. 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. Az animáció során a tartalom és a feliratok különböző sebességgel. ezáltal rendkívül látványos. valamint az átméretezés elkerülését.2. 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. Háttérképként jellemzően JPEG ajánlott 480x800-as. A Panorama vezérlővel ellentétben nem egyetlen nagy téren helyezkednek el az egyes szekciók. és biztosítja a navigációt közöttük. illetve 1024x800-as felbontásban. elkülönített nézeteket helyez el egymás mellett. a görgetés során pedig egészen egyedi animációval és tulajdonságokkal rendelkezik. Map vezérlők). A navigáció a menüelemek fejlécét érintve.

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

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

3. Különböző vizuális állapotokat hozhatunk létre. Többek között a VS ezen gyenge pontját ellensúlyozandó hozta létre a Microsoft az Expression termékcsaládot. A Visual Studio 2010 elsősorban a fejlesztőknek készült. akár több már meglévő elem együttes használatával. áttekintő összefoglalást kíván adni. amelyek segítségével a legegyszerűbbtől a legbonyolultabb üzleti alkalmazásokig bármilyen felhasználói felületet átlátható. 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. amelyekkel akár az egyes vezérlők. izgalmassá. de korábban megszerzett tudása azonnal és közel száz százalékosan átvihető WP7-re. hogy kiterjesszük azokat – új tulajdonságokat. viselkedést adjunk nekik –. hogy segítsék a dizájnerek és a fejlesztők együttműködését. Azonban a felületek kialakítása egyes esetekben eléggé fájdalmas tud lenni a VS használatával. A vezérlők kinézetét egy nagyszerű vezérlősablonrendszerrel. 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. é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 –. 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. sok minden megegyezik az „asztali” Silverlighttal. Ebben a fejezetben ezeket a témaköröket nézzük meg közelebbről. egységes módon. akár a teljes felület bizonyos helyzetekben felvett megjelenítését írhatjuk le központi. Alkalmazásfejlesztés Windows Phone-on Az eredetileg RIA fejlesztésre kialakított Silverlight keretrendszer talán legfontosabb alapgondolata a gazdag tartalmú. ezért. 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. összetett felhasználói felületek (a továbbiakban UI – User Interface) kialakításának támogatása. Ahogy a Silverlight „asztali” verziójában is. a Windows Phone 7-re átszabott változatban is két nagyobb részben jelenik meg ennek megvalósítása: a vezérlőkönyvtárban. Előbbiben értelemszerűen a vezérlőket találjuk. 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. Az adatkötésirendszerrel és az adatsablonok használatával pedig rengeteg kódot megspórolva építhetünk dinamikus. és lehetőséget adnak arra. és az ezekben leírtak komolyabb változtatások nélkül alkalmazhatók Windows Phone 7-fejlesztésben is. Ennek a fejezetnek az első részében ezekkel az építőelemekkel ismerkedünk meg. Az Expression termékek elsősorban a dizájnereknek készültek – ahogy a Silverlight elődjét. ahogy látni is fogjuk. Mivel már rengeteg könyv megjelent Silverlight 4 témában. Ezek azok az alapvető építőelemek. illetve saját vezérlőket hozzunk létre. 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. A fejezet során végig az Expression Blend 4 segítségével hozzuk létre és szabjuk testre a felületeket. ez a fejezet csak egy gyors. amelyek a felületek építéséhez elengedhetetlenek. illetve stílusok segítségével változtathatjuk meg. adatfüggő felületeket. az is találhat néhány új dolgot (például az InputScopeok). amelyek testre szabhatóvá. 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. ezenfelül pedig könnyedén animálhatjuk azokat. kézre álló módon felépíthetünk. könnyen használhatóvá teszik a vezérlőket. 43 . illetve a keretrendszer UIhoz kapcsolódó szolgáltatásaiban. a Windows Presentation Foundationt is azzal a céllal hozták létre. 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 Samples fülön mintaalkalmazásokat tekinthetünk meg. Alul nevet adhatunk az alkalmazásnak (BaseControlsSample). majd áttérünk a szövegmegjelenítésre és a szövegbevitelre. kiválaszthatjuk a projekt fizikai helyét a merevlemezen. amint azt a 3-2 ábra mutatja. amelyen létrehozhatunk új projektet vagy megnyithatunk egy már létezőt. a Close gombbal (Alt+C) bezárhatjuk az alkalmazást. Hozzunk is létre egy alkalmazást a Blend 4 segítségével! Az Expression Blendet a Start Menü az All Programs menüpontban a Microsoft Expression mappában találjuk. A ListBox osztályon keresztül áttekintjük a listavezérlők általános használatát. 3-2 ábra: Sablon kiválasztása 44 . illetve beállíthatjuk a Windows Phone verziót (7. A bal oldali listából a Windows Phone pontot. amelyek részét képezik a WP7 fejlesztői csomagnak. Az egyszerűség kedvéért egyetlen alkalmazáson belül helyezzük el ezeket a vezérlőket. A File menü New Project menüpontjára kattintva hozhatunk létre új projektet (3-1 ábra).1). Alkalmazásfejlesztés Windows Phone-on Megjegyzés: mind a Visual Studio 2010. Alapvető WP7 vezérlők Ebben a részben először az alapvető parancskiadási vezérlőkkel foglalkozunk. érjük be a C#-pal). mind az Expression Blend 4 rendelkezik ingyenes. kifejezetten WP7-fejlesztésre kihegyezett verzióval. illetve segítséget kérhetünk a program használatával kapcsolatban (Help fül). hogy milyen projektet szeretnénk létrehozni. Elindítása után egy nyitóképernyő fogad. A legtöbb programnál szokásos főmenü itt is elérhető. a jobb oldalon pedig a Windows Phone Application projektsablont kell választanunk.3. illetve megadhatunk egyéb beállításokat. nyelvet választhatunk (főtt marha nincs. 3-1 ábra: Új projekt létrehozása Expression Blenddel A megjelenő ablakban választhatjuk ki.

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

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

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

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

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

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

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

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

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

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

Egyebek között átállíthatjuk a betűtípust. dőlt. amelynek nem kell szöveget megjelenítenie. 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. 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). aláhúzott) betűformázási lehetőségeket is megkapjuk (3-21 ábra). 3-20 ábra: A TextBlock szövegének beállítása A Text csoportban található tulajdonságok segítségével szabhatjuk testre a szöveg kinézetét. A Silverlightban erre elsősorban két vezérlőt használunk: egyszerű szövegmegjelenítésre a TextBlockot. illetve a szokásos (félkövér. a betűk méretét. 55 .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.

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

hanem akár karakterenként mást és mást (3-25 ábra). hogy hivatkozássá alakítsuk 3-27 ábra – A Create Hyperlink gomb és ablak Ahogy korábban a HyperlinkButton esetén. és átállíthatóak jellemzői. Amellett. A RichTextBox WP7-es implementációja nem teszi lehetővé szöveg bevitelét vagy szerkesztését a felhasználó számára. A szöveg bármely része kijelölhető. hogy programozottan töltsük fel szöveggel. milyen linket kell megnyitni. ha a Text csoportban lévő földgömb gombra kattintunk (3-27 ábra). 57 . 3-26 ábra: A szöveg egy részének kijelölése. 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. Sajnos erre a tervezőfelületen belül nincs lehetőség. képek stb. és a XAML-t. a helyzet azonban — legalább is jelen pillanatban — nem ez. hogy az egyszerű szövegeknél bonyolultabb elemeket is meg tud jeleníteni. tartalma rögtön szerkeszthetővé is válik (3-26 ábra). hogy egy szövegbeviteli vezérlőről lehet szó. illetve egyéb elemekkel – hivatkozások. A tervezőfelület jobb felső sarkában találjuk a nézetváltó ikonokat (3-28 ábra). hogy a hivatkozás tudja. ahol egyszerre látjuk a tervezőfelületet. a RichTextBox igazi előnye.Alapvető WP7 vezérlők Formázott szövegek megjelenítése a RichTextBoxszal A RichTextBox neve azt sugallja. Sőt. a legalsóval válthatunk osztott nézetbe. rögtön hivatkozást is befűzhetünk a szövegbe. csupán arra ad lehetőséget. kézzel kell beleírni a XAML-be. – a vezérlőt. Amint elhelyezünk egyet a felületen. 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 link már jól fog működni – ha megérintik. Alkalmazásfejlesztés Windows Phone-on 3-28 ábra: A tervezőfelület jobb felső sarkában található nézetváltó gombok A XAML-ben meg kell keresni a Hyperlink elemet. és a felhasználó különböző parancsokat futtathat. De gyorsan szembe kerülünk azzal az igénnyel. A Silverlight számos speciálisabb vezérlőt kínál a fejlesztőknek. hogy megkönnyíthessék a felhasználói adatbevitelt. 58 . hanem ő maga adhasson meg valamilyen bemenetet. vagy éppen választhat lehetőségek közül. Ha ezek után fut az alkalmazás.3. 3-29 ábra – Osztott nézetben egyszerre látjuk a tervezőfelületet és a hozzá tartozó XAML-t Szövegbeviteli vezérlők Szövegeket kiírni már tudunk. hogy ne csak a felkínált lehetőségek közül választhasson. de legáltalánosabb adatbeviteli vezérlő mindig is a TextBox marad. amit a program fel tud dolgozni. és TargetName tulajdonságának a „_blank” értéket kell adni. megnyílik az Internet Explorerben a megadott weblap.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

és pontosan mely tulajdonságaik. hanem egy másodperc alatt változik az Opacity értéke 1-ről 0-ra és vissza.tutsplus. 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. 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. megadhatjuk. hogy mennyi ideig tartson (1s). hogy a felületen lévő vezérlők közül melyek animáltak. A VisualState-ek témaköre ennél természetesen jóval terebélyesebb. és a gombok is egy másodperc alatt csúsznak egyik helyről a másikra.3. Néhány link a továbblépéshez: Mike Taulty bevezető screencastja a VisualState-ekhez: http://active. illetve hogy milyen görbe mentén történjen (EasingFunction). Amikor kijelölünk egy állapotátmenetet a States panelen. 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ó. 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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ö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. ezek között a kiemelt pozíciók jelölésével. Ezekkel a módszerekkel nemcsak hogy rendkívül egyszerűen valósíthatunk meg komplex alkalmazásokat. de könnyedén varázsolhatjuk a Metro stílushoz és a Mango felhasználói felület koncepciójához illeszkedő megjelenésűnek azokat. Végül a Silverlight Toolkit előnyeit ismerhettük meg. azokon belül pedig a Panorama és Pivot vezérlőket. 111 . az egyszerű címkereséssel és az útvonaltervezéssel. Ezt követően átnéztük a tartalmak rendszerezésére szolgáló műveleteket: az oldalak kezelését.

.

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

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

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

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

ábra: A projekt struktúrája Következő tennivalónk a zenefájlok átmásolása az Isolated Storage-ba.0. amiket szeretnénk majd lejátszani! Jelöljük ki a zenefájlokat.193. így Zune-on keresztül a telefonra másolt zenéket ne is próbáljuk meg elérni! Az App. ábrán látható. jobb kattintással rajtuk a Properties parancsot választva állítsuk be a Copy To Output Directory tulajdonságot a Copy if newer opcióra! Az én projekt struktúrám az 5-6.xaml.Folyamatok a háttérben <StackPanel Orientation="Horizontal" Width="420" Margin="18. és ne felejtsük azt az App osztály konstruktorából meghívni! Természetesen a zeneszámokat tartalmazó fájlok listáját mindenkinek a saját fájljaira kell szabnia. a Zune gyűjteményünkhöz nincs hozzáférése. 127 . ehhez hasonló eredményt kell kapnunk.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. 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.40. Fontos megemlíteni. 5-6.18.0" VerticalAlignment="Top" Width="438" TextWrapping="Wrap" /> </Grid> Hozzunk létre egy új mappát és másoljuk bele az MP3 fájlokat.

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

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

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

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

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

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

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

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

.

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

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

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. 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. 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 . és kihasználja a Silverlight által biztosított adatkötési mechanizmust. Ahhoz.1-es verziót. megjelenítés). ami XAML formátumban rögzít néhány tesztbejegyzést a tervezésidejű megjelenítéshez (a Blend és a Visual Studio design felülete is ezt használja). logika. A ViewModels mappa fogja össze azokat az osztályokat. megjelenítési felületek által elvárt formában tárolják az egyéb adatforrásból származó információt. Ilyen adatforrás például a SampleData MainViewModelSampleData. amelyek az egyes oldalak. mivel példát mutat arra.xaml állománya. hogy ezt a forrást a tervező eszközök meg is jelenítsék. 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. hogyan tudjuk az MVVM modellnek megfelelően szervezni kódunkat.

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

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

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

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

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

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

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

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

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

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

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

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

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

Kamera használata taszk nélkül

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

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

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

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

153

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

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

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

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

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

154

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

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

155

6. Alapvető telefonos funkciók használata

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

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

156

Kamera használata taszk nélkül

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

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

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

157

6. Alapvető telefonos funkciók használata

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

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

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

158

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

Xna. amelyen keresztül hozzáférhetünk a telefonon tárolt zenékhez és képekhez. hogy a kamera váltása megtörtént. A mentés helye a CaptureImageAvailable eseménykezelő. 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. 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. ezt cseréljük most ki az alábbiaknak megfelelően: 160 . hogy a kapott képpel kezdjünk is valamit.Framework szerelvény része. Kép készítésekor a gomb egy időre inaktívvá válik. ahol korábban már egy // TODO: mentés megírása sort hagytunk.6. 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.Frameword dll! MediaLibrary library = new MediaLibrary(). A mentés akkor történjen. amiből tudhatjuk. 6-18 ábra: Értesítés a feldolgozás befejeződéséről Már csak annyi maradt hátra.Xna. 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. Ehhez egy MediaLibrary példányra lesz szükségünk. amikor a kép már elkészült. így a MediaLibrary típusú library objektumot a CameraViewModel osztályban deklaráljuk: // Microsoft.

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

9. Kommunikáció szerverrel 9-13 ábra: Az Access Control a Windows Azure portálon Az Access Control webes interfészének bal oldalán kattintsunk a Management service elemre. Kattintsunk a Password elemre. 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. és másoljuk ki az ott megjelenített értéket (9-14 ábra)! 9-14 ábra: Access Control szolgáltatásunk menedzsment-jelszava 242 .

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful