Académique Documents
Professionnel Documents
Culture Documents
Creez Des Applications en C# Pour Windows Phone-8
Creez Des Applications en C# Pour Windows Phone-8
Julien Chichignoud
ISBN : 979-10-90085-73-2
Maurice Chavelli
ISBN : 979-10-90085-62-6
Quallez-vous apprendre ?
Les bases dActionscript
Guillaume Chau
Guillaume Lapayre
Programmez en ACTIONSCRIPT 3
Vous avez toujours voulu raliser des animations Flash sans jamais vraiment savoir comment
faire ? Ce livre est fait pour vous ! Conu pour les dbutants, il vous apprendra pas pas
Actionscript 3, le langage de programmation de Flash.
PROGRAMMEZ EN
Guillaume Chau
Etudiant ingnieur, passionn par les nouvelles technologies et le Web, il a
remport le premier prix de InnovGame 2011, grce un jeu de stratgie
ralis laide de Actionscript 3.0 et du Flex SDK.
Mathieu Nebra
ISBN : 979-10-90085-59-6
Guillaume Lapayre
Diplm dune cole dingnieurs gnralistes et dun master en acoustique
et vibrations, Guillaume Lapayre est toujours en qute de connaissances
dans de nouveaux domaines. Cest ainsi quaprs avoir fait ses premiers pas
avec divers langages tels que le C, le C++, le Java ou lActionscript, il dcide
de partager ses connaissances sur OpenClassrooms.
Lesprit dOpenClassrooms
ACTIONSCRIPT 3
propos de lauteur
ACTIONSCRIPT 3
Guillaume Chau et Guillaume Lapayre
ISBN : 979-10-90085-55-8
32
9 791090 085558
Vous souhaitez structurer les donnes manipules ou changes par vos programmes ou vos
applications mobiles ? Ce livre est fait pour vous! Conu pour les dbutants, il vous apprendra
pas pas matriser le XML.
Quallez-vous apprendre ?
Ludovic Roland
Apprenez programmer en
ADA
XML
LAPI DOM
LAPI XPath
Les espaces de noms
La mise en forme avec CSS
Ludovic Roland
propos de lauteur
Programmez en
ACTIONSCRIPT 3
Vincent Jarc
ISBN : 979-10-90085-58-9
DevenezPremium!
ISBN : 979-10-90085-56-5
27
9 791090 085565
XML
Ludovic Roland
Dveloppeur Android et Windows Phone, Ludovic voit le XML comme un
moyen efficace de structurer les donnes changer entre un serveur et les
nouveaux appareils que sont les smartphones et tablettes. Il dcide alors
de partager ses connaissances en rdigeant un cours sur OpenClassrooms.
Lesprit dOpenClassrooms
Des cours clairs et ludiques, conus pour tous
Une communaut de professionnels et de passionns prts vous aider sur nos forums
Des ressources disponibles partout, tout le temps : sur le web, en PDF, en eBook
Ludovic Roland
ISBN : 979-10-90085-56-5
Rejoignez la communaut
OpenClassrooms :
www.openclassrooms.com
www.facebook.com/openclassrooms
@OpenClassrooms
Devenez Premium
Tlchargez
les eBooks
Accdez
aux certifications
Tlchargez
les vidos en HD
www.openclassrooms.com/premium
WINDOWS PHONE 8
Nicolas Hilaire
Sauf mention contraire, le contenu de cet ouvrage est publi sous la licence : Creative Commons
BY-NC-SA 2.0 La copie de cet ouvrage est autorise sous rserve du respect des conditions de la licence
Texte complet de la licence disponible sur : http : //creativecommons.org/licenses/by-nc-sa/2.0/fr/
Mentions lgales
Conception couverture : Sophie Bai
Illustrations chapitres : Fan Jiyong, Alexandra Persil et Sophie Bai
OpenClassrooms 2014 - ISBN : 979-10-90085-63-3
Avant-propos
a rvolution de la mobilit est en marche. Nous connaissons tous liPhone qui
a su conqurir un grand nombre dutilisateurs, ainsi que les tlphones Android
dont le nombre ne cesse de crotre. . . Ces tlphones intelligents (ou smartphones)
deviennent omniprsents dans nos usages quotidiens. Microsoft se devait de monter dans
le TGV de la mobilit ! Sont donc apparus, peu aprs ses deux grands concurrents,
les tlphones Windows. Avec un peu plus de retard sur eux, Microsoft attaque ce
march avec plus de maturit quApple, qui a fonc en tant que pionnier, et nous
propose son systme dexploitation : Windows Phone. Cest une bonne nouvelle !
Cest aujourdhui un nouveau march avec plein dapplications potentielles raliser
grce vos talents de dveloppeur. Vous souhaitez raliser des applications mobiles
pour Windows Phone 8 avec le langage C# ? Ce livre est fait pour vous ! Conu pour
les dbutants, il vous apprendra pas pas tout ce quil faut pour vous lancer dans
le dveloppement XAML/C# pour Windows Phone 8. Sachez que vous pouvez suivre
beaucoup de chapitres de ce cours sans possder forcment de Windows Phone, ce
qui est idal lorsque lon souhaite simplement dcouvrir le sujet. Le seul prrequis
sera de matriser un tant soit peu le C#. Pour ceux qui auraient besoin dune piqre
de rappel, vous pouvez consulter mon cours C# sur le site OpenClassrooms - http:
//fr.openclassrooms.com/informatique/cours/apprenez-a-developper-en-c.
CHAPITRE 0. AVANT-PROPOS
XAML, lment indispensable pour pouvoir dvelopper pour Windows Phone. Il
sagit du langage permettant de raliser la partie graphique de nos applications.
2. Un mobile orient donnes : une application, cest avant tout de la mise en
forme de donnes. Nous allons voir comment manipuler ces donnes dans cette
partie et nous allons apprendre bien architecturer nos applications.
3. Une bibliothque de contrles :en plus du XAML, vous avez accs plein
de contrles ddis aux Windows Phone. De la carte du monde, au panorama,
en passant par le navigateur web, vous dcouvrirez des contrles optimiss pour
enrichir vos applications.
4. Un tlphone ouvert vers lextrieur : dans cette partie, vous verrez comment faire pour interagir avec votre smartphone grce ses diffrents capteurs
ou des gestes. Le GPS et lacclromtre nauront plus de secrets pour vous
mais vous verrez galement comment envoyer des notifications ou communiquer
avec Facebook.
Avant de commencer, je dois quand mme vous signaler que le dveloppement pour
Windows Phone peut rendre accroc ! Vous allez avoir envie de crer des applications
sans jamais vous arrter ! Si vous tes prts assumer cette probable dpendance, cest
que vous tes bons pour continuer. Alors, cest parti !
Remerciements
Je souhaite remercier un certain nombre de personnes qui, de prs ou de loin, ont
contribu la naissance de cet ouvrage :
ma femme Delphine, qui me soutient au quotidien et moffre chaque jour une
raison davancer dans la vie ses cts et mon fils Timo, mme sil ntait
encore quun rve lors de la rdaction de cet ouvrage,
ii
REMERCIEMENTS
Anna, Jonathan, Jessica, Marine, Mathieu, Pierre, et toute lquipe dOpenClassrooms,
tous les relecteurs et particulirement Rudy Huyn, qui ma donn dexcellents
conseils.
iii
CHAPITRE 0. AVANT-PROPOS
iv
Avant-propos
ii
ii
ii
Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ii
Windows Phone 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Lesprit Modern UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Prrequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
11
Lmulateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
22
25
30
Linterface en XAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
Le code-behind en C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
Le contrle Grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
Le contrle StackPanel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
Le contrle TextBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
Le contrle TextBlock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
Les vnements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
42
Le bouton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
44
45
4 Les contrles
47
48
49
52
5 Le clavier virtuel
55
56
56
57
61
StackPanel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
62
ScrollViewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
Grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
67
Canvas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
Alignement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72
Marges et espacement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
7 Ajouter du style
vi
29
77
78
Les ressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
80
Les styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
84
Les thmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
88
92
95
96
Correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
96
101
Dessin 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Pinceaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Les transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
10 Crer des animations
113
II
129
131
155
161
. . . . . . . . . . . . . . . . . . . . . . . . . . 162
165
Le .XAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
Affichage dimages en ressources . . . . . . . . . . . . . . . . . . . . . . . . . 167
vii
169
181
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
. . . . . . . . . . . . . . . . . . . . . . . . . . 201
211
247
263
III
20 Panorama et Pivot
289
291
Panorama . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
Pivot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300
21 Navigateur web
307
321
341
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
361
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
367
381
405
429
IV
29 La gestuelle
447
449
455
467
481
489
499
517
531
541
557
569
593
xii
Premire partie
Chapitre
WINDOWS PHONE 8
applications trop lentes. Lcran doit tre multipoint dau moins 3.5 pouces, cest-dire quil doit pouvoir ragir plusieurs pressions simultanes et permettant une
rsolution de 480x800. Les tlphones doivent galement tre munis obligatoirement de quelques quipements, comme le fait davoir un GPS, davoir une camra,
un acclromtre, etc . . . Chaque tlphone possdera galement trois boutons faisant
partie intgrante de son chssis. Le premier bouton permettra de revenir en arrire, le
second daccder au menu et le dernier de faire des recherches.
Windows Phone 8
Cest tout dernirement, avec la sortie de Windows 8, que le systme dexploitation
Windows Phone a chang de version pour passer galement la version 8. Lobjectif
de Microsoft est dunifier au maximum le cur de Windows 8 et de Windows Phone 8,
permettant de faire facilement des passerelles entre eux. Windows 8 tant un systme
dexploitation cr avant tout pour des tablettes, il paraissait logique que Windows 8 et
Windows Phone 8 partagent beaucoup de fonctionnalits. Windows 8 sest largement
inspir de Windows Phone pour crer son style, Modern UI, et cest dsormais au tour
de Windows Phone de subir une volution majeure Windows Phone 8, prsent dans
la figure 1.3 afin de se rapprocher de son grand frre, Windows 8.
Beaucoup de choses sont partages entre les deux systmes, cest ce quon appelle le
Shared Windows Core . Ainsi, il deviendra trs facile de crer des applications pour
Windows Phone 8 qui ne ncessiteront que trs peu dadaptation pour fonctionner sur
Windows 8. Cest une des grandes forces de Windows Phone 8.
Notez que les applications Windows Phone 7 fonctionnent galement sur Windows Phone 8, cest une bonne chose si vous possdiez dj des applications
Windows Phone 7 et que celles-ci nont pas t portes pour WP8.
5
Lesprit Modern UI
Anciennement appel Mtro , Modern UI est le nom donn par Microsoft son
langage de design. Plutt que dadapter linterface des anciens Windows Mobile, pour
Windows Phone 7 il a t dcid de repartir sur un tout nouveau design.
Le nom Mtro a t inspir par les affichages qui se trouvent effectivement dans les
stations de mtro et qui guident efficacement les voyageurs jusqu leurs destinations.
Les affichages sont clairs, prcis, souvent minimalistes et sans fioritures, par exemple
une flche et un gros 5 pour indiquer que cest par l quon va trouver le mtro numro
5. . . Voil quoi doivent ressembler les interfaces pour Windows Phone. Elles doivent
valoriser linformation et la fluidit plutt que les interfaces lourdes et charges. Le but
est de faire en sorte que lutilisateur trouve le plus rapidement possible linformation
dont il a besoin et dviter les images ou animations superflues qui pourraient le ralentir.
Dans cette optique, les applications doivent tre fluides et rpondre rapidement aux
actions de lutilisateur, ou du moins lui indiquer que son action a t prise en compte.
Ras le bol des applications Windows ou autre o on ne sait mme plus si on a cliqu
sur un bouton car rien ne se passe !
Courant 2012, Mtro a chang de nom pour devenir Modern UI. Les applications Windows 8 et Windows Phone 8 doivent chacune suivre les normes
dictes par les principes de Modern UI .
6
LESPRIT MODERN UI
Modern UI se veut donc simple, pur et moderne. Les fonctionnalits sont spares en
Hubs qui sont des espaces regroupant des informations de plusieurs sources de donnes.
Ainsi, il existe plusieurs Hubs (voir figure 1.4), comme le Hub contacts o lon
retrouvera les contacts du tlphone mais aussi les contacts Facebook, Twitter, . . . Nous
avons aussi le Hub Photos , Musique et vidos , Jeux , Microsoft Office ,
Windows Phone Store ou encore le hub Entreprise qui permettra daccder aux
applications mtiers via un portail que les entreprises peuvent personnaliser.
Figure 1.4 Ecran daccueil de lmulateur o lon voit laccs aux Hubs et aux
applications
Une fois rentr dans un Hub, nous avons accs plusieurs informations disposes sous
la forme dun panorama. Nous verrons un peu plus loin ce quest le panorama mais
je peux dj vous dire quil permet dafficher des crans de manire cyclique avec un
dfilement latral. Ainsi, dans le Hub de contact, on arrive dans un premier temps sur
la liste de tous les contacts. Lcran de panorama que lon peut faire glisser avec le
doigt nous permet dobtenir sur lcran suivant la liste des dernires activits de nos
contacts, puis la liste des contacts rcents, etc. Et cest pareil pour les autres Hub, le
but est davoir un point dentre qui centralise toutes les informations relatives un
point dintrt.
Cest avec tous ces principes en tte que vous devrez dvelopper votre application.
Nhsitez pas observer comment sont faites les autres, on trouve souvent de bonnes
sources dinspirations permettant de voir ce qui fait la qualit du design dune appli7
En rsum
Windows Phone est le nouveau systme dexploitation de Microsoft pour Smartphone.
Il arrive avec une nouvelle philosophie de design des applications : Modern UI.
Les applications ralises sont tlchargeables via le magasin en ligne (store) de
Microsoft.
Chapitre
Prrequis
Avant toute chose, je vais vous donner les lments qui vont vous permettre de choisir
entre lenvironnement de dveloppement ddi au dveloppement dapplications pour
Windows Phone 7.5 et celui ddi au dveloppement dapplications pour Windows
Phone 7.5 et 8.
Pourquoi choisir entre un environnement qui fait tout et un environnement
qui ne fait que la moiti des choses ?
Bonne question. . . ! En effet, qui peut le plus peut bien sr le moins. Mais bien que
les environnements de dveloppement soient gratuits, vous nallez peut-tre pas avoir
envie de changer de machine de dveloppement pour autant.
Voici le matriel requis pour dvelopper pour Windows Phone 7.5 :
La premire chose est de possder Windows Vista SP2, ou bien Windows 7 ou encore Windows 8, qui sont les seules configurations supportes
permettant de dvelopper pour Windows Phone 7.5.
Il est galement grandement conseill de possder une carte graphique compatible avec DirectX 10 afin de pouvoir utiliser correctement lmulateur. Je
reviendrai plus tard sur ce quest lmulateur.
La plupart des PC est aujourdhui quipe de cette configuration. Ce qui est trs
pratique pour se lancer et dcouvrir le dveloppement pour Windows Phone. Par contre,
pour pouvoir dvelopper pour Windows Phone 8, cest un peu plus dlicat :
Il vous faut avant tout Windows 8 en version 64 bits, rien dautre. La version conseille est dailleurs la version PRO ou la version Entreprise qui vont
permettre dutiliser lmulateur.
Pour faire tourner lmulateur, il faut que votre processeur supporte la technologie SLAT (qui permet de faire de la virtualisation) et quelle soit active dans le bios ; ce qui est le cas gnralement des PC rcent ( partir de 2011). Il faut galement installer le systme de virtualisation de Microsoft, Hyper-V - http://fr.wikipedia.org/wiki/Hyper-V, qui est disponible avec les versions PRO ou Entreprise de Windows 8. Si vous ntes pas
certain que votre processeur supporte cette technologie, vous pouvez le vrifier avec cette procdure - http://msdn.microsoft.com/fr-fr/library/
windowsphone/develop/ff626524(v=vs.105).aspx (en anglais) ou alors,
tentez linstallation et il vous dira une fois que tout est fini sil y a un problme ou pas.
Il vous faut aussi une bonne une carte graphique compatible avec DirectX
10 ainsi que 4 Go de mmoire.
Ces contraintes matrielles peuvent rendre difficile daccs le dveloppement pour Windows Phone 8 quelquun qui souhaite simplement sinitier ou dcouvrir cette technologie. Si cest votre cas et que vous ne possdez pas ce matriel, alors je vous conseille
dinstaller lenvironnement de dveloppement pour Windows Phone 7.5, qui vous per10
Pour rsumer ce quest le C#, il sagit dun langage orient objet apparu en mme
temps que le framework .NET qui na cess dvoluer depuis 2001. Il permet dutiliser les briques du framework .NET pour raliser des applications de toutes sortes et
notamment des applications pour Windows Phone. Cest le ciment et les outils qui
permettent dassembler les briques de nos applications.
15
16
Figure 2.10 Modle de projet pour crer une application Windows Phone
18
Figure 2.12 Linterface de Visual Studio, ainsi que la liste droulante permettant de
choisir lmulateur
Nous allons revenir sur cet cran trs bientt. Ce quil est important de remarquer
cest que si nous dmarrons lapplication telle quelle, elle va se compiler et sexcuter
dans lmulateur Windows Phone. Vous le voyez dans le petit encadr en haut de Visual
Studio, cest la cible du dploiement. Il est possible de dployer soit sur lmulateur, soit
directement sur un tlphone reli au poste de travail. Il ne reste plus qu rellement
excuter notre application. . .
19
Lmulateur
Attention, si vous avez install le SDK 8.0, vous allez avoir besoin galement dinstaller
le logiciel gestion de la virtualisation : Hyper-v. Celui-ci nest disponible quavec les
versions PRO ou Entreprise de Windows 8 et uniquement si votre processeur supporte
la technologie SLAT. Allez dans le panneau de configuration, programmes, et choisissez
dactiver des fonctionnalits Windows (voir la figure 2.13).
LMULATEUR
23
La balise <prenom> est ce quon appelle une balise ouvrante, cela signifie que ce qui se
trouve aprs (en loccurrence la chane Nicolas ) fait partie de cette balise jusqu
ce que lon rencontre la balise fermante </prenom> qui est comme la balise ouvrante
lexception du / prcdant le nom de la balise. Le XML est un fichier facile lire par
nous autres humains. On en dduit assez facilement que le fichier contient la chane
Nicolas et quil sagit smantiquement dun prnom. Une balise peut contenir des
attributs permettant de donner des informations sur la donne. Les attributs sont
entours de guillemets et et font partis de la balise. Par exemple :
1
< client nom = " Nicolas " age = " 30 " > </ client >
Ici, la balise client possde un attribut nom ayant la valeur Nicolas et un attribut
age ayant la valeur 30 . Encore une fois, cest trs facile lire pour un humain.
Il est possible que la balise nait pas de valeur, comme cest le cas dans lexemple cidessus. On peut dans ce cas-l remplacer la balise ouvrante et la balise fermante par
cet quivalent :
1
< client nom = " Nicolas " age = " 30 " / >
Enfin, et nous allons terminer notre aperu rapide du XML avec un dernier point. Il
est important de noter que le XML peut imbriquer ses balises et quil ne peut possder
quun seul lment racine, ce qui nous permet davoir une hirarchie de donnes. Par
exemple nous pourrons avoir :
1
2
3
4
5
6
7
8
9
10
On voit tout de suite que le fichier dcrit une liste de deux clients. Nous en avons un
qui est un particulier, qui sappelle Nicolas et qui a 30 ans alors que lautre est un
professionnel, prnomm Jrmie et qui a 40 ans.
quoi cela nous sert-il ? comprendre ce fameux fichier de droite. Cest le fichier
XAML (prononcez Zammel ). Le XAML est un langage qui permet de dcrire des
interfaces et en loccurrence ici le code XAML ( droite dans Visual Studio) dcrit
linterface que nous retrouvons au milieu. Cette zone est la prvisualisation du rendu
du code crit dans la partie droite. On appelle la zone du milieu, le concepteur (ou
plus souvent le designer en anglais). En fait, le fichier XAML contient des balises qui
dcrivent ce qui doit safficher sur lcran du tlphone. Nous allons y revenir.
Nous allons donc devoir apprendre un nouveau langage pour pouvoir crer des applications sur Windows Phone : le XAML. Ne vous inquitez pas, il est assez facile
24
En rsum
Pour dvelopper pour Windows Phone, nous avons besoin de Visual Studio et
du kit de dveloppement pour Windows Phone.
Il existe une version totalement gratuite de Visual Studio permettant de raliser
des applications sous Windows Phone.
Un mulateur accompagne Visual Studio pour tester ses applications en mode
dveloppement.
Blend est loutil de design permettant de styler son application, dont une version
gratuite est fournie avec le kit de dveloppement pour Windows Phone.
27
28
Chapitre
29
Hello World
Revenons donc sur notre cran o nous avons le designer et le XAML. Positionnonsnous sur le code XAML et ajoutons des lments sans trop comprendre ce que nous
allons faire afin de raliser notre Hello World . Nous reviendrons ensuite sur ce que
nous avons fait pour expliquer le tout en dtail.
Pour commencer, on va modifier la ligne suivante :
1
< TextBlock Text = " nom de la page " Margin = "9 , -7 ,0 , 0 " Style = " {
StaticResource PhoneTextTitle1Style } " / >
et crire ceci :
1
< TextBlock Text = " Hello World " Margin = "9 , -7 ,0 , 0 " Style = " {
StaticResource PhoneTextTitle1Style } " / >
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Button Content = " Valider " Tap = " Button_Tap_1 " / >
30
HELLO WORLD
31
3
4
Nous pouvons ds prsent dmarrer notre application en appuyant sur F5 . Lmulateur se lance et nous voyons apparatre les nouvelles informations sur lcran (voir la
figure 3.3).
La souris va ici permettre de simuler le toucher avec le doigt lorsque nous cliquons.
Cliquons donc dans la zone de texte et nous voyons apparatre un clavier virtuel
lintrieur de notre application (voir la figure 3.4).
Ce clavier virtuel sappelle le SIP (pour Soft Input Panel ) et apparait automatiquement quand on en a besoin, notamment dans les zones de saisie, nous y reviendrons.
Saisissons une valeur dans la zone de texte et cliquons sur le bouton Valider. Nous
voyons apparatre le rsultat en rouge avec un magnifique message construit (voir la
figure 3.5).
Et voil, notre Hello World est termin ! Chouette non ? Pour quitter lapplication, le
plus simple est darrter le dbogueur de Visual Studio en cliquant sur le carr Stop.
32
HELLO WORLD
Linterface en XAML
Alors, taper des choses sans rien comprendre, a va un moment. . . mais l, il est temps
de savoir ce que nous avons fait !
Nous avons dans un premier temps fait des choses dans le XAML. Pour rappel, le
XAML sert dcrire le contenu de ce que nous allons voir lcran. En fait, un fichier
XAML correspond une page. Une application peut tre dcoupe en plusieurs pages,
nous y reviendrons plus tard. Ce que nous avons vu sur lmulateur est laffichage de
la page MainPage.
Donc, nous avons utilis le XAML pour dcrire le contenu de la page. Il est globalement
assez explicite mais ce quil faut comprendre cest que nous avons ajout des contrles
du framework .NET dans la page. Un contrle est une classe C# complte qui sait
safficher, se positionner, traiter des vnements de lutilisateur (comme le clic sur le
bouton), etc. Ces contrles ont des proprits et peuvent tre ajouts dans le XAML.
Par exemple, prenons la ligne suivante :
1
< TextBlock Text = " Saisir votre nom " HorizontalAlignment = " Center "
/>
34
LINTERFACE EN XAML
xmlns = " http :// schemas . microsoft . com / winfx / 2006 / xaml /
presentation "
xmlns : x = " http :// schemas . microsoft . com / winfx / 2006 / xaml "
xmlns : phone = " clr - namespace : Microsoft . Phone . Controls ;
assembly = Microsoft . Phone "
xmlns : shell = " clr - namespace : Microsoft . Phone . Shell ; assembly =
Microsoft . Phone "
xmlns : d = " http :// schemas . microsoft . com / expression / blend / 2008
"
xmlns : mc = " http :// schemas . openxmlformats . org / markup compatibility / 2006 "
FontFamily = " { StaticResource Ph oneFo ntFami lyNor mal } "
FontSize = " { StaticResource PhoneFontSizeNormal } "
Foreground = " { StaticResource PhoneForegroundBrush } "
S u p p o r t e d Orient ation s = " Portrait " Orientation = " Portrait "
mc : Ignorable = " d " d : DesignHeight = " 768 " d : DesignWidth = " 480 "
shell : SystemTray . IsVisible = " True " >
3
4
5
6
7
8
9
10
11
12
13
14
Cest dailleurs le conteneur de base du fichier XAML, celui qui contient tous les autres
contrles. La page est en fait reprsente par la classe PhoneApplicationPage qui
est aussi un objet du framework .NET. Plus prcisment, notre page est une classe
gnre qui drive de lobjet PhoneApplicationPage. Il sagit de la class MainPage
situe dans lespace de nom HelloWorld, cest ce que lon voit dans la proprit :
1
On peut sen rendre compte galement dans le code behind de la page o Visual Studio
a gnr une classe partielle du mme nom que le fichier XAML et qui drive de
PhoneApplicationPage :
1
2
3
4
5
6
7
8
9
10
11
12
13
Pourquoi partielle ? Parce quil existe un autre fichier dans votre projet. Ce fichier est
cach mais on peut lafficher en cliquant sur le bouton en haut de lexplorateur de
solution (voir la figure 3.6).
Et nous pouvons voir notamment un rpertoire obj contenant un rpertoire debug
contenant le fichier MainPage.g.i.cs. Si vous louvrez, vous pouvez trouver le code
35
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
36
LE CODE-BEHIND EN C#
23
24
25
26
27
28
29
Il sagit dune classe qui est gnre lorsquon modifie le fichier XAML. Ne modifiez
pas ce fichier car il sera re-gnr tout le temps. On peut voir quil sagit dune classe
MainPage, du mme nom que la proprit x:Class de tout lheure, qui soccupe de
charger le fichier XAML et qui cre des variables partir des contrles quil trouvera
dedans. Nous voyons notamment quil a cr les deux variables suivantes :
1
2
Le nom de ces variables correspond aux proprits x:Name des deux contrles que nous
avons cr :
1
2
Ces variables sont initialises aprs quil ait charg tout le XAML en faisant une recherche partir du nom du contrle. Cela veut dire que nous disposons dune variable
qui permet daccder au contrle de la page, par exemple la variable Nom du type
TextBox. Je vais y revenir. Nous avons donc :
Un fichier MainPage.xaml qui contient la description des contrles
Un fichier gnr qui contient une classe partielle qui drive de
PhoneApplicationPage et qui charge ce XAML et qui rend accessible nos
contrles via des variables
Un fichier de code behind qui contient la mme classe partielle o nous pourrons
crire la logique de notre code
Remarquez quil existe galement le fichier MainPage.g.cs qui correspond au fichier
gnr aprs la compilation. Nous ne nous occuperons plus de ces fichiers gnrs, ils ne
servent plus rien. Nous les avons regards pour comprendre comment cela fonctionne.
Le code-behind en C#
Revenons sur le code behind, donc sur le fichier MainPage.xaml.cs, nous avons :
1
37
3
4
5
6
7
// Constructeur
public MainPage ()
{
I nitializeComponent () ;
}
8
9
10
11
12
13
On retrouve bien notre classe partielle qui hrite des fonctionnalits de la classe
PhoneApplicationPage. Regardez lintrieur de la mthode Button_Tap_1, nous
utilisons les fameuses variables que nous navons pas dclar nous-mme mais qui ont
t gnres. . . Ce sont ces variables qui nous permettent de manipuler nos contrles
et en loccurrence ici, qui nous permettent de modifier la valeur de la zone de texte
non modifiable en concatnant la chane Bonjour la valeur de la zone de texte
modifiable, accessible via sa proprit Text.
Vous aurez compris ici que ce sont les proprits Text des TextBlock et TextBox qui
nous permettent daccder au contenu qui est affich sur la page. Il existe plein dautres
proprits pour ces contrles comme la proprit Foreground qui permet de modifier
la couleur du contrle, sauf quici nous lavions positionn grce au XAML :
1
< TextBlock x : Name = " Resultat " Foreground = " Red " / >
Sachez quand mme que dune manire gnrale, on aura tendance essayer de mettre
le plus de chose possible dans le XAML plutt que dans le code behind. La proprit
Foreground ici a tout intrt tre dclare dans le XAML.
Le contrle Grid
Je vais y revenir plus loin un peu plus loin, mais pour que vous ne soyez pas compltement perdu dans notre Hello World, il faut savoir que la Grid est un conteneur.
38
LE CONTRLE STACKPANEL
<mode bilingue = on>Vous aurez compris que la Grid est en fait une
grille. . .<mode bilingue = off >
Aprs cet effort de traduction intense, nous pouvons dire que la grille sert contenir
et agencer dautres contrles. Dans notre cas, le code suivant :
1
2
3
4
5
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
9
10
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock Text = " MON APPLICATION " Style = " {
StaticResource PhoneTextNormalStyle } " Margin = " 12 , 0 "
/>
< TextBlock Text = " Hello World " Margin = "9 , -7 ,0 , 0 " Style = "
{ StaticResource PhoneTextTitle1Style } " / >
</ StackPanel >
11
12
13
14
15
16
17
18
19
20
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< StackPanel >
< TextBlock Text = " Saisir votre nom "
HorizontalAlignment = " Center " / >
< TextBox x : Name = " Nom " / >
< Button Content = " Valider " Tap = " Button_Tap_1 " / >
< TextBlock x : Name = " Resultat " Foreground = " Red " / >
</ StackPanel >
</ Grid >
</ Grid >
Dfini une grille qui contient deux lignes. La premire contient un contrle StackPanel,
nous allons en parler juste aprs. La seconde ligne contient une nouvelle grille sans ligne
ni colonne, qui est galement compose dun StackPanel. Nous aurons loccasion den
parler plus longuement plus tard donc je marrte l pour linstant sur la grille.
Le contrle StackPanel
Ici cest pareil, le contrle StackPanel est galement un conteneur. Je vais y revenir un
peu plus loin galement mais il permet ici daligner les contrles les uns en dessous des
autres. Par exemple, celui que nous avons rajout contient un TextBlock, un TextBox,
un bouton et un autre TextBlock :
1
2
39
Nous pouvons voir sur le designer que les contrles sont bien les uns en dessous des
autres. Nous avons donc au final, la page qui contient une grille, qui contient un
StackPanel et une grille qui contiennent chacun des contrles.
Le contrle TextBox
Le contrle TextBox est une zone de texte modifiable. Nous lavons utilise pour saisir
le prnom de lutilisateur. On dclare ce contrle ainsi :
1
Lorsque nous cliquons dans la zone de texte, le clavier virtuel apparait et nous offre
la possibilit de saisir une valeur. Nous verrons un peu plus loin quil est possible de
changer le type du clavier virtuel. La valeur saisie est rcupre via la proprit Text
du contrle, par exemple ici je rcupre la valeur saisie que je concatne la chane
Bonjour et que je stocke dans la variable resultat :
1
Inversement, je peux pr-remplir la zone de texte avec une valeur en utilisant la proprit Text, par exemple depuis le XAML :
1
2
3
4
5
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< StackPanel >
< TextBox x : Name = " Nom " Text = " Nicolas " / >
</ StackPanel >
</ Grid >
LE CONTRLE TEXTBLOCK
Le contrle TextBlock
Le contrle TextBlock reprsente une zone de texte non modifiable. Nous lavons utilis
pour afficher le rsultat de notre Hello World. Il suffit dutiliser sa proprit Text pour
afficher un texte. Par exemple, le XAML suivant :
1
Comme nous lavons dj fait, il est possible de modifier la valeur dun TextBlock en
passant par le code-behind :
1
41
Les vnements
Il sagit des vnements sur les contrles. Chaque contrle est capable de lever une srie
dvnements lorsque cela est opportun. Cest le cas par exemple du contrle bouton qui
est capable de lever un vnement lorsque nous tapotons dessus (ou que nous cliquons
avec la souris). Nous lavons vu dans lexemple du Hello World, il suffit de dclarer une
mthode que lon associe lvnement, par exemple :
1
< Button Content = " Valider " Tap = " Button_Tap_1 " / >
qui permet de faire en sorte que la mthode Button_Tap_1 soit appele lors du clic sur
le bouton. Rappelez-vous, dans notre Hello World, nous avions la mthode suivante :
1
2
3
4
< Button x : Name = " UnBouton " Content = " Cliquez - moi " / >
LES VNEMENTS
1
2
3
4
5
6
7
9
10
11
12
13
14
< CheckBox Content = " Cochez - moi " Checked = " CheckBox_Checked_1 " / >
Avec la mthode :
1
2
3
4
Il existe normment dvnement sur les contrles, mais aussi sur la page, citons encore
par exemple lvnement qui permet dtre notifi lors de la fin du chargement de la
page :
1
2
3
4
5
public MainPage ()
{
I ni t i al i zeComponent () ;
Loaded += MainPage_Loaded ;
}
6
7
8
9
10
Nous aurons loccasion de voir beaucoup dautres vnements tout au long de ce cours.
Remarquez que les vnements sont toujours construits de la mme faon. Le premier
paramtre est du type object et reprsente le contrle qui a dclench lvnement.
En loccurrence, dans lexemple suivant :
1
< Button Content = " Valider " Tap = " Button_Tap_1 " / >
Le second paramtre est, quant lui, spcifique au type dvnement et peut fournir
des informations complmentaires.
Le bouton
Revenons prsent rapidement sur le bouton, nous lavons vu il nest pas trs compliqu
utiliser. On utilise la proprit Content pour mettre du texte et il est capable de lever
un vnement lorsquon clique dessus, grce lvnement Tap. Le bouton possde
galement un vnement Click qui fait la mme chose et qui existe encore pour des
raisons de compatibilit avec Silverlight.
Prfrez cependant lvnement Tap qui est plus performant.
Il est galement possible de passer des paramtres un bouton. Pour un bouton tout
seul, ce nest pas toujours utile, mais dans certaines situations cela peut tre primordial.
Dans lexemple qui suit, jutilise deux boutons qui ont la mme mthode pour traiter
lvnement de clic sur le bouton :
1
2
3
4
5
Cest la proprit CommandParameter qui me permet de passer un paramtre. Je pourrais ensuite lutiliser dans mon code behind :
1
2
3
4
5
6
En rsum
Le XAML permet de dcrire linterface de nos pages.
Le code behind permet dcrire le code C# de la logique de nos pages.
On utilise des contrles dans nos interfaces, comme le bouton ou la zone de
texte.
Les contrles sont des classes compltes qui savent safficher, se positionner ou
ragir des vnements utilisateurs, comme le clic sur un bouton.
46
Chapitre
Les contrles
Difficult :
Jusqu prsent nous avons vu peu de contrles, la zone de texte non modifiable, la zone de
saisie modifiable, le bouton. . . Il existe beaucoup de contrles disponibles dans les bibliothques de contrles XAML pour Windows Phone. Ceux-ci sont facilement visibles grce
la boite outils que lon retrouve gauche de lcran.
Voyons un peu ce quil y a autour de ces fameux contrles.
47
48
< CheckBox Content = " CheckBox " HorizontalAlignment = " Left " Margin =
" 168 , 167 ,0 , 0 " VerticalAlignment = " Top " / >
< Canvas H o ri z ontalAlignment = " Left " Height = " 100 " Margin = " 102 , 125
,0 , 0 " Ve rticalAlignment = " Top " Width = " 100 " >
49
50
2
3
< CheckBox Content = " CheckBox " Canvas . Left = " 56 " Canvas . Top = "
40 " / >
</ Canvas >
Figure 4.4 Modification des proprits dun contrle partir de la fentre des proprits
< ToggleButton Content = " ToggleButton " HorizontalAlignment = " Left "
Margin = " 111 , 169 ,0 , 0 " VerticalAlignment = " Top " Background = " #
FFF71616 " BorderBrush = " # FF2DC50C " / >
En rsum
Il existe tout une hirarchie des contrles utilisables dans nos pages.
Les contrles sont accessibles depuis la barre doutils de Visual Studio ou dans
expression blend.
52
53
54
Chapitre
Le clavier virtuel
Difficult :
Le clavier virtuel est ce petit clavier qui apparat lorsque lon clique dans une zone de texte
modifiable, que nous avons pu voir dans notre Hello World. En anglais il se nomme le SIP,
pour Soft Input Panel, que lon traduit par clavier virtuel. Nous allons voir comment nous
en servir.
55
Et le code behind :
1
2
3
4
5
6
7
8
9
< TextBox x : Name = " MonTextBox " InputScope = " Number " / >
En rsum
Le clavier virtuel saffiche lorsque lon clique dans une zone de texte modifiable.
Il existe plusieurs types de clavier notre disposition que nous pouvons choisir
grce la proprit InputScope.
58
59
60
Chapitre
61
StackPanel
Le StackPanel par exemple, comme son nom peut le suggrer, permet dempiler les
contrles les uns la suite des autres. Dans lexemple suivant, les contrles sont ajouts
les uns en-dessous des autres :
1
2
3
4
5
STACKPANEL
1
2
3
4
5
< StackPanel Orientation = " Horizontal " Height = " 40 " >
< TextBlock Text = " Bonjour tous " / >
< Button Content = " Cliquez - moi " / >
< Image Source = " http :// open -e - education - 2013 . openclassrooms .
com / img / logos / logo - openclassrooms . png " / >
</ StackPanel >
Ici, jai rajout une hauteur pour le contrle StackPanel, en fixant la proprit Height
40 pixels, ce qui fait que tous les sous-contrles se sont adapts cette hauteur. Nous
aurons donc la figure 6.3.
63
ScrollViewer
Il existe dautres conteneurs, voyons par exemple le ScrollViewer. Il nous sert rendre
accessible des contrles qui pourraient tre masqus par un cran trop petit. Prenons
par exemple ce code XAML :
64
SCROLLVIEWER
1
2
3
4
5
6
7
8
9
10
11
tous
tous
tous
tous
tous
tous
tous
1"
2"
3"
4"
5"
6"
7"
/>
/>
/>
/>
/>
/>
/>
Nous crons 7 contrles TextBlock, contenant une petite phrase, qui doivent se mettre
les uns en-dessous des autres. Vous aurez devin que la proprit Margin permet de
dfinir une marge autour du contrle, jy reviendrai. Si nous regardons le rsultat, nous
pouvons constater quil nous manque un TextBlock (voir la figure 6.5).
Vous vous en doutez, il saffiche trop bas et nous ne pouvons pas le voir sur lcran car
il y a trop de choses. Le ScrollViewer va nous permettre de rsoudre ce problme. Ce
contrle gre une espce de dfilement, comme lorsque nous avons un ascenseur dans
nos pages web. Ce qui fait quil sera possible de naviguer de haut en bas sur notre
mulateur en cliquant sur lcran et en maintenant le clic tout en bougeant la souris
de haut en bas (voir la figure 6.6).
65
GRID
Vous pouvez galement vous amuser faire dfiler le ScrollViewer horizontalement,
mais il vous faudra changer une proprit :
1
2
3
Grid
Parlons prsent du contrle Grid. Cest un contrle trs utilis qui va permettre
de positionner dautres contrles dans une grille. Une grille peut tre dfinie par des
colonnes et des lignes. Il sera alors possible dindiquer dans quelle colonne ou quelle
ligne se positionne un contrle. Par exemple, avec le code suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
67
21
< TextBlock Text = " X " FontSize = " 50 " Grid . Row = " 2 " Grid . Column =
" 2 " HorizontalAlignment = " Center " VerticalAlignment = "
Center " / >
</ Grid >
Je dfinis une grille compose de 3 lignes sur 3 colonnes. Dans chaque case je pose un
TextBlock avec une valeur qui me simule un jeu de morpion. Ce quil est important de
remarquer ici cest que je dfinis le nombre de colonnes grce ColumnDefinition :
1
2
3
4
5
Il y a donc 3 colonnes et 3 lignes. Chaque colonne a une largeur dun tiers de lcran.
Chaque ligne a une hauteur dun tiers de lcran. Je vais y revenir juste aprs. Pour indiquer quun contrle est la ligne 1 de la colonne 2, jutiliserai les proprits Grid.Row
et Grid.Column avec les valeurs 1 et 2. ( noter quon commence numroter partir
de 0, classiquement). Ce qui donnera la figure 6.7.
Pratique non ? Nous pouvons voir aussi que dans la dfinition dune ligne, nous positionnons la proprit Height. Cest ici que nous indiquerons la hauteur de chaque
ligne. Cest la mme chose pour la largeur des colonnes, cela se fait avec la proprit
Width sur chaque ColomnDefinition.
Ainsi, en utilisant ltoile, nous avons dit que nous voulions que le XAML soccupe de
rpartir toute la place disponible. Il y a trois toiles, chaque ligne et colonne a donc
un tiers de la place pour safficher. Dautres valeurs sont possibles. Il est par exemple
possible de forcer la taille une valeur prcise. Par exemple, si je modifie lexemple
prcdent pour avoir :
1
2
3
4
5
6
7
8
9
10
68
GRID
Par contre, les lignes saffichent uniquement dans lmulateur car le designer montre
dj ce que a donne (voir la figure 6.8).
69
< TextBlock Text = " X " FontSize = " 50 " Grid . Row = " 1 " Grid . Column = " 0 "
H or i z ontalAlignment = " Center " VerticalAlignment = " Center " Grid
. ColumnSpan = " 3 " / >
la place de :
1
2
3
< TextBlock Text = " X " FontSize = " 50 " Grid . Row = " 1 " Grid . Column = " 0 "
H or i z ontalAlignment = " Center " VerticalAlignment = " Center " / >
< TextBlock Text = " O " FontSize = " 50 " Grid . Row = " 1 " Grid . Column = " 1 "
H or i z ontalAlignment = " Center " VerticalAlignment = " Center " / >
< TextBlock Text = " X " FontSize = " 50 " Grid . Row = " 1 " Grid . Column = " 2 "
H or i z ontalAlignment = " Center " VerticalAlignment = " Center " / >
CANVAS
Figure 6.9 Une grille avec une case stirant sur 3 colonnes
1
< TextBlock Text = " X " FontSize = " 50 " Grid . Row = " 0 " Grid . Column = " 0 "
/>
Canvas
Nous finirons notre aperu des conteneurs avec le Canvas. Au contraire des autres
conteneurs qui calculent eux mme la position des contrles, ici cest le dveloppeur qui
indique lemplacement dun contrle, de manire relative la position du Canvas. De
plus le Canvas ne calculera pas automatiquement sa hauteur et sa largeur en analysant
ses enfants, contrairement aux autres conteneurs. Ainsi si on met dans un StackPanel
un Canvas suivi dun bouton, le bouton sera affich par-dessus le Canvas, car ce dernier
aura une hauteur de 0 bien quil possde des enfants. Ainsi, lexemple suivant :
1
2
3
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Canvas >
< TextBlock Text = " Je suis en bas gauche " Canvas . Top = "
500 " / >
71
< TextBlock Text = " Je suis en haut droite " Canvas . Left =
" 250 " Canvas . Top = " 10 " / >
</ Canvas >
</ Grid >
Alignement
Lalignement permet de dfinir comment est align un contrle par rapport son
contenant, en gnral un panneau. Il existe plusieurs valeurs pour cette proprit :
Stretch (tir) qui est la valeur par dfaut
Left (gauche)
72
MARGES ET ESPACEMENT
Right (droite)
Center (centre)
Ainsi le code XAML suivant :
1
2
3
4
5
6
7
8
9
10
11
Marges et espacement
Avant de terminer, je vais revenir rapidement sur les marges. Je les ai rapidement
voques tout lheure. Pour mieux les comprendre, regardons cet exemple :
73
Figure 6.12 Ltirement est annul par les proprits Height et Width
74
MARGES ET ESPACEMENT
1
2
3
4
5
6
7
8
< TextBlock Text = " Mon texte " Margin = " 50 " / >
< TextBlock Text = " Mon texte " Margin = " 50 50 50 50 " / >
75
< TextBlock Text = " Mon texte " Margin = " 0 10 270 100 " / >
Figure 6.15 La marge peut tre de taille diffrente en haut, en bas, gauche ou
droite du contrle
Bref, les marges aident positionner le contrle lemplacement voulu, trs utile pour
avoir un peu despace dans un StackPanel. Remarquez que nous avons aperu dans
ces exemples le contrle Rectangle qui permet, vous vous en doutez, de dessiner un
rectangle. Nous ltudierons un peu plus loin.
En rsum
Les conteurs contiennent des contrles et nous sont utiles pour les positionner
sur la page.
Chaque page doit possder un unique conteneur racine.
Les proprits dalignement, de marge et despacement nous permettent daffiner
nos positionnements dans les conteneurs.
76
Chapitre
Ajouter du style
Difficult :
Nous avons vu quon pouvait modifier les couleurs, la taille de lcriture. . . grce la fentre
des proprits dun contrle. Cela modifie les proprits des contrles et affecte leur rendu.
Cest trs bien. Mais imaginons que nous voulions changer les couleurs et lcriture de
plusieurs contrles, il va falloir reproduire ceci sur tous les contrles, ce qui dun coup est
plutt moins bien !
Cest l quintervient le style. Il correspond lidentification de plusieurs proprits par un
nom, que lon peut appliquer facilement plusieurs contrles.
77
< Image x : Name = " MonImage " Source = " / Assets / Images / rond . png " Width
= " 60 " Height = " 60 " / >
noter que cela peut aussi se faire grce au code behind. Pour cela, supprimons la
proprit Source du XAML :
1
< Image x : Name = " MonImage " Width = " 60 " Height = " 60 " / >
78
MonImage . Source = new BitmapImage ( new Uri ( " / Assets / Images / rond .
png " , UriKind . Relative ) ) ;
79
Cela semble moins pratique, mais je vous lai prsent car nous utiliserons cette mthode
un petit peu plus loin. Dune manire gnrale, il sera toujours plus pertinent de passer
par le XAML que par le code !
Il nest pas possible dafficher des images GIF dans ce contrle lorsquon
dveloppe pour Windows Phone 7.5, seuls les formats JPG et PNG sont
supports. Par contre, le GIF est utilisable pour des projets Windows Phone
8 mais ne sanime pas.
Les ressources
Les ressources sont un mcanisme de XAML qui permet de rutiliser facilement des
objets ou des valeurs. Chaque classe qui drive de FrameworkElement dispose dune
proprit Resources, qui est en fait un dictionnaire de ressources. Chaque contrle
peut donc avoir son propre dictionnaire de ressources mais en gnral, on dfinit les
ressources soit au niveau de la page, soit au niveau de lapplication. Par exemple, pour
dfinir une ressource au niveau de la page, nous utiliserons la syntaxe suivante :
1
2
3
4
5
6
7
8
9
10
11
12
80
LES RESSOURCES
3
4
< Button Content = " Cliquez - moi , je suis rouge " Foreground = " {
StaticResource BrushRouge } " / >
</ StackPanel >
Des accolades avec le mot-cl StaticResource. . . Cela signifie qu lexcution de lapplication, le moteur va aller chercher la ressource associe au nom BrushRouge et il va
la mettre dans la proprit Foreground de notre contrle.
On appelle la syntaxe entre accolades une extension de balisage XAML ,
en anglais : extension markup.
Ce moteur commence par chercher la ressource dans les ressources de la page et sil ne
la trouve pas, il ira chercher dans le dictionnaire de ressources de lapplication. Nous
avons positionn notre ressource dans la page, cest donc celle-ci quil utilise en premier.
81
< Application
x : Class = " HelloWorld . App "
xmlns = " http :// schemas . microsoft . com / winfx / 2006 / xaml /
presentation "
xmlns : x = " http :// schemas . microsoft . com / winfx / 2006 / xaml "
xmlns : phone = " clr - namespace : Microsoft . Phone . Controls ;
assembly = Microsoft . Phone "
xmlns : shell = " clr - namespace : Microsoft . Phone . Shell ; assembly =
Microsoft . Phone "
xmlns : system = " clr - namespace : System ; assembly = mscorlib " >
Pourquoi ? Parce que la classe String nest pas connue de lapplication. Il faut lui
indiquer o elle se trouve, en indiquant son espace de nom, un peu comme un using
C#. Pour cela on utilise la syntaxe prcdente pour dire que lespace de nom que jai
nomm system correspondra lespace de nom System de lassembly mscorlib.
Pour utiliser ma classe String, il faudra que je la prfixe de system : .
82
LES RESSOURCES
Bref, revenons notre ressource de type String. Je vais pouvoir lutiliser depuis nimporte quelle page vu quelle est dfinie dans le dictionnaire de ressources de lapplication, par exemple dans ma page principale :
1
Les styles
Le style correspond lidentification de plusieurs proprits par un nom, que lon peut
appliquer facilement plusieurs contrles. Un style trouve donc tout fait naturellement sa place dans les dictionnaires de ressources que nous avons dj vus. Un style
est, comme une ressource, caractris par un nom et cible un type de contrle. Par
exemple, observons le style suivant :
1
2
3
4
5
6
7
8
9
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,0 , 28
">
< TextBlock Text = " MON APPLICATION " Style = " { StaticResource
P h oneTextNormalStyle } " Margin = " 12 , 0 " / >
< TextBlock Text = " Hello World " Margin = "9 , -7 ,0 , 0 " Style = " {
StaticResource PhoneTextTitle1Style } " / >
</ StackPanel >
Vous pouvez dsormais comprendre que ces deux TextBlock utilisent les styles
PhoneTextNormalStyle et PhoneTextTitle1Style. Ce ne sont pas des styles que nous
avons crs. Il sagit de styles systmes, prsents directement dans le systme dexploitation et que nous pouvons utiliser comme bon nous semble.
Le style est un lment qui sera trs souvent utilis dans nos applications. Dfinir le
XAML associ ces styles est un peu rbarbatif. Heureusement, Blend peut nous aider
dans la cration de style. . . Prenons par exemple le code XAML suivant :
84
LES STYLES
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Grid . ColumnDefinitions >
< ColumnDefinition Width = " * " / >
< ColumnDefinition Width = " * " / >
</ Grid . ColumnDefinitions >
< Grid . RowDefinitions >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " auto " / >
</ Grid . RowDefinitions >
< TextBlock Text = " Nom " Grid . Column = " 0 " Grid . Row = " 0 " / >
< TextBox Grid . Row = " 0 " Grid . Column = " 1 " / >
< TextBlock Text = " Pr nom " Grid . Column = " 0 " Grid . Row = " 1 " / >
< TextBox Grid . Row = " 1 " Grid . Column = " 1 " / >
< TextBlock Text = " Age " Grid . Column = " 0 " Grid . Row = " 2 " / >
< TextBox Grid . Row = " 2 " Grid . Column = " 1 " / >
</ Grid >
86
LES STYLES
Blend nous ouvre une nouvelle fentre o nous pouvons crer un nouveau style (voir
la figure 7.8).
< TextBlock Text = " Pr nom " Grid . Column = " 0 " Grid . Row = " 1 " Style = " {
StaticResource TexteStyle } " / >
Cest la proprit Style bien videmment, qui va permettre dindiquer que lon applique
le style TexteStyle. Celui-ci est dfini dans le XAML du fichier App.xaml :
1
2
3
4
5
< Style x : Key = " TexteStyle " TargetType = " TextBlock " >
< Setter Property = " Foreground " Value = " # FF0B5EF0 " / >
< Setter Property = " FontFamily " Value = " Andy " / >
< Setter Property = " FontSize " Value = " 32 " / >
</ Style >
Ce qui correspond aux valeurs que jai modifies. Et voil, plutt simple non ? Remarquons avant de terminer que les styles peuvent hriter entre eux, ce qui permet de
complter ou de remplacer certaines valeurs. Prenons par exemple le XAML suivant :
1
2
3
4
5
6
7
8
9
< Style x : Key = " TexteStyle " TargetType = " TextBlock " >
< Setter Property = " Foreground " Value = " # FF0B5EF0 " / >
< Setter Property = " FontFamily " Value = " Andy " / >
< Setter Property = " FontSize " Value = " 32 " / >
</ Style >
< Style x : Key = " TexteStyle2 " TargetType = " TextBlock " BasedOn = " {
StaticResource TexteStyle } " >
< Setter Property = " FontSize " Value = " 45 " / >
< Setter Property = " HorizontalAlignment " Value = " Center " / >
</ Style >
Le deuxime style hrite du premier grce la proprit BaseOn. Notez que les styles
sont encore plus puissants que a, nous aurons loccasion de voir dautres utilisations
plus loin dans le cours.
Les thmes
Si vous avez jou avec lmulateur ou avec vos Windows Phone, vous avez pu vous rendre
compte que Windows Phone disposait de plusieurs thmes. Ouvrez votre mulateur et
faites glisser lcran sur la droite ou cliquez sur la flche en bas de lcran daccueil,
cliquez ensuite sur Paramtres (voir la figure 7.11).
Puis sur thme (voir la figure 7.12).
On obtient cet cran (voir la figure 7.13).
Il est possible de choisir le thme, soit sombre soit clair puis la couleur daccentuation
(voir la figure 7.14).
Quest-ce que a veut dire ? Eh bien cela veut dire quon ne peut pas faire nimporte
quoi avec les couleurs et surtout pas nimporte comment. Par exemple, si jcris du
88
LES THMES
LES THMES
texte de couleur blanche, cela passera trs bien avec mon thme sombre, mais cela
deviendra invisible avec un thme clair.
Les contrles de Windows Phone savent grer ces diffrents thmes sans aucun problme grce aux styles systmes qui savent sadapter aux diffrents thmes, comme
par exemple les styles PhoneTextNormalStyle et PhoneTextTitle1Style. Ainsi, si
vous lancez votre application frachement cre en mode sombre, vous aurez les titres
suivants (voir la figure 7.15).
Figure 7.15 Le titre est blanc sur fond noir en mode sombre
Alors quen mode clair, vous aurez la figure 7.16.
Les couleurs sont diffrentes, cest le style qui gre les diffrents thmes. Il est possible de
dtecter le thme de lapplication afin dadapter nos designs, par exemple en changeant
une image ou en changeant une couleur, etc. Pour ce faire, on peut utiliser la technique
suivante :
1
2
3
4
5
6
7
8
9
91
Figure 7.16 Le titre est noir sur fond blanc en mode clair
De mme, on peut rcuprer la couleur daccentuation choisie afin de lutiliser sur nos
pages, par exemple :
1
2
Si on peut mettre un TextBlock, on peut mettre nimporte quoi et cest a qui est
formidable. Par exemple, on peut facilement mettre une image. Reprenons notre rond
rouge du dbut du chapitre, puis utilisez le XAML suivant :
1
2
3
4
5
6
7
8
Nous obtenons un bouton tout fait fonctionnel possdant une image et un texte (voir
la figure 7.18).
Nous navons rien eu dautre faire que de modifier lobjet Content et ce bouton
continue se comporter comme un bouton classique. Remarquons avant de terminer
quil est possible de pousser la personnalisation encore plus loin grce aux modles (en
anglais template) que nous verrons plus loin.
En rsum
Les styles sont un lment trs puissant nous permettant de modifier lapparence
de nos contrles.
On peut changer lapparence des contrles de type ContentControl pour crer
un autre look tout en conservant la fonctionnalit du contrle.
Il faut faire attention aux diffrents thmes dune application et toujours vrifier
93
94
Chapitre
95
Vous pouvez choisir les bornes que vous voulez, mais de 1 500 me parat pas trop mal.
Noubliez pas de grer le cas o lutilisateur saisit nimporte quoi. Nous ne voudrions
pas que notre premier jeu sur Windows Phone ait un bug qui fasse planter lapplication !
Cest vous de jouer. Bon courage.
Correction
Alors, comment tait ce TP ? Pas trop difficile, non ?
Alors, voyons ma correction. Il y a plusieurs faons de raliser ce TP ainsi quune
infinit de mise en page possible. Jai choisi un look trs simple, mais nhsitez pas
faire parler votre crativit.
Commenons par le XAML :
1
2
3
4
5
6
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
< RowDefinition Height = " Auto " / >
</ Grid . RowDefinitions >
7
8
9
10
96
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " TP du jeu du
plus ou du moins " Style = " { StaticResource
PhoneTextTitle2Style } " / >
</ StackPanel >
CORRECTION
11
12
13
14
15
16
17
18
19
20
21
22
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< StackPanel >
< TextBlock Text = " Veuillez saisir une valeur ( entre
0 et 500 ) " Style = " { StaticResource
PhoneTextNormalStyle } " HorizontalAlignment = "
Center " / >
< TextBox x : Name = " Valeur " InputScope = " Number " / >
< Button Content = " V rifier " Tap = " Button_Tap_1 " / >
< TextBlock x : Name = " Indications " Height = " 50 "
TextWrapping = " Wrap " / >
< TextBlock x : Name = " NombreDeCoups " Height = " 50 "
TextWrapping = " Wrap " Style = " { StaticResource
PhoneTextNormalStyle } " / >
</ StackPanel >
</ Grid >
< Button Content = " Rejouer " Tap = " Button_Tap_2 " Grid . Row = " 2 "
/>
</ Grid >
Il sagit de disposer mes contrles de manire obtenir ce rendu (voir la figure 8.1).
6
7
8
9
public MainPage ()
{
I nitializeComponent () ;
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
98
CORRECTION
45
46
47
48
49
50
51
52
Input . GestureEventArgs e )
valeurSecrete = random . Next (1 , 500 ) ;
nbCoups = 0 ;
Indications . Text = string . Empty ;
NombreDeCoups . Text = string . Empty ;
Valeur . Text = string . Empty ;
Le jeu en lui-mme ne devrait pas avoir pos trop de problmes. Lalgorithme est
classique, on commence par dterminer un nombre alatoire puis chaque demande
de vrification, on transforme la valeur saisie en entier, afin de vrifier que lutilisateur
na pas saisi nimporte quoi. Avec le clavier numrique, les erreurs sont limites, mais
elles sont encore possible car on demande des entiers et lutilisateur a la possibilit de
saisir des nombres virgule. Puis on compare et on indique le rsultat (voir la figure
8.2).
100
Chapitre
101
Dessin 2D
Il existe plusieurs types de formes. Elles sont reprsentes par des classes qui drivent toutes dune classe abstraite de base : Shape - http://msdn.microsoft.com/
fr-fr/library/system.windows.shapes.shape(v=vs.95).aspx. Shape est un lment affichable sur une page dans la mesure o elle drive, comme les contrles, de
FrameworkElement et de UIElement. Nous avons notre disposition :
Les ellipses et cercles via la classe Ellipse - http://msdn.microsoft.com/fr-fr/
library/system.windows.shapes.ellipse(v=vs.95).aspx
Les lignes, via la classe Line - http://msdn.microsoft.com/fr-fr/library/
system.windows.shapes.line(v=vs.95).aspx
Plusieurs lignes ou courbes connectes, via la classe Path - http:
//msdn.microsoft.com/fr-fr/library/system.windows.shapes.path(v=
vs.95).aspx. Path pouvant tre traduit en trac, il sagit dun trac de lignes
ou de courbes.
Des lignes connectes via la classe PolyLine - http://msdn.microsoft.com/
fr-fr/library/system.windows.shapes.polyline(v=vs.95).aspx
Les polygones, via la classe Polygon - http://msdn.microsoft.com/fr-fr/
library/system.windows.shapes.polygon(v=vs.95).aspx. La diffrence avec
le PolyLine est que la forme se termine en reliant le dernier trait au premier.
Des rectangles via la classe Rectangle - http://msdn.microsoft.com/fr-fr/
library/system.windows.shapes.rectangle(v=vs.95).aspx
Si vous vous rappelez, nous avons utilis la classe Rectangle dans un prcdent chapitre
pour illustrer les marges. Dessinons par exemple un carr et un cercle. Pour cela, je
peux utiliser les classes Rectangle et Ellipse :
1
2
3
4
qui va nous permettre de tracer une ligne bleue horizontale dpaisseur 15. Nous la
voyons apparatre dans Blend (voir la figure 9.3).
102
DESSIN 2D
Figure 9.1 Affichage dun rectangle et dune ellipse grce leurs contrles respectifs
103
Pinceaux
Les pinceaux vont nous permettre de colorier nos formes. Nous avons rapidement vu
tout lheure que nous pouvions colorier nos formes grce la proprit Fill. Par
exemple, le XAML suivant :
1
2
3
dessine un triangle rectangle de couleur Aqua dont le trait est bleu, dpaisseur 5 (voir
la figure 9.4).
En fait, Aqua et Blue sont des objets drivs de la classe Brush, en loccurrence
ici il sagit dune SolidColorBrush - http://msdn.microsoft.com/fr-fr/library/
system.windows.media.solidcolorbrush(v=vs.95).aspx. Comme on la dj vu,
on peut donc crire notre prcdent pinceau de cette faon :
104
PINCEAUX
1
2
3
4
5
< Polygon Points = " 50 , 50 200 , 200 50 , 200 " Stroke = " Blue "
StrokeThickness = " 5 " >
< Polygon . Fill >
< SolidColorBrush Color = " Aqua " / >
</ Polygon . Fill >
</ Polygon >
Ce qui nous offre un meilleur contrle sur le pinceau. Nous pouvons par exemple changer
lopacit et la passer de 1 (valeur par dfaut) 0.4 par exemple :
1
2
3
4
5
< Polygon Points = " 50 , 50 200 , 200 50 , 200 " Stroke = " Blue "
StrokeThickness = " 5 " >
< Polygon . Fill >
< SolidColorBrush Color = " Aqua " Opacity = " 0 . 4 " / >
</ Polygon . Fill >
</ Polygon >
Et nous pouvons voir que la couleur est un peu plus transparente (voir la figure 9.5).
< Polygon Points = " 50 , 50 200 , 200 50 , 200 " Stroke = " Blue "
StrokeThickness = " 5 " >
< Polygon . Fill >
< ImageBrush ImageSource = " http :// uploads . siteduzero . com /
files / 337001_338000 / 337519 . png " / >
</ Polygon . Fill >
</ Polygon >
PINCEAUX
Reprenons notre triangle rectangle et cliquez droite sur le pinceau de dgrad (voir
la figure 9.8).
< Polygon Points = " 50 , 50 200 , 200 50 , 200 " Stroke = " Blue "
StrokeThickness = " 5 " >
< Polygon . Fill >
< LinearGradientBrush EndPoint = " 0 .5 , 1 " StartPoint = " 0 .5 , 0
">
< GradientStop Color = " Black " Offset = " 0 " / >
< GradientStop Color = " # FF1FDC0C " Offset = " 1 " / >
< GradientStop Color = " # FFE8AD11 " Offset = " 0 . 488 " / >
</ LinearGradientBrush >
</ Polygon . Fill >
</ Polygon >
Les transformations
Le XAML possde un systme de transformations qui permet dagir sur les contrles. Il
existe plusieurs types de transformations dites affines car elles conservent la structure
originale du contrle. Il est par exemple possible deffectuer :
une rotation grce la classe RotateTransform - http://msdn.microsoft.com/
fr-fr/library/system.windows.media.rotatetransform(v=vs.95).aspx
une translation grce la classe TranslateTransform - http://msdn.microsoft.
com/fr-fr/library/system.windows.media.translatetransform(v=vs.95)
.aspx
une mise lchelle grce la classe ScaleTransform - http://msdn.microsoft.
com/fr-fr/library/system.windows.media.scaletransform(v=vs.95).aspx
une inclinaison grce la classe SkewTransform - http://msdn.microsoft.
com/fr-fr/library/system.windows.media.skewtransform(v=vs.95).aspx
Une transformation matricielle grce la classe MatrixTransform http://msdn.microsoft.com/fr-fr/library/system.windows.media.
matrixtransform(v=vs.95).aspx
Par exemple, pour faire pivoter un bouton de 45, je peux utiliser le code suivant :
1
2
3
4
5
6
7
8
9
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< StackPanel >
< Button Content = " Cliquez - moi ! " >
< Button . RenderTransform >
< RotateTransform x : Name = " Rotation " Angle = " 45 "
CenterX = " 100 " CenterY = " 50 " / >
</ Button . RenderTransform >
</ Button >
</ StackPanel >
</ Grid >
LES TRANSFORMATIONS
109
Voil pour les transformations. En soi elles ne sont pas toujours trs utiles, mais elles
rvlent toutes leurs puissances grce aux animations que nous dcouvrirons dans le
chapitre suivant.
En rsum
Le XAML possde plein de formes que nous pouvons utiliser pour dessiner dans
nos applications, comme le trait, lellipse, le rectangle, etc.
chaque forme peut tre applique une couleur de remplissage ou de traits
grce aux pinceaux.
110
LES TRANSFORMATIONS
111
112
Chapitre
10
113
Pour fonctionner, elles ont besoin dune autre classe qui soccupe de contrler les animations afin dindiquer leurs cibles et la planification de lanimation. Il sagit de la
classe StoryBoard - http://msdn.microsoft.com/fr-fr/library/system.windows.
media.animation.storyboard(v=vs.95).aspx dont le nom explicite rappelle un peu
les projets de montage audio ou vido. Cest le mme principe, cest elle qui va cadencer
les diffrentes animations.
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< StackPanel x : Name = " LeStackPanel " >
< Button Content = " Cliquez - moi ! " / >
< TextBlock Text = " Je vais bient t dispara tre ... " / >
</ StackPanel >
< StackPanel Grid . Row = " 1 " >
114
< Button Content = " D marrer l ' animation " Tap = " Button_Tap "
/>
</ StackPanel >
</ Grid >
Nous allons maintenant crer notre Storyboard. Celui-ci doit se trouver en ressources.
Comme on la dj vu, vous pouvez le mettre en ressources de lapplication, de la page
ou bien en ressources dun contrle parent. Mettons-le dans les ressources de la grille :
1
2
3
4
5
6
7
8
9
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< Grid . Resources >
< Storyboard x : Name = " MonStoryBoard " >
</ Storyboard >
</ Grid . Resources >
10
11
12
13
14
15
16
17
18
Ce Storyboard doit avoir un nom afin dtre manipul par le clic sur le bouton. Il faut
maintenant dfinir lanimation :
1
2
3
4
5
Il sagit dune animation de type double o nous allons animer la proprit Opacity
pour la faire aller de la valeur 1 (visible) la valeur 0 (invisible) pendant une dure
de deux secondes, ciblant notre contrle nomm LeStackPanel. Il faut maintenant
dclencher lanimation lors du clic sur le bouton :
1
2
3
4
Difficile de vous faire une copie dcran du rsultat mais nhsitez pas essayer par
vous-mme (voir la figure 10.1).
115
11
12
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< Grid . Resources >
< Storyboard x : Name = " MonStoryBoard " >
< DoubleAnimation From = " 0 " To = " 200 " Duration = " 0 : 0 : 3 "
AutoReverse = " True "
RepeatBehavior = " Forever "
Storyboard . TargetName = "
MonBouton " Storyboard .
TargetProperty = " ( Canvas . Left
)"/>
</ Storyboard >
</ Grid . Resources >
13
14
15
16
116
< Canvas Width = " 480 " Height = " 500 " x : Name = " LeCanvas " >
< Button x : Name = " MonBouton " Content = " Cliquez - moi ! " / >
</ Canvas >
Jen profite pour indiquer que pour animer une proprit complexe, il faut la
saisir entre parenthses. Je reviendrai sur ce type de proprit plus loin dans
le cours.
Nous pouvons contrler plus finement une animation. Jusqu prsent, nous avons utilis la mthode Begin() pour dmarrer une animation. Vous pouvez galement utiliser
la mthode Stop() pour arrter une animation, la mthode Pause() pour la mettre
en pause et la mthode Resume() pour la reprendre. Vous pouvez galement faire des
animations de transformations. Il suffit de combiner lutilisation des transformations
et dune DoubleAnimation. Par exemple, ici je vais faire tourner mon bouton de 90
degrs et le faire revenir sa position initiale :
1
2
3
4
5
6
7
8
9
10
11
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< Grid . Resources >
< Storyboard x : Name = " MonStoryBoard " >
< DoubleAnimation From = " 0 " To = " 90 " Duration = " 0 : 0 : 1 "
AutoReverse = " True "
Storyboard . TargetName = " Rotation "
Storyboard . TargetProperty = " Angle
"/>
</ Storyboard >
</ Grid . Resources >
12
13
14
15
16
17
18
19
20
21
22
23
< Storyboard x : Name = " MonStoryBoard " BeginTime = " 0 : 0 : 2 " >
< DoubleAnimation From = " 0 " To = " 90 " Duration = " 0 : 0 : 1 "
AutoReverse = " True "
Storyboard . TargetName = " Rotation " Storyboard .
TargetProperty = " Angle " / >
</ Storyboard >
Par exemple ici, lanimation va durer une seconde et dmarrera deux secondes aprs son
dclenchement via la mthode Begin(). On peut contrler plus finement une animation
grce aux animations dites Key Frame qui permettent dindiquer diffrents moments
cls dune animation. Il est possible ainsi de spcifier la valeur de la proprit anime
un moment T. On utilisera les trois types danimations suivantes :
DoubleAnimationUsingKeyFrames
ColorAnimationUsingKeyFrames
PointAnimationUsingKeyFrames
Chacune de ces animations peut tre de trois types : Linear, Discret et Spline.
Lanimation linaire se rapproche des animations que nous avons vues prcdemment
dans la mesure o entre les moments cls, lanimation passera par toutes les valeurs
sparant les deux valeurs des moments cls. On pourrait illustrer ceci en simulant
un secouage de bouton afin dattirer lattention de lutilisateur. Le secouage va
consister faire une rotation de X degrs dans le sens horaire, puis revenir la position
initiale, puis faire la rotation de X degrs dans le sens anti horaire et enfin revenir la
position initiale. Il y a donc cinq moments cls dans cette animation :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< Grid . Resources >
< Storyboard x : Name = " MonStoryBoard " >
< D o u b l e A n i m a t i o n U s i n g K e y F r a m e s Storyboard .
TargetName = " Rotation " Storyboard . TargetProperty =
" Angle " RepeatBehavior = " 5x " >
< LinearDoubleKeyFrame Value = " 0 " KeyTime = " 00 : 00 :
00 " / >
< LinearDoubleKeyFrame Value = " 5 " KeyTime = " 00 : 00 :
00 . 1 " / >
< LinearDoubleKeyFrame Value = " 0 " KeyTime = " 00 : 00 :
00 . 2 " / >
< LinearDoubleKeyFrame Value = " -5 " KeyTime = " 00 : 00
: 00 . 3 " / >
< LinearDoubleKeyFrame Value = " 0 " KeyTime = " 00 : 00 :
00 . 4 " / >
</ DoubleAnimationUsingKeyFrames >
</ Storyboard >
</ Grid . Resources >
17
18
118
< Button x : Name = " MonBouton " Content = " Cliquez - moi ! "
Width = " 200 " Height = " 100 " >
< Button . RenderTransform >
< RotateTransform x : Name = " Rotation " Angle = " 0 "
CenterX = " 100 " CenterY = " 50 " / >
</ Button . RenderTransform >
</ Button >
</ StackPanel >
< StackPanel Grid . Row = " 1 " >
< Button Content = " D marrer l ' animation " Tap = " Button_Tap "
/>
</ StackPanel >
</ Grid >
5
6
7
8
9
10
11
12
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
13
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock Text = " MON APPLICATION " Style = " {
StaticResource PhoneTextNormalStyle } " Margin = " 12 , 0 "
/>
< TextBlock Text = " nom de la page " Margin = "9 , -7 ,0 , 0 "
Style = " { StaticResource PhoneTextTitle1Style } " / >
</ StackPanel >
14
15
16
17
18
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< Button x : Name = " button " Content = " Button "
HorizontalAlignment = " Left " Margin = " 137 , 68 ,0 , 0 "
VerticalAlignment = " Top " Rend erTran sformO rigin = " 0 .5 , 0
.5">
< Button . RenderTransform >
< CompositeTransform / >
</ Button . RenderTransform >
</ Button >
</ Grid >
</ Grid >
19
20
21
22
23
24
25
26
On peut voir quil nous a mis une CompositeTransform dans le bouton avec une
translation sur laxe des X et sur laxe des Y de une seconde. Remarquez la syntaxe
particulire qua utilis Blend :
1
122
2
3
4
5
< Button x : Name = " button " Content = " Button " Height = " 77 " Margin = " 98
, 60 , 165 , 0 " VerticalAlignment = " Top " Rend erTran sform Origin = " 0 .
5 , 0 . 5 " Tap = " Button_Tap " >
< Button . RenderTransform >
< C om positeTransform / >
</ Button . RenderTransform >
</ Button >
Projections 3D
Chaque lment affichable avec le XAML peut subir une projection 3D. Cela consiste
donner une surface 2D une perspective 3D afin de raliser un effet visuel. Plutt
quun long discours, un petit exemple qui parlera de lui-mme. Prenons par exemple
une image, limage de la couverture de mon livre sur le C# :
1
< Image Source = " http :// uploads . siteduzero . com / files /
365001_366000 / 365350 . jpg " / >
< Image Source = " http :// uploads . siteduzero . com / files /
365001_366000 / 365350 . jpg " >
124
PROJECTIONS 3D
2
3
4
5
qui lui fera subir une rotation de -35 autour de laxe des X, de -35 autour de laxe
des Y et de 15 autour de laxe des Z, ce qui donnera la figure 10.10.
125
Vous vous doutez que je vais animer la rotation sur laxe des Y et sur laxe des Z de 0
360 degrs pendant une dure de 5 secondes . . . Difficile de vous montrer le rsultat,
mais je ne peux que vous encourager tester chez vous (voir la figure 10.11).
public MainPage ()
{
I ni t i alizeComponent () ;
Loaded += MainPage_Loaded ;
}
126
PROJECTIONS 3D
6
7
8
9
10
En rsum
Le XAML possde un framework complexe danimation.
Blend se rvle un atout de qualit dans la ralisation danimations complexes.
Les projections 3D permettent dajouter un effet de perspective 3D dont le rendu
est plutt intressant.
127
128
Deuxime partie
129
Chapitre
11
131
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
10
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " D
monstration de la navigation " Style = " { StaticResource
PhoneTextNormalStyle } " / >
< TextBlock x : Name = " PageTitle " Text = " Page de Login "
Margin = "9 , -7 ,0 , 0 " Style = " { StaticResource
PhoneTextTitle1Style } " / >
</ StackPanel >
11
12
13
14
15
16
17
18
19
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< StackPanel >
< TextBlock Text = " Saisir votre login "
HorizontalAlignment = " Center " / >
< TextBox x : Name = " Login " / >
< Button Content = " Se connecter " Tap = " Button_Tap " / >
</ StackPanel >
</ Grid >
</ Grid >
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
10
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " D
monstration de la navigation " Style = " { StaticResource
PhoneTextNormalStyle } " / >
< TextBlock x : Name = " PageTitle " Text = " Page des cours "
Margin = "9 , -7 ,0 , 0 " Style = " { StaticResource
P honeTextTitle1Style } " / >
</ StackPanel >
11
12
13
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< Grid . RowDefinitions >
133
14
15
16
17
18
19
20
Retournons dans la mthode de clic sur le bouton de la premire page. Nous allons
utiliser le code suivant :
1
2
3
4
5
Nous utilisons le service de navigation et notamment sa mthode Navigate pour accder la page ListeCours.xaml, si le login nest pas vide. Grce cette mthode, nous
pouvons aller facilement sur la page en construction. Remarquons que si nous appuyons
sur le bouton en bas gauche du tlphone permettant de faire un retour arrire, alors
nous revenons la page prcdente. Si nous cliquons nouveau sur le retour arrire,
134
Dsormais, la page ListeCours sera appele avec le paramtre login qui vaudra la
valeur saisie dans la TextBox. Pour rcuprer cette valeur, rendez-vous dans le code
behind de la seconde page o nous allons substituer la mthode appele lorsquon
navigue sur la page, il sagit de la mthode OnNavigatedTo, cette mthode faisant
partie de la classe PhoneApplicationPage. Nous aurons donc le code behind suivant :
1
2
3
4
5
6
7
8
9
10
11
12
Cest cet endroit que nous allons extraire la valeur du paramtre avec le code suivant :
1
2
3
4
5
6
7
8
9
135
136
Lutilisation du dictionnaire dtat est trs pratique pour faire transiter un objet complexe qui sera difficilement reprsentable dans des paramtres de query string.
Attention : le dictionnaire dtat ne doit contenir que des informations srialisables.
Voil pour ce premier aperu du service de navigation. Remarquez que le XAML
possde galement un contrle qui permet de naviguer entre les pages, comme le
NavigationService. Il sagit du contrle HyperlinkButton - http://msdn.microsoft.
com/fr-fr/library/system.windows.controls.hyperlinkbutton(v=vs.95).aspx.
Il suffira de renseigner sa proprit NavigateUri. Compltons notre page ListeCours
pour rajouter en bas un HyperLinkButton qui renverra vers une page Contact.xaml :
1
2
3
4
5
6
7
8
9
10
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Grid . RowDefinitions >
< RowDefinition Height = " 200 " / >
< RowDefinition Height = " * " / >
< RowDefinition Height = " auto " / >
</ Grid . RowDefinitions >
< TextBlock x : Name = " Bonjour " Text = " Bonjour "
H or i zontalAlignment = " Center " / >
< TextBlock Grid . Row = " 1 " Text = " Cette page est en
construction ... " / >
< HyperlinkButton Grid . Row = " 2 " Content = " Nous contacter "
NavigateUri = " / Contact . xaml " / >
</ Grid >
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " D
monstration de la navigation " Style = " { StaticResource
PhoneTextNormalStyle } " / >
< TextBlock x : Name = " PageTitle " Text = " Nous contacter "
Margin = "9 , -7 ,0 , 0 " Style = " { StaticResource
P honeTextTitle1Style } " / >
137
11
12
13
14
15
16
17
18
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< StackPanel >
< TextBlock Text = " Il n ' y a rien pour l ' instant ... "
/>
< Button Content = " Revenir la page pr c dente " Tap =
" Button_Tap " / >
</ StackPanel >
</ Grid >
</ Grid >
Ainsi, lorsque nous dmarrerons lapplication et aprs nous tre logus, nous pouvons
voir le bouton nous contacter en bas de la page (voir la figure 11.4).
139
140
Il est possible ici de faire ce que lon veut, comme afficher un message de confirmation
demandant si on veut rellement quitter cette page, ou sauvegarder des infos, etc. On
pourra annuler laction de retour arrire en modifiant la proprit Cancel de lobjet
CancelEventArgs true, si par exemple lutilisateur ne souhaite finalement pas revenir
en arrire. On peut galement choisir de rediriger vers une autre page si cest pertinent :
1
2
3
4
5
6
7
8
143
Le tombstonning
Avec Windows Phone 7 est apparu un changement radical dans la faon dont sont
traites les applications. Fini le multitche comme on le connaissait auparavant avec
un Windows classique, il ny a dsormais quune application qui sexcute la fois.
Cela veut dire que si je suis dans une application, que jappuie sur le bouton de menu
et que jouvre une nouvelle application, je nai pas deux applications qui tournent en
parallle, mais une seule. Ma premire application ne sest pas ferme non plus, elle
est passe dans un mode suspendu , voire dsactiv en fonction du contexte.
Ainsi, si je quitte ma seconde application en appuyant par exemple sur le bouton de
retour arrire, alors ma premire application qui tait en mode suspendu ou dsactiv,
se ractive et repasse dans le mode en cours dexcution.
Ce fonctionnement est conserv pour Windows Phone 8 et a t galement tendu pour
les applications Windows 8. Une application peut donc soit tre :
En cours dexcution
Suspendue
Dsactive
Non dmarre
Lorsque lapplication passe en mode suspendu, par exemple lorsque jappuie sur le
bouton de menu, elle reste intacte en mmoire. Cela veut dire quun retour arrire
pour retourner lapplication sera trs rapide et vous retrouverez votre application
comme elle se trouvait prcdemment.
Enfin, a, cest la thorie. En vrai, cest un peu plus compliqu que a. Cest le systme
dexploitation qui soccupe de grer les tats des applications en fonction notamment
de la mmoire disponible. En effet, Windows Phone peut choisir de dsactiver une
application suspendue si lapplication en cours dexcution a besoin de mmoire. De
la mme faon, lapplication peut avoir simplement t suspendue et se ractiver de
manire optimale si le systme dexploitation na pas eu besoin de mmoire. Une application dsactive a t termine par le systme dexploitation, bien souvent parce
quil avait besoin de mmoire. Quelques informations restent cependant disponibles et
si lutilisateur revient sur lapplication, celle-ci est alors redmarre depuis zro mais
ces informations sont accessibles afin de permettre de restaurer ltat de lapplication.
Tout ceci implique que lon ne peut jamais garantir que lutilisateur va fermer correctement une application ou que celle-ci va se terminer proprement, cest mme dailleurs
rarement le cas. Il peut y avoir plein de scnarios possibles. Par exemple votre utilisateur
est en train de saisir des informations dans votre application, il change dapplication
pour aller lire un mail, voir la mto, puis plus tard il revient votre application ; entre
temps il a reu un coup de tlphone, recharg son tlphone . . . Quest devenue notre
application ? Comment apporter lutilisateur tout le confort dutilisation possible et
lui garantir quil na pas perdu toute sa saisie ? Heureusement, lorsque lapplication
change dtat, nous pouvons tre prvenus grce des vnements. Ce sont des vnements applicatifs que lon retrouve dans le fichier dapplication que nous avons dj vu :
App.xaml. Par contre, ici nous allons nous intresser son code behind : App.xaml.cs
et notamment aux vnements dj gnrs pour nous. Ouvrez-le et vous pouvez voir :
144
LE TOMBSTONNING
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Les commentaires gnrs parlent deux-mmes. Ces mthodes sont donc lendroit idal
pour faire des sauvegardes de contexte. Voici la figure 11.11 un schma rcapitulatif
des diffrents tats.
1
2
3
4
5
6
Action
Dmarrage
Dsactivation
Reprise rapide
Reprise lente
Fermeture
Fermeture force par lOS
vnement applicatif
Launching
Deactivated
Activated
Activated
Closing
145
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< StackPanel >
< TextBox / >
</ StackPanel >
</ Grid >
Et dans le code-behind :
146
LE TOMBSTONNING
1
2
3
4
5
6
7
8
9
10
public MainPage ()
{
I ni t i alizeComponent () ;
_ e s t N ouvelleInstance = true ;
}
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
147
Figure 11.12 Appui sur le bouton de menu pour que lapplication soit suspendue
Nous sommes alors passs dans la mthode OnNavigatedTo et nous sommes dans le cas
o _estNouvelleInstance vaut vrai et que le dictionnaire dtat est vide (dmarrage
de lapplication). Lorsquon clique sur le bouton de menu, alors nous passons dans la
mthode OnNavigatedFrom qui indique que la page est dsactive. Vous arrivez alors
sur la page daccueil de votre mulateur (ou de votre Windows Phone). Un petit clic
sur le bouton de retour vous ramne sur notre application avec la zone de texte qui
correspond ce que nous avons saisi. On repasse dans la mthode OnNavigatedTo avec
_estNouvelleInstance qui vaut faux. Ceci prouve bien que lapplication est intacte
en mmoire et que nous ne sommes pas repasss dans le constructeur de la classe. Il ny
a rien faire car lapplication est exactement la mme quavant son changement dtat.
Il ne reste plus qu cliquer nouveau sur la flche de retour pour fermer lapplication
et ainsi repasser dans la mthode OnNavigatedFrom mais cette fois-ci dans le else,
quand e.NavigationMode vaut NavigationMode.Back. Remarquez que le dbogueur
est toujours en route et quil faut larrter. Voil pour ltat suspendu.
Pour simuler ltat dsactiv, il faut aller dans les proprits du projet en faisant un
148
LE TOMBSTONNING
clic droit dessus, puis proprits. On arrive sur lcran des proprits du projet, cliquez
sur dboguer et vous pouvez alors cocher la case qui permet de forcer passer dans
ltat dsactiv (Tombstone) lorsque lon suspend lapplication (voir la figure 11.13).
Puis modifiez le code behind, tout en conservant le squelette de MainPage, pour avoir
ceci :
1
2
3
4
5
6
7
8
9
public MainPage ()
{
I ni t i alizeComponent () ;
_ e s t N ouvelleInstance = true ;
}
10
149
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Qui est excut lorsque lapplication est dsactive. Vous me direz quon sembte
peut-tre un peu pour rien. Ne pourrait-on pas remplacer la mthode OnNavigatedTo
par :
1
150
LE TOMBSTONNING
2
3
4
5
Car finalement, peu importe si on est en mode dmarr, suspendu ou dsactiv, tout
ce qui nous intresse cest que le TextBox soit rempli si jamais il la t auparavant.
Je vous dirais oui, mais. . . Ici, lappel au dictionnaire dtat est assez rapide, mais
imaginons que nous ayons besoin daller lire une information sur internet (ce que nous
apprendrons faire trs bientt), ou effectuer un calcul complexe, ou quoi que ce soit,
ce nest pas la peine de le faire si nous possdons dj linformation. Cela fluidifie
le redmarrage de lapplication, vite de consommer des datas pour rien, etc. Veillez
toujours ne pas faire des choses inutiles et gardez lesprit quun tlphone a des
ressources limites.
Et les vnements applicatifs ?
Ils servent aussi a. Lorsque lapplication est suspendue ou dsactive, nous avons
vu que lvnement application Deactivated tait lev. Cest galement lemplacement
idal pour faire persister des informations dans le dictionnaire dtat :
1
2
3
4
De la mme faon, lorsque lapplication est ractive, que ce soit en reprise rapide
(depuis ltat suspendu) ou en reprise lente (depuis ltat dsactive), lvnement
applicatif Activated est lev. Cest galement un endroit idal pour prparer nouveau
ltat de notre application :
1
2
3
4
5
6
7
8
151
T e l e c h a r g e r L e s N o u v e l l e s D o n n e e s () ;
Remarquez que le dictionnaire dtat est accessible via la proprit PhoneApplicationService.Current.State["..."] depuis nimporte quel emplacement et via la proprit State["..."] depuis une page
(qui drive de PhoneApplicationPage). Cest la mme chose.
Mais bon, il y a encore un petit problme ! tant donn que nous ne matrisons pas le
passage en dsactiv, encore moins la fermeture force de lapplication par le systme
dexploitation, ou encore le redmarrage manuel de lapplication par lutilisateur (sil
relance lapplication depuis la page daccueil), nous risquons de perdre nouveau toutes
les informations que notre utilisateur a saisi mais cette fois-ci, pas parce que nous avons
mal gr la dsactivation, mais parce que lapplication sest termine !
La solution est dutiliser la mme mcanique mais en faisant persister les informations
dans la mmoire du tlphone ddie lapplication. Il sagit du rpertoire local (en
anglais Local folder ), galement connu sous son ancien nom : IsolatedStorage. Voyez
cela un peu comme des fichiers sur un disque dur o nous pouvons enregistrer ce que
bon nous semble. Puisque cette information persiste entre les dmarrages successifs de
lapplication, il sera possible denregistrer ltat de notre application afin par exemple
que lutilisateur ne perde pas toute sa saisie. Je ne vais pas dtailler le code qui permet
denregistrer des informations dans la mmoire du tlphone, car jy reviendrai dans
un prochain chapitre.
Avant de terminer, sachez quil existe un autre tat, ltat Obscured, que lon peut
traduire par obscurci . Il sagit dun tat o une partie de lcran est masqu, par
exemple lorsquon reoit un SMS, un appel, une notification, etc. Lapplication reste
dans un tat o elle est en cours dexcution, mais lapplication peut devenir difficile
utiliser. Imaginons que votre utilisateur soit en plein compte rebours final, prt
vaincre le boss final et quil reoive un SMS juste au moment o il va gagner et qu
cause de cela il reoit la flche fatale juste en plein milieu du cur. . ., il va maudire votre
application, juste titre ! Pour viter cela, il est possible dtre notifi lorsque lapplication passe en mode Obscured, ce qui nous laisse par exemple lopportunit de faire une
pause dans notre compte rebours final . . . Pour cela, rendez-vous dans le constructeur
de la classe App pour vous abonner aux vnements Obscured et Unobscured :
1
2
3
public App ()
\{
// plein de choses ...
4
5
6
7
8
9
152
LE TOMBSTONNING
10
11
12
13
14
15
16
17
18
En rsum
Il est possible de naviguer de page en page dans une application grce au service
de navigation.
Le contrle HyperlinkButton permet de dmarrer une navigation trs simplement.
Il est possible de faire transiter des informations de contexte entre les pages ; on
pourra utiliser la query string ou le dictionnaire dtat.
Pour dclencher un retour arrire par code, on utilisera la mthode GoBack()
du NavigationService.
On peut ajouter facilement une image daccueil une application Windows
Phone en utilisant une image JPEG, nomme SplashScreenImage.jpg.
Il est trs important de grer correctement les diffrents tats par lesquels peut
passer une application afin de fournir une exprience dutilisation la plus optimale.
153
154
Chapitre
12
155
Correction
Passons la correction, maintenant que tout le monde a ralis ce dfi haut la main. Il
sagit dans un premier temps de crer deux pages diffrentes. Vous avez pu y mettre ce
que vous vouliez, il fallait juste un moyen de pouvoir naviguer sur une autre page. La
premire chose faire est donc de crer lanimation qui va permettre de faire disparaitre
lgamment la premire page. Il sagit dune animation qui cible le conteneur de premier
niveau de notre page, dans mon cas une Grid. tant donn que je vais avoir besoin de
faire une translation, je vais dfinir une classe TranslateTransform dans la proprit
RenderTransform de ma grille :
1
2
3
4
5
6
7
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RenderTransform >
< TranslateTransform x : Name = " Translation " / >
</ Grid . RenderTransform >
[... reste du code supprim pour plus de lisibilit ...]
< Button Content = " Aller la page 2 " Tap = " Button_Tap " / >
</ Grid >
156
CORRECTION
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
157
5
6
7
8
9
10
11
12
13
14
15
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RenderTransform >
< TranslateTransform x : Name = " Translation " / >
</ Grid . RenderTransform >
[... code supprim pour plus de lisibilit ...]
</ Grid >
7
8
9
10
11
12
13
On redfinit la mthode qui est appele lorsquon navigue sur la page afin de dmarrer
lanimation. Et voil ! Quoique. . . ce nest pas tout fait complet en ltat car si vous
revenez sur la page prcdente en appuyant sur le bouton de retour arrire, vous vous
rendrez compte que la page est vide. Eh oui, nous avons fait disparaitre la page lors de
lanimation de transition ! Nous devons donc arrter cette fameuse animation lorsque
nous revenons sur la page avec :
1
2
3
4
5
Et voil, prsentes comme jai pu, nos deux animations (voir la figure 12.1).
158
CORRECTION
159
160
Chapitre
13
161
Avec une telle classe, il est possible dutiliser cette proprit ainsi :
1
2
3
< TextBlock Text = " Je suis un texte " Foreground = " Red " / >
Ici, on ne le voit pas mais ces deux proprits sont en fait des proprits de dpendances.
Le vrai appel qui sopre derrire est quivalent :
1
2
3
162
On utilise ici la proprit attache Grid.Column pour indiquer la grille quel endroit
il faut placer nos TextBlock.
Allez, jarrte de vous embter avec ces proprits volues. Jen ai rapidement parl
pour que vous sachiez que quand je parle de proprits, je parle en fait de quelque
chose dun peu plus pouss que ce que nous connaissions dj.
Ce quil faut retenir cest quil y a un systme complexe derrire qui est presque invisible
pour une utilisation de dbutant. Si le sujet vous intresse, nhsitez pas poser des
questions ou aller chercher des informations sur internet.
Sachez enfin quil est possible de crer nos propres proprits de dpendances et nos
propres proprits attaches, mais nous sortons du cadre dbutant et je ne le montrerai
pas dans ce cours.
En rsum
Les proprits de dpendances offrent un mcanisme plus complet que la proprit classique C#.
Ces proprits sont utilises par le moteur XAML pour grer les styles, la liaison
de donnes, etc.
En tant que dbutant, nous navons pas vraiment besoin de savoir ce quil se
cache l dessous.
163
164
Chapitre
14
165
Le .XAP
Pour illustrer ce chapitre, crons un nouveau projet, que nous nommerons par exemple
DemoXap. Lorsque nous compilons notre application pour Windows Phone, celle-ci se
gnre par dfaut dans un sous rpertoire de notre projet : DemoXap\Bin\Debug, Debug
tant le mode de compilation par dfaut lorsque nous crons une solution. Nous verrons
dans la dernire partie comment passer le mode de compilation en Release.
Toujours est-il que dans ce rpertoire, il va sy gnrer plein de choses, mais une seule
nous intresse vraiment ici, cest le fichier qui porte le nom du projet et dont lextension
est .xap. Dans mon cas, il sappelle DemoXap_Debug_AnyCPU.xap car mon mode de
compilation est Debug, Any Cpu (voir la figure 14.1).
et
1
MonImage . Source = new BitmapImage ( new Uri ( " / monimage . png " ,
UriKind . Relative ) ) ;
Ceci sexplique simplement. tant donn que limage est inclue dans le .xap, il va
pouvoir aller la chercher tranquillement lemplacement /monimage.png, donc la
racine du package. Essayez dsormais de changer laction de gnration ressource, et
vous verrez que limage ne saffiche plus. En effet, limage nest plus cet emplacement
mais compile lintrieur de lassembly. Il est quand mme possible daccder son
contenu, mais cela demande daller lire lintrieur de lassembly, ce que lon peut faire
de cette faon :
1
Bien sr, si limage nest pas place la racine, mais dans un sous rpertoire, il faudra
indiquer le sous rpertoire dans lURL de limage.
Remarquez que dune manire gnrale, il vaudra mieux positionner le plus
souvent possible laction de gnration contenu afin de rduire la taille de
lassembly et ainsi augmenter les performances de chargement de celle-ci. Si
les images sont en ressources, elles se chargeront plus vite. Si elles sont en
contenu, alors cest lapplication qui se chargera plus vite. De mme, pour
des raisons de performances, vous aurez intrt utiliser des jpg partout sauf
si vous avez besoin de transparence.
167
En rsum
Une application Windows Phone est gnre sous la forme dune archive dont
lextension est .xap.
On peut embarquer des lments dans notre assembly en positionnant laction
de gnration Resource.
Un lment compil avec laction de gnration Contenu sera disponible directement dans le .xap.
168
Chapitre
15
ListBox
Difficult :
La ListBox est un lment incontournable dans la cration dapplications pour Windows
Phone. Elle permet un puissant affichage dune liste dlment. Voyons tout de suite de
quoi il sagit car vous allez vous en servir trs souvent !
169
Un contrle majeur
Utilisons notre designer prfr pour rajouter une ListBox dans notre page et nommonsl ListeDesTaches, ce qui donne le XAML suivant :
1
2
Une ListBox permet dafficher des lments sous la forme dune liste. Pour ajouter des
lments, on peut utiliser le XAML suivant :
1
2
3
4
5
List < string > chosesAFaire = new List < string >
170
UN CONTRLE MAJEUR
2
3
4
5
6
7
};
ListeDesTaches . ItemsSource = chosesAFaire ;
Il ne reste plus qu dmarrer lapplication. Nous pouvons voir que la ListBox sest
automatiquement remplie avec nos valeurs (voir la figure 15.2).
171
3
4
5
public MainPage ()
{
I nitializeComponent () ;
6
7
8
9
10
11
12
13
14
15
16
"
"
"
"
=>
17
18
19
20
21
22
5
6
7
8
9
10
Et laffaire est rgle ! Et je vous rpondrai oui, parfait. Sauf que cela ne fonctionne que
parce que nous affichons du texte ! Et si nous devions afficher du texte et une image ?
Ou du texte et un bouton ?
172
Figure 15.3 Cest la reprsentation de lobjet qui saffiche ici dans la ListBox
6
7
8
9
10
11
174
};
13
14
15
16
17
18
19
20
21
22
23
24
Le principe est de construire des lments numrables partir de notre liste. Il sagit
dy mettre un nouvel objet qui possde une proprit Description et une proprit
Image qui contient un objet BitmapImage construit partir de la valeur de la priorit
de la tche. Il est important de constater que la classe contient des proprits qui ont
les mmes noms que ce quon a crit dans lextension de balisage vue plus haut.
1
2
< Image Source = " { Binding Image } " Width = " 30 " Height = " 30 " / >
< TextBlock Text = " { Binding Description } " Margin = " 20 0 0 0 " / >
Jy reviendrai plus tard, mais nous avons ici fait ce quon appelle un binding, que lon
peut traduire par une liaison de donnes. Nous indiquons que nous souhaitons mettre la
valeur de la proprit Image de llment courant dans la proprit Source de limage
et la valeur de la proprit Description de llment courant dans la proprit Text
du TextBlock. Rappelez-vous, llment courant est justement un objet spcial qui
contient ces proprits.
Si nous excutons le code, nous obtenons donc la figure 15.6.
Magique ! Le seul dfaut viendrait de mes images qui ne sont pas transparentes. . .
175
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " 100 " / >
</ Grid . RowDefinitions >
176
14
15
16
17
18
19
20
Ce qui va nous permettre dafficher dans le TextBlock la valeur de ce que nous avons
choisi (voir la figure 15.7).
Nous voyons au passage que la slection est mise en valeur automatiquement dans la
ListBox.
Remarquez qutant donn que notre ListBox a un nom et donc une variable pour
la manipuler, il est galement dobtenir la valeur slectionne grce linstruction
suivante :
1
2
3
4
Ce qui est dailleurs plus propre. Lobjet SelectedItem est du type object et sera
du type de ce que nous avons mis dans la proprit ItemsSource. tant donn que
nous avons mis une liste de chane de caractres, SelectedItem sera une chane, nous
pouvons donc faire :
177
public MainPage ()
{
I ni t i alizeComponent () ;
List < string > chosesAFaire = new List < string >
{
" Arroser les plantes " ,
" Tondre le gazon " ,
" Planter les tomates "
};
178
Ou encore :
1
2
3
4
5
6
7
8
9
10
11
12
public MainPage ()
{
I ni t i al i zeComponent () ;
List < string > chosesAFaire = new List < string >
{
" Arroser les plantes " ,
" Tondre le gazon " ,
" Planter les tomates "
};
ListeDesTaches . ItemsSource = chosesAFaire ;
ListeDesTaches . SelectedValue = chosesAFaire [ 1 ];
}
sachant que le fait dinitialiser la slection dun lment par code dclenche lvnement de changement de slection ; ce qui nous arrange pour que notre TextBlock soit
rempli. Pour viter ceci, il faudrait associer la mthode lvnement de changement
de slection aprs avoir slectionn llment. Cela revient enlever la dfinition de
lvnement dans le XAML :
1
2
public MainPage ()
{
I ni t i al i zeComponent () ;
List < string > chosesAFaire = new List < string >
{
" Arroser les plantes " ,
" Tondre le gazon " ,
" Planter les tomates "
};
ListeDesTaches . ItemsSource = chosesAFaire ;
ListeDesTaches . SelectedValue = chosesAFaire [ 1 ];
ListeDesTaches . SelectionChanged +=
ListeDesTaches_SelectionChanged ;
}
Pour finir sur la slection dun lment, il faut savoir que la ListBox peut permettre
de slectionner plusieurs lments en changeant sa proprit SelectionMode et en la
passant Multiple :
1
179
En rsum
La ListBox est un contrle trs utile qui permet dafficher une liste dlments
trs facilement.
Il est possible de personnaliser efficacement le rendu de chaque lment dune
ListBox grce au systme de modles.
La ListBox est un contrle complet qui possde tout une gestion de llment
slectionn.
180
Chapitre
16
181
Principe du Databinding
Le databinding se traduit en franais par liaison de donnes . Il sagit de la possibilit de lier un contrle des donnes. Le principe consiste indiquer un contrle o il
peut trouver sa valeur et celui-ci se dbrouille pour lafficher. Nous lavons entre-aperu
dans le chapitre prcdent avec la ListBox, il est temps de creuser un peu son fonctionnement. Techniquement, le moteur utilise un objet de type Binding - http://msdn.
microsoft.com/fr-fr/library/system.windows.data.binding(v=vs.95).aspx qui
associe une source de donnes un lment de destination, do lemploi du mot raccourci binding pour reprsenter la liaison de donnes. Le binding permet de positionner
automatiquement des valeurs aux proprits des contrles en fonction du contenu de la
source de donnes. En effet, il est trs frquent de mettre des valeurs dans des TextBox,
dans des TextBlock ou dans des ListBox, comme nous lavons fait. Le binding est l
pour faciliter tout ce qui peut tre automatisable et risque derreurs. De plus, si la
source de donnes change, il est possible de faire en sorte que le contrle soit automatiquement mis jour. Inversement, si des modifications sont faites depuis linterface,
alors on peut tre notifi automatiquement des changements.
public MainPage ()
{
I nitializeComponent () ;
5
6
7
8
9
10
11
12
< TextBox Text = " { Binding Valeur } " Height = " 80 " / >
Cela se fait grce lexpression de balisage {Binding}. Lorsque nous excutons notre
application, nous pouvons voir que la TextBox sest correctement remplie avec la chane
de caractres Nicolas (voir la figure 16.1).
< TextBox Text = " { Binding Valer } " Height = " 80 " / >
183
< TextBox x : Name = " MonTextBox " Height = " 80 " / >
public MainPage ()
{
I nitializeComponent () ;
5
6
7
8
9
10
11
12
13
18
19
20
21
22
23
185
9
10
11
12
13
14
15
16
17
18
19
186
20
21
22
23
24
25
26
variable = valeur ;
N o t i f yPro pertyC hange d ( nomPropriete ) ;
return true ;
Relanons lapplication, nous pouvons voir que le clic sur le bouton entrane bien le
changement de valeur dans la TextBox.
Ok, cest bien beau tout a, mais nest-ce pas un peu compliqu par rapport
ce quon a dj fait, savoir modifier directement la valeur de la proprit
Text ?
Effectivement, dans ce cas-l, on pourrait juger que cest sortir lartillerie lourde pour
pas grand-chose. Cependant cest une bonne pratique dans la mesure o on automatise
le processus de mise jour de la proprit. Vous aurez remarqu que lon ne manipule
plus directement le contrle mais une classe qui na rien voir avec le TextBox. Et
quand il y a plusieurs valeurs mettre jour dun coup, cest dautant plus facile. De
plus, nous pouvons faire encore mieux avec ce binding grce la bidirectionnalit de la
liaison de donnes. Par exemple, modifions le XAML pour rajouter encore un bouton :
1
2
3
4
5
On utilise pour cela la mthode MessageBox.Show qui affiche une petite bote de dialogue minimaliste. Les lecteurs attentifs auront remarqu que jai enrichi le binding
sur la Valeur en rajoutant un Mode=TwoWay. Ceci permet dindiquer que le binding
seffectue dans les deux sens. Cest--dire que si je modifie la proprit de la classe
de contexte, alors linterface est mise jour. Inversement, si je modifie la valeur de la
187
188
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
variable = valeur ;
N o t i f yPro pertyC hange d ( nomPropriete ) ;
return true ;
26
public MainPage ()
{
I ni t i alizeComponent () ;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
La classe Contexte na plus de raison dtre. Tout est port par la classe reprsentant
la page. On affecte donc lobjet this la proprit DataContext de la page. Cette
construction est peut-tre un peu plus perturbante dun point de vue architecture
o on a tendance mlanger les responsabilits dans la classe mais elle a lavantage
189
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
variable = valeur ;
N ot ifyPro perty Change d ( nomPropriete ) ;
return true ;
26
public MainPage ()
{
I nitializeComponent () ;
27
28
29
30
31
32
33
34
Prenoms = new List < string > { " Nicolas " , " J r mie " , "
Delphine " };
DataContext = this ;
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Grid . ColumnDefinitions >
< ColumnDefinition Width = " * " / >
< ColumnDefinition Width = " * " / >
</ Grid . ColumnDefinitions >
< ListBox x : Name = " ListeBoxPrenoms " ItemsSource = " { Binding
Prenoms } " / >
< TextBlock Grid . Column = " 1 " Text = " { Binding ElementName =
ListeBoxPrenoms , Path = SelectedItem } " Foreground = " Red " / >
</ Grid >
Regardons lexpression de binding du TextBlock, nous indiquons que nous voulons lier la valeur du TextBlock la proprit SelectedItem du contrle nomm
ListeBoxPrenoms. Ici cela voudra dire que lorsque nous slectionnerons un lment
dans la ListBox, alors celui-ci sera automatiquement affich dans le TextBlock, sans
avoir rien dautre faire comme le montre la figure 16.4.
Tout simplement !
Voil pour cet aperu du binding. Nous nen avons pas vu toutes les subtilits mais ce
que nous avons tudi ici vous sera grandement utile et bien souvent suffisant dans vos
191
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< ListBox ItemsSource = " { Binding ListeDesTaches } " >
< ListBox . ItemTemplate >
< DataTemplate >
< StackPanel Orientation = " Horizontal " >
< Image Source = " { Binding Image } " Width = " 30 "
Height = " 30 " / >
< TextBlock Text = " { Binding Description } "
Margin = " 20 0 0 0 " / >
</ StackPanel >
</ DataTemplate >
</ ListBox . ItemTemplate >
192
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
variable = valeur ;
N o t i f yPro pertyC hange d ( nomPropriete ) ;
return true ;
26
27
28
29
public MainPage ()
{
I ni t i alizeComponent () ;
30
31
32
33
34
35
36
37
193
39
40
41
42
DataContext = this ;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Pour linstant, rien na chang, la ListBox est toujours vide en mode design. Sauf que
nous avons galement la possibilit de lier le mode design un contexte de design.
Crons donc une nouvelle classe :
1
2
3
4
5
6
7
8
9
10
11
194
12
13
14
15
16
}; ;
Cette classe ne fait que renvoyer une proprit ListeDesTaches avec des valeurs de
design. Compilez et rajoutez maintenant dans le XAML linstruction suivante avant le
conteneur de plus haut niveau :
1
2
3
Ceci permet de dire que le contexte de design est aller chercher dans la classe
MainPageDesign. Attention, la classe MainPageDesign nest pas connue de la page !
Il faut lui indiquer o elle se trouve, en indiquant son espace de nom, un peu
comme un using C#. Cette proprit se rajoute dans les proprits de la page,
<phone:PhoneApplicationPage> :
1
2
3
4
5
Avec cette criture, je lui dis que le raccourci design correspond lespace de nom
DemoPartie2.
Nous commenons voir apparatre des choses dans le designer de Visual Studio (voir
la figure 16.5).
Avouez que cest beaucoup plus pratique pour raliser le design de sa page.
Dans la mesure o le contexte de la page et le contexte de design doivent
contenir des proprits communes, cest une bonne ide de faire en sorte
quils implmentent tous les deux une interface qui contienne les proprits
implmenter des deux cts. . .
Avant de terminer, il faut savoir que Blend est galement capable de nous gnrer des
donnes de design sans que lon ait forcment besoin de crer une classe spcifique. Pour
illustrer ceci, repartez dune nouvelle page vide. Puis ouvrez la page dans Expression
Blend.
195
Figure 16.5 Le designer affiche les donnes de design grce la liaison de donnes
196
199
Figure 16.14 Une ListBox est automatiquement cre partir de la source de donnes
200
UTILISER LOBSERVABLECOLLECTION
Utiliser lObservableCollection
Avant de terminer sur la liaison de donnes, reprenons un exemple simplifi de notre
liste de taches. Avec le XAML suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " 100 " / >
</ Grid . RowDefinitions >
< ListBox ItemsSource = " { Binding ListeDesTaches } " >
< ListBox . ItemTemplate >
< DataTemplate >
< StackPanel Orientation = " Horizontal " >
< TextBlock Text = " { Binding Priorite } " Margin
= " 20 0 0 0 " / >
< TextBlock Text = " { Binding Description } "
Margin = " 20 0 0 0 " / >
</ StackPanel >
</ DataTemplate >
</ ListBox . ItemTemplate >
</ ListBox >
< Button Content = " Ajouter un l ment " Tap = " Button_Tap " Grid .
Row = " 1 " / >
</ Grid >
O nous affichons notre liste des tches avec la valeur de la priorit et la description
dans des TextBlock. Nous disposons galement dun bouton en bas pour rajouter un
nouvel lment. Le code behind sera :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
201
18
19
20
21
22
23
24
25
variable = valeur ;
N ot ifyPro perty Change d ( nomPropriete ) ;
return true ;
26
public MainPage ()
{
I nitializeComponent () ;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
DataContext = this ;
43
44
45
46
47
48
49
50
51
52
53
54
UTILISER LOBSERVABLECOLLECTION
nous ajoutons un nouvel lment la liste des taches, en utilisant la mthode Add()
de la classe List<>. Si nous excutons notre application et que nous cliquons sur
le bouton, un lment est rajout la liste, sauf que rien nest visible dans notre
ListBox. Problme !
Ah oui, cest vrai, nous navons pas inform la page que la ListBox devait se mettre
jour. Pour ce faire, il faudrait modifier lvnement de clic sur le bouton de cette faon :
1
2
3
List < ElementAFaire > nouvelleListe = new List < ElementAFaire >(
ListeDesTaches ) ;
nouvelleListe . Add ( new ElementAFaire { Priorite = 1 , Description
= " Faire marcher ce binding ! " }) ;
ListeDesTaches = nouvelleListe ;
Cest--dire crer une copie de la liste, ajouter un nouvel lment et affecter cette
nouvelle liste la proprit ListDesTaches. Ce qui devient peu naturel . . .
Cest parce que la liste nimplmente pas INotifyCollectionChanged qui permet denvoyer des vnements sur lajout ou la suppression dun lment dans une liste. Heureusement il existe une autre classe dans le framework .NET qui implmente dj ce
comportement, il sagit de la classe ObservableCollection - http://msdn.microsoft.
com/fr-fr/library/vstudio/ms668604(v=vs.95).aspx. Il sagit dune liste volue
prenant en charge les mcanismes de notification automatiquement lorsque nous faisons
un ajout la collection, lorsque nous supprimons un lment, etc. Changeons donc le
type de notre proprit de liaison :
1
2
3
4
5
6
Remarque
:
vous
devez
importer
System.Collections.ObjectModel.
lespace
de
nom
Ce qui est quand mme beaucoup plus simple. Plutt pratique cette
ObservableCollection. Elle nous simplifie normment la tche lorsquil sagit
de faire des oprations sur une collection et quun contrle doit tre notifi de ce
changement. Cest le complment idal pour toute ListBox qui se respecte. De plus,
203
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " 150 " / >
</ Grid . RowDefinitions >
< ListBox ItemsSource = " { Binding ListeDesTaches } " >
< ListBox . ItemTemplate >
< DataTemplate >
< StackPanel Orientation = " Horizontal " >
< TextBlock Text = " { Binding Priorite } " Margin
= " 20 0 0 0 " / >
< TextBlock Text = " { Binding Description } "
Margin = " 20 0 0 0 " / >
</ StackPanel >
</ DataTemplate >
</ ListBox . ItemTemplate >
</ ListBox >
< StackPanel Grid . Row = " 1 " >
< Button Content = " Ajouter un l ment " Tap = " Button_Tap "
/>
< Button Content = " Augmenter les priorit s " Tap = "
Button_Tap_1 " / >
</ StackPanel >
</ Grid >
204
UTILISER LOBSERVABLECOLLECTION
Sauf quaprs un clic sur notre bouton, on se rend compte que lObservableCollection
est mise jour mais pas la ListBox. . . Aarrrgghhhh ! Alors que notre
ObservableCollection tait cense rsoudre tous nos problmes de notification . . .
Cest l o il est important davoir compris ce quon faisait rellement . . . Ici, ce nest
pas la collection que lon a modifie (pas dajout, pas de suppression, . . .), mais bien
lobjet contenu dans la collection. Il doit donc implmenter INotifyPropertyChanged,
ce qui donne :
1
2
3
5
6
7
8
9
10
11
12
13
14
15
16
17
18
variable = valeur ;
N o t i f yPro pertyC hange d ( nomPropriete ) ;
return true ;
19
20
21
22
23
24
25
26
27
Les converters
Parfois, lorsque nous faisons des liaisons de donnes, la source de donnes ne correspond
pas exactement ce que nous souhaitons afficher ; la preuve juste au-dessus. Nous
voulions afficher une image dans une ListBox mais nous navions notre disposition
quun chiffre reprsentant une priorit. Pour y remdier, nous avions construit un objet
spcial avec directement les bonnes valeurs via la classe ElementAFaireBinding :
1
2
3
4
5
6
7
8
9
206
LES CONVERTERS
Cest une bonne faon de faire mais il existe une autre solution qui consiste appliquer
un convertisseur lors de la liaison de donnes. Appels converters en anglais, ils font
en sorte de transformer une donne en une autre, adapte ce que lon souhaite lier.
Un exemple sera plus clair quun long discours. Prenons par exemple le cas o lon
souhaite masquer une zone de lcran en fonction dune valeur. Laffichage / masquage
dun contrle, cest le rle de la proprit Visibility qui a la valeur Visible par
dfaut ; pour tre invisible, il faut que la valeur soit Collapsed :
1
2
3
4
5
6
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< StackPanel >
< TextBlock Text = " Je suis visible " Visibility = " Collapsed
" />
< Button Content = " Masquer / Afficher " Tap = " Button_Tap " / >
</ StackPanel >
</ Grid >
7
8
9
10
11
12
13
permet de remplacer :
1
2
3
4
5
Visibility v ;
if ( visibility )
v = Visibility . Visible ;
else
v = Visibility . Collapsed ;
Ce code doit tre prsent au mme niveau que le conteneur de base de la page, cest-dire lintrieur de la balise <phone:PhoneApplicationPage>.
Attention, la classe converter nest pas connue de la page, il faut ajouter un espace de
nom dans les proprits de la page : xmlns:converter="clr-namespace:DemoPartie2"
Il ne reste plus qu crer une proprit pour le binding dans notre classe :
1
2
3
4
5
6
Maintenant, nous devons indiquer le binding dans le XAML et que nous souhaitons
utiliser un converter, cela se fait avec :
1
< TextBlock Text = " Je suis visible " Visibility = " { Binding
TextBlockVisible , Converter ={ StaticResource
V is i b ilityConverter }} " / >
208
LES CONVERTERS
Nous lui indiquons ici que le converter est accessible en ressources par son nom :
VisibilityConverter. Noublions pas de donner la valeur initiale du boolen, par
exemple dans le constructeur, ainsi que dalimenter le DataContext :
1
2
3
4
5
6
public MainPage ()
{
I ni t i al i zeComponent () ;
TextBlockVisible = false ;
DataContext = this ;
}
Et voil, le fait de changer la valeur du boolen influe bien sur la visibilit du contrle,
comme vous pouvez le constater la figure 16.16.
En rsum
La liaison de donnes, binding en anglais, est un lment fondamental des applications XAML et permet dassocier une source de donnes un contrle.
209
210
Chapitre
17
MVVM
Difficult :
Passons maintenant MVVM. . . Si vous tes dbutants en XAML, je ne vous cache pas
que ce chapitre risque dtre difficile apprhender. Il sagit de concepts avancs quil nest
pas ncessaire de maitriser immdiatement. Au contraire, dune manire gnrale, il faut
dj pas mal de pratique avant de pouvoir utiliser les concepts prsents dans ce chapitre.
Mais nhsitez pas le lire quand mme et y revenir plus tard, cela vous sera toujours
utile.
Trs la mode, MVVM est un patron de conception (design pattern en anglais) qui sest
construit au fur et mesure que les dveloppeurs craient des applications utilisant le
XAML. MVVM signifie Model-View-ViewModel, nous allons dtailler son principe et son
fonctionnement dans ce chapitre.
211
213
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " auto " / >
</ Grid . RowDefinitions >
6
7
8
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " PageTitle " Text = " Fiche client "
Margin = "9 , -7 ,0 , 0 " Style = " { StaticResource
P honeTextTitle1Style } " / >
</ StackPanel >
10
215
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
On utilise les expressions de balisage pour indiquer les valeurs grce au binding.
Sauf quil est difficile de se rendre compte ainsi si la vue est bien construite, car
il nous manque les valeurs de design. Qu cela ne tienne, nous savons dsormais comment crer un contexte de design. Crons un nouveau rpertoire sous le
rpertoire ViewModel que nous appelons Design et une nouvelle classe sappelant
DesignVoirClientViewModel.cs qui contiendra les valeurs de design suivantes :
1
2
3
4
5
6
public class D e s i g n Vo i r C l i e n t V i ew M o d e l
{
public string Prenom
{
get { return " Nico " ; }
}
8
9
10
11
12
13
14
15
16
17
216
Ainsi, nous pourrons avoir en mode design le rsultat affich la figure 17.3.
9
10
11
12
13
14
15
16
17
18
217
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
variable = valeur ;
N ot ifyPro perty Change d ( nomPropriete ) ;
return true ;
Rien de sorcier, nous dfinissons galement les proprits Prenom, Age et BonClient.
Reste charger notre modle depuis notre view-model et affecter les proprits du
view-model partir des valeurs du modle :
1
2
3
4
5
6
7
8
9
10
11
12
Il nous manque une dernire chose, hautement indispensable, qui est de lier la vue au
view-model. Pour linstant, nous avons vu que nous pouvions le faire depuis le codebehind de la vue, avec :
1
2
3
218
4
5
6
7
8
I ni t i alizeComponent () ;
DataContext = new VoirClientViewModel () ;
Il y a une autre solution qui vite de passer par le code, en utilisant le XAML :
1
2
3
Revenons prsent un peu sur ce que nous avons fait. Nous avons cr une vue, la
page XAML, lie lexcution au view-model VoirClientViewModel et lie en design
au pseudo view-model DesignVoirClientViewModel. Le pseudo view-model de design
expose des donnes en dur, pour nous permettre davoir des donnes dans le designer
alors que le view-model utilise et transforme le model pour exposer les mmes donnes.
Une bonne pratique ici serait de dfinir une interface avec les donnes exposer et
que nos deux view-models limplmentent. Crons donc un rpertoire Interface dans le
rpertoire ViewModel et crons linterface IVoirClientViewModel :
1
2
3
4
5
6
Et :
1
2
3
4
5
6
7
219
9
10
11
12
13
14
15
16
17
18
19
20
Vous aurez remarqu que nous avons rajout le mutateur set dans le view-model de
design, et quelle na besoin de rien faire.
Nous pouvons encore faire une petite amlioration. Ici, elle est mineure car nous navons
quun seul view-model, mais elle sera intressante ds que nous en aurons plusieurs.
En effet, chaque view-model doit implmenter linterface INotifyPropertyChanged et
avoir le code suivant :
public event P r o p e r t y C h a n g e d E v e n t H a n d l e r PropertyChanged ;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
variable = valeur ;
N o t i f yPro perty Change d ( nomPropriete ) ;
return true ;
Nous pouvons factoriser ce code dans une classe de base dont vont driver tous les
view-models. Crons pour cela un rpertoire FrameworkMvvm et dedans, mettons-y la
classe ViewModelBase :
1
2
3
4
5
6
220
LES COMMANDES
7
8
if ( PropertyChanged != null )
PropertyChanged ( this , new P ro p e rt y C ha n g ed E v en t A rg s (
nomPropriete ) ) ;
10
11
12
13
14
15
16
17
18
19
variable = valeur ;
N o t i f yPro pertyC hange d ( nomPropriete ) ;
return true ;
Les commandes
Bon, cest trs bien tout a, mais nous navons fait quune partie du chemin. . . MVVM
ce nest pas que du binding avec une sparation entre la vue et les donnes. Il faut tre
capable de faire des actions. Imaginons que nous souhaitions charger les donnes du
client suite un appui sur un bouton. Avant MVVM, nous aurions utilis un vnement
sur le clic du bouton, puis nous aurions charg les donnes dans le code-behind et nous
les aurions affiches sur notre page. Avec notre dcoupage, le view-model nest pas
au courant dune action sur linterface, car cest un fichier part. Il nest donc pas
directement possible de raliser une action dans le view-model lors dun clic sur le
bouton. On peut rsoudre ce problme dune premire faon trs simple mais pas tout
fait parfaite. Crons tout dabord un bouton dans notre XAML :
1
2
3
4
5
6
7
8
9
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
Background = " { Binding BonClient } " >
< Grid . RowDefinitions >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " auto " / >
</ Grid . RowDefinitions >
< Grid . ColumnDefinitions >
< ColumnDefinition Width = " * " / >
< ColumnDefinition Width = " * " / >
221
10
11
12
13
14
15
16
Voyons prsent comment rsoudre simplement ce problme. Il suffit dutiliser lvnement Tap et de faire quelque chose comme ceci dans le code-behind de la page, dans
la mthode associe lvnement de clic :
1
2
3
4
5
6
7
8
9
10
11
12
8
9
10
11
12
13
14
15
16
17
18
222
LES COMMANDES
19
20
21
get { return 30 ; }
set { }
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public V o irClientViewModel ()
{
}
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Vous pouvez tester cette solution, cela fonctionne. Cependant, elle est imparfaite car
cela cre un couplage entre la vue et le view-model, cest--dire que la vue connait
linstance du view-model car cest effectivement elle qui linstancie avec la dclaration
que nous avons vue dans le XAML. Mais bien quimparfaite, ncartez pas non plus
compltement cette solution de votre esprit, elle reste bien pratique et ne rajoute pas
tant de code que a dans la vue (de plus, ce code ne fait pas de traitement, il fonctionne
juste comme un relai du traitement).
223
< Button Grid . Row = " 2 " Grid . ColumnSpan = " 2 " Content = " Charger
client " Tap = " Button_Tap " / >
par :
1
< Button Grid . Row = " 2 " Grid . ColumnSpan = " 2 " Content = " Charger
client " Command = " { Binding ChargerClientCommand } " / >
Ici, nous avons enlev lvnement Tap et la mthode associe (vous pouvez donc supprimer cette mthode dans le code behind) pour la remplacer par un binding dune
commande. Cette commande devra tre dfinie dans le view-model :
public ICommand ChargerClientCommand { get ; private set ; }
Elle sera du type ICommand et videmment en lecture seule afin que seul le viewmodel puisse instancier la commande. Cette commande doit ensuite tre relie une
mthode et pour faire cela, nous allons utiliser un dlgu et plus particulirement
un dlgu de type Action. Crons donc une classe qui implmente ICommand et qui
associe la commande une action. Nous pouvons placer cette classe dans le rpertoire FrameworkMvvm et la nommer RelayCommand (ce nom nest pas choisi au hasard,
vous verrez plus loin pourquoi). Linterface ICommand impose de dfinir la mthode
CanExecute qui permet dindiquer si la commande peut tre excute ou non. Nous
allons renvoyer vrai dans tous les cas pour cet exemple. Elle oblige galement dfinir un vnement CanExecuteChanged que nous nallons pas utiliser et une mthode
Execute qui appellera la mthode associe la commande. La classe RelayCommand
pourra donc tre :
1
2
3
4
5
6
7
8
224
10
11
12
13
14
15
16
17
18
19
20
21
Ce qui fait que nous allons pouvoir instancier un objet du type RelayCommand que
nous stockerons dans la proprit ChargerClientCommand dans notre view-model, par
exemple depuis le constructeur :
1
2
3
4
public V o ir C l ientViewModel ()
{
C h a r g e r C l ientCommand = new RelayCommand ( ChargeClient ) ;
}
Installation du toolkit
Voyons prsent comment crer une application MVVM Light. Nous allons installer la dernire version stable du framework lheure o jcris ces lignes, savoir la
version 4.1.25. Le plus simple pour tlcharger les bibliothques est de passer par NuGet, qui est un gestionnaire de package .NET open source permettant de tlcharger
des bibliothques externes trs facilement. Pour cela, allez dans le menu outils, puis
gestionnaire de package de bibliothques, puis Grer les packages NuGet pour la
solution, comme indiqu la figure 17.4.
Vous arrivez dans NuGet o vous allez pouvoir cliquer sur En ligne gauche et commencer rechercher le MVVM Light Toolkit (voir la figure 17.5).
226
227
Vous pouvez voir que dans votre projet, les assemblys suivantes ont automatiquement
t rfrences :
228
GalaSoft.MvvmLight.Extras.WP8.dll
GalaSoft.MvvmLight.WP8.dll
Microsoft.Practices.ServiceLocation
System.Windows.Interactivity.dll
sachant que la dernire est une assembly de Blend et que lavant dernire permet
dutiliser le service locator.
Recrez alors un rpertoire View pour y mettre votre page VoirClientView.xaml,
un rpertoire Model avec la classe Client et un rpertoire ViewModel avec une classe
VoirClientViewModel. La classe Client est la mme que prcdemment, le service
aussi. Nous allons simplement lui rajouter une interface en plus :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Puis nous allons rajouter une classe de design pour notre service. Au contraire de ce
que nous avons fait dans le chapitre prcdent, ce nest pas ici le view-model qui sera
en mode design, mais le model :
1
2
3
4
5
6
7
Ici, la classe ServiceClient et la classe DesignServiceClient sont identiques, mais dans une vraie application, la classe ServiceClient irait
srement chercher les donnes en base ou autre. . .
229
1
2
3
4
5
Le service locator
Il est temps de crer le service locator afin de bnficier dun couplage faible entre
notre vue et le view-model, mais galement entre le view-model et le service, ce qui
nest pas indispensable mais ne fait pas de mal. Pour cela, crons une nouvelle classe
ViewModelLocator, je la place la racine du projet :
1
2
3
4
5
if ( ViewModelBase . IsInDesignModeStatic )
SimpleIoc . Default . Register < IServiceClient ,
DesignServiceClient >() ;
else
SimpleIoc . Default . Register < IServiceClient ,
ServiceClient >() ;
7
8
9
10
11
12
13
14
15
16
17
18
19
Noubliez
pas
dimporter
les
espaces
de
nom
Microsoft.Practices.ServiceLocation, GalaSoft.MvvmLight.Ioc et
GalaSoft.MvvmLight.
Elle contient un constructeur statique qui soccupe de linversion de dpendance en ellemme, savoir associer le service client de design avec linterface lorsquon est en mode
design, et le vrai service sinon. De mme, il enregistre une instance du view-model. Il
230
3
4
5
< vm : ViewModelLocator x : Key = " Locator " d : IsDataSource = " true "
/>
</ Application . Resources >
xmlns : mc = " http :// schemas . openxmlformats . org / markup compatibility / 2006 "
xmlns : d = " http :// schemas . microsoft . com / expression / blend / 2008 "
mc : Ignorable = " d "
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " auto " / >
</ Grid . RowDefinitions >
231
7
8
9
10
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
Background = " { Binding BonClient } " >
< Grid . RowDefinitions >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " auto " / >
</ Grid . RowDefinitions >
< Grid . ColumnDefinitions >
< ColumnDefinition Width = " * " / >
< ColumnDefinition Width = " * " / >
</ Grid . ColumnDefinitions >
< TextBlock Text = " Pr nom : " / >
< TextBlock Grid . Column = " 1 " Text = " { Binding Prenom } " / >
< TextBlock Grid . Row = " 1 " Text = " Age : " / >
< TextBlock Grid . Column = " 1 " Grid . Row = " 1 " Text = " { Binding
Age } " / >
</ Grid >
</ Grid >
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
232
24
25
26
27
28
29
30
31
32
33
variable = valeur ;
R a i s e PropertyChanged ( nomPropriete ) ;
return true ;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Rajoutons une nouvelle vue dans le rpertoire View que nous allons appeler ListeClientsView.x
Et enfin, crons un nouveau view-model que nous appellerons ListeClientsViewModel
et qui hritera de ViewModelBase. Noubliez pas de dclarer le nouveau view-model
dans le locator :
1
2
3
4
5
6
7
234
if ( ViewModelBase . IsInDesignModeStatic )
else
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
6
7
8
9
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< ListBox ItemsSource = " { Binding ListeClients } " >
< ListBox . ItemTemplate >
< DataTemplate >
< Button Content = " Qui suis - je ? " Command = " {
Binding QuiSuisJeCommand } " CommandParameter =
" { Binding } " / >
</ DataTemplate >
</ ListBox . ItemTemplate >
</ ListBox >
</ Grid >
Le code XAML prcdent contient volontairement une erreur que nous corrigerons un peu plus loin.
Nous voyons que notre ListBox est lie une proprit ListeClients qui devra tre
prsente dans notre view-model. Le bouton prsent dans le template possde une commande lie la commande QuiSuisJeCommand. Remarquons la proprit CommandParameter
qui permet de positionner llment en cours comme paramtre de la commande. Liez
ensuite le view-model la vue en modifiant la proprit Datacontext avec notre nouvelle proprit dans le locator :
1
235
10
11
12
13
14
15
16
17
variable = valeur ;
R aisePropertyChanged ( nomPropriete ) ;
return true ;
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Nous avons cr la proprit ListeClients que nous avons alimente dans le constructeur grce au modle. Puis nous voyons comment dfinir une commande qui accepte
un paramtre. En loccurrence, ici le paramtre sera du type Client car cest le type
que nous passons dans :
1
Lextension de balisage {Binding} prend ici llment courant de la proprit numrable ListeClients qui est bien de type Client. Une fois le bouton cliqu, nous
pourrons alors afficher le client slectionn grce la boite de message MessageBox.
Vrifions cela en dmarrant lapplication. Noubliez pas de changer le point dentre de lapplication dans le fichier WMAppManifest.xml afin quil dmarre sur la vue
236
237
Remarquez que jai aussi chang le type gnrique de RelayCommand pour avoir un
ClientBinding vu que dsormais, cest un objet de ce type qui est li au paramtre
de la commande. Ce qui implique galement de changer le type du paramtre de la
mthode QuiSuisJe() :
1
2
3
4
< Button Content = " Qui suis - je ? " Command = " { Binding ViewModel .
QuiSuisJeCommand } " CommandParameter = " { Binding } " / >
Et voil, cela fonctionne. Mais cela implique pas mal de changement. . . Lautre solution
est de lier directement la proprit Command la proprit QuiSuisJeCommand de la
proprit du locator pour accder au view-model. Plus besoin de classe intermdiaire
qui contient une rfrence vers le view-model. Il suffit dcrire :
1
< Button Content = " Qui suis - je ? " Command = " { Binding Source ={
StaticResource Locator } , Path = ListeClientsVM .
QuiSuisJeCommand } " CommandParameter = " { Binding } " / >
Et le rsultat est le mme, ainsi que vous pouvez le constater sur la figure 17.7.
Pouvoir passer un paramtre une commande est trs pratique dans ce genre de situation. La classe RelayCommand du toolkit nous aide bien pour rcuprer ce paramtre,
que lon retrouve en paramtre de la mthode QuiSuisJe(). Elle sait faire encore une
chose intressante, savoir de permettre de savoir si la commande est utilisable ou
pas. Rappelez-vous, cest ce que nous avions vu plus haut. Il sagissait de la mthode
CanExecute de linterface ICommand. Javais dcid arbitrairement que cette mthode
renverrait toujours vrai. La classe RelayCommand de MVVM Light permet dassocier
une condition la possibilit dexcuter une commande. Par exemple, on pourrait imaginer quon ne puisse cliquer sur le bouton que des clients qui sont des bons clients. Cest
de la sgrgation, mais cest comme a. Les mauvais clients resteront inconnus ! Pour
ce faire, on utilisera le deuxime paramtre du constructeur de la classe RelayCommand
qui permet de dfinir une mthode qui servira de prdicat permettant dindiquer si la
commande peut tre excute ou non. Ici, nous aurons simplement besoin de renvoyer la
valeur du boolen EstBonClient, mais cela pourrait tre une mthode plus complexe.
Notre instanciation de commande devient donc :
1
238
Ainsi, non seulement il ne sera pas possible dexcuter la commande en cliquant sur le
bouton, mais le bouton est galement gris, signe de son tat dsactiv (voir la figure
17.8).
Plutt pratique quand un bouton doit tre dsactiv. Juste avant de terminer ce point,
remarquons que le prdicat associ la possibilit dexcution dune commande est
excut une unique fois. Si jamais notre client venait devenir un bon client, notre
bouton resterait dans un tat dsactiv car il naura pas t mis au courant de ce
changement. ce moment-l, MVVM Light fournit une mthode qui permet ce
prdicat de se rvaluer et ainsi modifier ventuellement ltat du bouton. Il sagit de
la mthode RaiseCanExecuteChanged. On pourra lutiliser ainsi :
1
Continuons cet aperu de MVVM Light et de ses commandes en vous indiquant comment relier nimporte quel vnement une commande. Par exemple, lvnement de
239
Figure 17.8 Le bouton est gris quand la commande nest pas utilisable
slection dun lment dans une ListBox. Premire chose faire, modifier ma vue pour
ne plus avoir ce bouton, mais simplement pour avoir le prnom du client afin quil soit
facilement slectionnable :
1
2
3
4
5
6
7
Avant, pour savoir quand un lment dun ListBox est slectionn, on se serait abonn
lvnement SelectionChanged. Grce MVVM Light, on peut utiliser laction
EventToCommand :
1
2
3
4
240
Le XAML est un peu plus verbeux, je vous le concde. Le principe est dutiliser les
triggers de Blend qui correspondent au dclenchement dun vnement, de prciser
lvnement choisi dans la proprit EventName et on pourra alors se brancher sur
nimporte quel vnement, ici lvnement SelectionChanged.
Reste dfinir la commande dans le view-model :
1
Ceci fait partie dun problme plus gnral, savoir : comment faire pour que le viewmodel puisse agir sur la prsentation part en utilisant les mcanismes du binding ?
La navigation se retrouve exactement dans ce cas-l. Cest le code-behind qui aurait
normalement pris en charge cette navigation, sauf que l, cest impossible. On retrouve
un cas similaire lorsque lon cherche afficher une boite de dialogue, autre que la
MessageBox.
MVVM Light propose une solution pour rsoudre cet pineux problme travers son
systme de messagerie. Ce systme offre la possibilit de pouvoir communiquer de
manire dcouple entre un view-model et sa vue ou entres view-models. Le principe
est que lmetteur envoie un message au systme de messagerie, qui le diffuse ceux qui
sy sont abonn. Dans notre cas, il faut donc que le code-behind sabonne au message :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Cela se fait grce la mthode Register du Messenger, qui se trouve dans lespace
de nom GalaSoft.MvvmLight.Messaging. On indique que lon sabonne aux messages
qui prendront un client en paramtre et que dans ce cas, la mthode AfficheClient
est appele. La mthode AfficheClient fait une navigation toute simple, comme on
la dj vu.
Il faut maintenant que le view-model mette le message, mais avant a, nous allons
ajouter une liaison de donnes pour rcuprer llment slectionn de la ListBox.
Remarque, on pourrait le faire avec la valeur de largument, mais cest plus propre
de faire comme a. Donc changeons notre ListBox pour avoir la liaison sur llment
slectionn :
1
242
Rsumons.
Pour terminer proprement la petite application, il faudrait que la vue qui affiche un
client utilise les donnes positionnes dans le dictionnaire dtat. Alors, comment feriezvous ?
Il y a plusieurs solutions, je vous propose la plus simple. Nous allons profiter quun
message est diffus chaque slection dun lment pour mettre jour les proprits
du view-model :
1
2
3
4
5
6
public V o ir C l ientViewModel ()
{
Messenger . Default . Register < Client >( this , MetAJourClient ) ;
Client client = ( Client ) P ho ne A pp li c at io nS e rv ic e . Current .
State [ " Client " ];
MetAJourClient ( client ) ;
}
7
8
9
10
11
12
13
14
15
243
Voil pour ce petit tour de MVVM Light. Nous avons vu lessentiel de ce toolkit qui
propose des solutions pour aider la mise en place du patron de conception MVVM.
Noubliez pas que malgr sa dnomination de light, cest un framework complet qui
prend sa place (110 ko). Il est en fait light par rapport dautres framework, comme
PRISM qui est utilis avec WPF. A utiliser en connaissance de cause.
Calcium - http://calcium.codeplex.com/
Caliburn Micro - http://caliburnmicro.codeplex.com/
Catel - http://catel.codeplex.com/
nRoute - http://nroute.codeplex.com/
Simple MVVM Toolkit - http://simplemvvmtoolkit.codeplex.com/
UltraLight.mvvm - http://ultralightmvvm.codeplex.com/
Je ne peux pas bien sur tous les prsenter et dailleurs je ne les ai pas tous tests :-
. Jaime bien lUltraLight.mvvm qui, via son locator, offre une liaison avec la page ce
qui permet facilement de dmarrer une navigation sans passer par lutilisation dune
messagerie. Nhsitez pas les tester pour vous faire votre propre opinion et pour vous
permettre de voir ce que vous souhaitez garder de MVVM et ce dont vous pouvez vous
passer.
244
En rsum
MVVM est un patron de conception qui aide la ralisation dapplications
denvergure utilisant le XAML.
Des frameworks gratuits nous aident la mise en place de ce patron de conception en fournissant des bibliothques remplies de classes prouves.
Le respect et lutilit de MVVM se dcouvrent en pratiquant. Ne soyez pas
forcment trop presss de respecter parfaitement MVVM.
245
246
Chapitre
18
247
Pressed
Disabled
Normal
MouseOver
chaque tat donc son apparence. . . ce qui implique que nous pouvons modifier les
apparences de chaque tat via des templates que nous allons dfinir dans un style.
Pour comprendre, le plus simple est dutiliser Blend. Ajoutons un bouton dans notre
XAML :
1
2
3
4
5
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< StackPanel >
< Button x : Name = " But " Content = " Cliquez - moi ! " / >
</ StackPanel >
</ Grid >
Puis dmarrons Blend en faisant un clic droit sur le projet, puis ouvrir dans expression
blend. Une fois ouvert, cliquez sur le bouton pour le slectionner et faites un clic droit
pour modifier une copie du modle, comme indiqu la figure 18.4.
Cela permet de crer un style automatiquement (voir la figure 18.5).
249
250
251
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
252
48
49
50
51
52
53
54
55
56
57
58
59
60
61
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
62
63
64
65
66
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12
, 17 ,0 , 28 " >
< TextBlock Text = " MON APPLICATION " Style = " {
StaticResource PhoneTextNormalStyle } " Margin = " 12
,0"/>
< TextBlock Text = " nom de la page " Margin = "9 , -7 ,0 , 0 "
Style = " { StaticResource PhoneTextTitle1Style } " / >
</ StackPanel >
67
68
69
70
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 ,
12 , 0 " >
< StackPanel >
< Button x : Name = " But " Content = " Cliquez - moi ! "
Style = " { StaticResource ButtonStyle1 } " / >
253
71
72
73
74
Beaucoup de choses, mais ce quil faut regarder prcisment cest que Blend a dclar
un nouveau template du bouton, celui-ci est simplement :
1
254
MODIFIER UN TAT
16
17
Ce quon peut voir cest que les tats dfinissent une animation qui permet de changer
la valeur de certaines proprits lorsque le contrle change dtat. Par exemple, en
passant ltat Pressed, nous pouvons constater que la proprit Foreground passe
la valeur de PhoneButtonBasePressedForegroundBrush.
Voil comment sont dfinis les tats, dans des modles.
Modifier un tat
Ceci nous permet de faire ce que nous voulons avec les tats des contrles afin damliorer le look de nos boutons. Rappelez-vous dans la premire partie, nous avions modifi
lapparence dun bouton en modifiant sa proprit Content :
1
2
3
4
5
6
7
8
Comme on peut sen rendre compte maintenant que nous avons vu le modle original du
contrle, nous navons modifi que ce qui correspondait au contenu du ContentControl.
Le cadre est donc conserv, mais plus encore, la mme animation sur le fond du cadre
existe toujours. Ceci ne correspond peut-tre pas ce que nous souhaitons avoir lorsque
le bouton est cliqu. En loccurrence, moi ce que je voudrais, cest que le rond rouge
devienne vert et que le texte passe cliqu . Pour cela, il suffit de modifier le template
de ltat Pressed de notre contrle. . . Reprenons donc notre bouton :
1
< Button x : Name = " But " Content = " Cliquez - moi ! " Style = " {
StaticResource ButtonStyle1 } " / >
255
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Vous pouvez voir que jai modifi lapparence du contrle pour quil contienne notre
image et notre texte :
1
256
MODIFIER UN TAT
2
3
4
5
6
Puis, dans ltat Pressed, jai anim les proprits Source de limage et Text du
TextBlock pour charger une nouvelle image et changer le texte :
1
2
3
4
5
6
7
8
9
10
Bien sr, il faudra rajouter les images rouge.png et vert.png la solution. De la mme
faon, dans ltat Disabled, jai chang la visibilit de limage pour la faire disparaitre,
puis jai anim le texte pour le changer :
1
2
3
4
5
6
7
8
9
10
< Button x : Name = " But " Content = " Cliquez - moi ! " Style = " {
StaticResource ButtonStyle1 } " / >
Qui, lorsquil est au repos, ressemble ce que vous pouvez voir sur la figure 18.7.
Changer dtat
Bon. . . javoue ! Dans le chapitre prcdent jai trich ! Mais ne le dites personne. Pour
faire mes copies dcrans, je nai pas cherch appuyer sur la touche de copie dcran
tout en maintenant le clic sur le bouton. . . trop compliqu, je fais attention ltat. . .
de mes doigts. :- Jai donc pour loccasion chang ltat du bouton par code. Et oui,
il ny a pas que les actions de lutilisateur qui peuvent changer ltat dun contrle. Il
est trs simple de changer ltat dun contrle avec une ligne de code. On utilise pour
cela le VisualStateManager - http://msdn.microsoft.com/fr-fr/library/system.
258
CHANGER DTAT
7
8
9
10
11
12
13
14
15
16
17
18
19
Ici, jai simplement choisi de rduire la taille de la proprit Width du contrle Border
afin de rduire la taille du bouton. Le voici la figure 18.10 donc dans un tat Pressed
et TailleReduite.
Pour obtenir cela, dans le XAML, jaurai toujours mon bouton, mais jai galement
rajout une case cocher pour pouvoir positionner ltat rduit :
1
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
260
2
3
4
5
6
5
6
7
8
9
261
En rsum
Un contrle peut possder plusieurs tats, comme un bouton qui peut tre cliqu
ou non cliqu.
chaque tat est associe une reprsentation visuelle diffrente, quil est possible
de modifier grce aux templates.
Il est possible de crer un nouvel tat ou un nouveau groupe dtat pour un
contrle.
On change un tat par code grce la classe VisualStateManager.
Blend peut se rvler trs utile dans la cration ou la modification dtats.
262
Chapitre
19
263
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
264
< TextBlock x : Name = " Resultat " TextWrapping = " Wrap " / >
public MainPage ()
{
I ni t i alizeComponent () ;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Figure 19.2 Envoi dun formulaire POST une page PHP et affichage du retour
Ici, le retour est du HTML, ce qui est normal vu que ce formulaire a t prvu pour
une page web. Il aurait pu tre judicieux dinterprter le rsultat, en retirant les balises
HTML par exemple. . .
Attention, un tlchargement fait avec HttpWebRequest sexcute sur un
thread en arrire-plan, cela veut dire que si nous voulons mettre jour linterface, nous aurons besoin dutiliser le dispatcher pour re-basculer sur le thread
de linterface.
Cest ce que nous avons fait ici avec :
1
6
7
8
9
10
TemperatureService . C o n v e r t T e m p e r a t u r e S o a p C l i e n t client
= new TemperatureService .
C o n v e r t T e m p e r a t u r e S o a p C l i e n t () ;
client . ConvertTempCompleted +=
client_ConvertTempCompleted ;
client . ConvertTempAsync ( 25 , TemperatureService .
TemperatureUnit . degreeCelsius , TemperatureService .
TemperatureUnit . degreeFahrenheit ) ;
11
12
13
14
15
16
17
18
19
Linq-To-Json
Parlons prsent un peu des services REST. Je ne prsenterai pas comment faire
un appel REST parce que vous savez dj le faire, dans la mesure o il sagit dune
simple requte HTTP. Par contre, ce quil est intressant dtudier ce sont les solutions pour interprter le rsultat dun appel REST. De plus en plus, les services REST
renvoient du JSON car cest un format de description de donnes beaucoup moins
verbeux que le XML. .NET sait interprter le JSON mais malheureusement lassembly Silverlight System.Json.dll nest pas porte pour Windows Phone. Nous pouvons quand mme lutiliser mais cest nos risques et prils. Elle a t installe avec
le SDK de Silverlight, chez moi cet emplacement : C:\Program Files\Microsoft
SDKs\Silverlight\v4.0\Libraries\Client\System.Json.dll.
Cette assemby nous permet de faire du Linq To Json et davoir accs aux objets JsonObject - http://msdn.microsoft.com/fr-fr/library/system.json.jsonobject(v=vs.
95).aspx et JsonArray - http://msdn.microsoft.com/fr-fr/library/system.json.
jsonarray(v=vs.95).aspx. Lorsque vous allez rfrencer cette assembly, vous aurez
le message davertissement prsent dans la figure 19.6 :
270
LINQ-TO-JSON
271
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
272
LINQ-TO-JSON
Le format JSON est relativement comprhensible lil nu, mais sa lecture fait un peu
mal aux yeux. Nous pouvons quand mme dcrypter que le rsultat contient une srie de
valeurs correspondant la recherche. Construisons une mini application qui effectuera
le tlchargement des donnes, vous savez faire, on utilise la classe WebClient :
1
2
3
4
5
6
7
8
10
11
12
13
14
15
16
17
18
Nous allons pouvoir obtenir un objet JsonObject grce la mthode statique Parse.
Le JsonObject est en fait une espce de dictionnaire o nous pouvons accder des
valeurs partir de leur cl. Par exemple, vous pouvez voir que le json rcupr possde
la proprit responseData qui contient une sous proprit cursor, contenant ellemme la proprit resultCount fournissant le nombre de rsultats de la requte. Nous
pouvons y accder de cette faon :
1
2
Dans ce cas, chaque JsonObject renvoie un nouvel JsonObject qui est lui-mme toujours cette espce de dictionnaire. En effet, responseData, cursor et resultCount
sont des proprits simples. Ce nest pas le cas par contre de la proprit results qui
est un tableau. On utilisera alors un JsonArray pour pouvoir le parcourir. Et cest l
que Linq To Json rentre en action, nous allons pouvoir requter sur ce tableau. Par
exemple :
1
2
3
List < string > resultats = new List < string >() ;
JsonObject json = ( JsonObject ) JsonObject . Parse ( e . Result ) ;
string nombreResultat = json [ " responseData " ][ " cursor " ][ "
resultCount " ];
273
var listeResultat =
from resultat in ( JsonArray ) ( json [ " responseData " ][ "
results " ])
where (( string ) resultat [ " content " ]) . IndexOf ( " cours " ,
StringComparison . C u rr e n tC u l tu r e Ig n o re C a se ) >= 0
select resultat ;
8
9
10
11
12
Ici, je rcupre les titres de chaque rsultats dont le contenu contient le mot cours, sans
faire attention la casse. Ainsi, avec une ListBox :
1
LINQ-TO-JSON
6
7
8
9
10
11
275
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
que nous pouvons inclure dans notre projet. Ces classes reprsentent exactement le
rsultat de la requte sous la forme de plusieurs objets. Il ne reste plus qu faire un
appel web comme on la vu :
1
2
3
4
5
6
7
public MainPage ()
{
I ni t i alizeComponent () ;
WebClient client = new WebClient () ;
client . D ow n lo ad St r in gC om p le te d +=
client_DownloadStringCompleted ;
client . DownloadStringAsync ( new Uri ( " http :// ajax . googleapis .
com / ajax / services / search / web ? v = 1 . 0 & q = openclassrooms " ) ) ;
}
8
9
10
11
12
13
276
LA BIBLIOTHQUE DE SYNDICATION
14
15
16
La bibliothque de Syndication
Maintenant que nous savons rcuprer des donnes depuis internet, pourquoi ne pas
essayer den faire quelque chose dun peu intressant ? Comme un lecteur de flux RSS
par exemple. . . Vous connaissez sans doute tous le RSS - http://fr.wikipedia.org/
wiki/RSS, cest ce format qui nous permet de nous abonner nos blogs favoris afin
dtre avertis des nouveaux articles publis. Le flux RSS est produit sous forme de XML
standardis, contenant des informations sur le nom du site, les billets qui le composent,
le titre du billet, la description, etc. Le site OpenClassrooms possde bien videmment
des flux RSS, comme le flux dactualit de son blog disponible cet emplacement :
http://www.simple-it.fr/blog/feed/. Si vous naviguez sur ce lien, vous pouvez
facilement voir le titre du site, la description, ainsi que les diffrentes actualits ; et
tout a au format XML.
Prenons un autre site pour lexemple, le blog de lquipe Windows Phone. Le flux
RSS est accessible via cette page : http://blogs.windows.com/windows_phone/b/
windowsphone/rss.aspx.
Vous savez dj rcuprer du XML grce la classe WebClient. Je vais en profiter
pour vous communiquer une petite astuce dont je nai pas parl dans les chapitres
prcdents. Il est possible de fournir un objet de contexte la requte de tlchargement
et ainsi pouvoir utiliser la mme mthode pour lvnement de fin de tlchargement
et identifier ainsi diffrentes requtes. Il suffit de lui passer en paramtre de lappel la
mthode DownloadStringAsync. Cet objet de contexte sera rcupr dans lvnement
de fin de tlchargement, dans la proprit UserState de lobjet rsultat :
1
2
277
3
4
public MainPage ()
{
I nitializeComponent () ;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
}
if (( string ) e . UserState == " WP " )
{
// ce sont les donn es venant du flux blog de l
' quipe windows phone
}
Ceci nous permettra dutiliser la mme mthode pour lvnement de fin de tlchargement. Nous avons maintenant besoin dinterprter les donnes du flux XML retourn.
tant donn que les flux RSS sont standards, il existe une bibliothque Silverlight qui
permet de travailler avec ce genre de flux. Cest la bibliothque System.ServiceModel.Syndicati
Encore une fois, cette assembly na pas t crite pour Windows Phone, mais elle est
quand mme utilisable avec nos applications Windows Phone. Pour lutiliser, nous
devons ajouter une rfrence celle-ci. Elle se trouve dans le rpertoire suivant :
C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries\Client.
Comme pour System.Json.dll, vous aurez une boite de dialogue davertissement o
vous pouvez cliquer sur Oui (voir la figure 19.9).
Nous allons donc pouvoir charger lobjet de Syndication partir du rsultat, cet ob278
LA BIBLIOTHQUE DE SYNDICATION
lors
de
la
rfrence
Sys-
9
10
11
12
13
14
15
16
17
}
if (( string ) e . UserState == " WP " )
{
// ce sont les donn es venant du flux blog de l '
quipe windows phone
AjouteFlux ( e . Result ) ;
}
279
20
21
22
23
24
25
26
27
Il nous faudra lier la proprit ItemsSource de la ListBox , par exemple une ObservableCollec
que nous construisons une fois le dernier flux reu, et qui sera trie par ordre de date
de publication de la plus rcente la plus ancienne :
1
2
3
4
5
280
ASYNCHRONISME AVANC
6
7
8
9
10
11
12
13
14
Asynchronisme avanc
Bon, cest trs bien les mthodes asynchrones, mais cest une gymnastique un peu
complique. On sabonne un vnement de fin de tlchargement puis on dmarre
le tlchargement et quand le tlchargement est termin, on exploite le rsultat dans
une autre mthode perdant au passage le contexte de lappel. Alors oui. . . il y a des
281
public MainPage ()
{
I ni t i alizeComponent () ;
4
5
6
7
9
10
11
12
13
14
15
16
17
18
19
20
21
282
ASYNCHRONISME AVANC
Commenons par utiliser la classe TaskCompletionSource - http://msdn.microsoft.
com/fr-fr/library/vstudio/dd449174.aspx dans une mthode dextension :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
webClient . Do wn l oa dS tr i ng Co mp l et ed +=
d o wn l o ad C o mp l e te d H an d l er ;
webClient . DownloadStringAsync ( uri ) ;
16
17
18
19
20
21
public MainPage ()
{
I ni t i al i zeComponent () ;
L a n c e T e l e c ha r g em e n tA s y nc () ;
}
6
7
8
9
10
11
12
public MainPage ()
{
I ni t i alizeComponent () ;
4
5
6
L a n c e L e T e l e c h a r g e m e n t A s y n c () ;
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
284
LE RPERTOIRE LOCAL
Le rpertoire local
Il nest pas toujours possible daccder internet pour rcuprer des infos ou les mettre
jour. Nous avons encore notre disposition un emplacement pour faire persister de
linformation : lintrieur du tlphone.
On appelle cet emplacement le rpertoire local (local folder en anglais ou anciennement
isolated storage) dans la mesure o nous navons pas accs directement au systme
de fichiers, mais plutt un emplacement mmoire isol dont nous pouvons ignorer
le fonctionnement. Tout ce quil faut savoir cest quil est possible dy stocker des
informations, comme du texte mais aussi des objets srialiss.
Il y a deux grandes faons dutiliser le rpertoire local. La plus simple est dutiliser le
dictionnaire ApplicationSettings. On peut y ranger des objets qui seront associs
une chane de caractres. Par exemple, en imaginant que lon cre une application
o lon demande le nom de notre utilisateur, il pourra tre judicieux dviter de le
redemander chaque ouverture de lapplication. . . Pour cela, nous pouvons le faire
persister dans le rpertoire local. On utilisera alors :
1
Nous pouvons mettre des objets complexes dans le rpertoire local, pas seulement des
chanes de caractres :
1
2
3
4
5
6
7
8
Le stockage dobjets dans le rpertoire local est quand mme trs pratique. Vous vous
servirez trs souvent de ce fonctionnement simple et efficace. Parfois vous aurez peuttre besoin dun peu plus de contrle sur ce que vous voulez stocker. ce moment-l,
on peut se servir du rpertoire local comme dun flux classique, comme lorsque lon
souhaite enregistrer des donnes dans un fichier.
Regardons lenregistrement :
1
2
3
4
5
6
7
8
Puis la lecture :
1
2
3
4
5
6
7
8
Cela ressemble beaucoup des oprations dcriture et de lecture dans un fichier classique. . . Enfin, si besoin, on pourra supprimer le fichier :
286
LE RPERTOIRE LOCAL
1
2
3
4
5
6
7
8
9
10
11
4
5
6
287
Ici, jai choisi de stocker mes donnes sous la forme de texte spars par des points
virgules, mais libre vous de spcifier le format de fichier de votre choix. Nous remarquons lutilisation des mots-cls async et await, dignes tmoins de lasynchronisme de
ces mthodes.
En rsum
Le XAML/C# pour Windows Phone dispose de toute une gamme de solutions
pour utiliser des donnes depuis internet ou en local sur le tlphone.
Les classes HttpRequest et WebClient permettent de faire des requtes sur le
protocole HTTP.
On utilise la bibliothque open-source JSON.NET pour interprter les donnes
au format JSON.
Il est trs facile dexploiter des flux RSS grce la bibliothque de syndication.
Lasynchronisme est grandement facilit dans Windows Phone 8 grce aux motscls async et await.
Le rpertoire local correspond un emplacement sur le tlphone, ddi notre
application, o lon peut faire persister de linformation entre les divers lancements dune application.
288
Troisime partie
289
Chapitre
20
Panorama et Pivot
Difficult :
Nous avons vu dans la partie prcdente que nous pouvions naviguer entre les pages,
cest bien ! Mais sachez que nous pouvons galement naviguer entre les donnes. Cest
encore mieux. Cest l quinterviennent deux contrles trs utiles qui permettent de naviguer
naturellement entre des donnes : le contrle Panorama et le contrle Pivot. Le contrle
Panorama sert en gnral voir un petit bout dun plus gros cran, qui ne rentre pas dans
lcran du tlphone. Le principe est quon peut mettre beaucoup dinformations sur une
grosse page et la mcanique du contrle Panorama incite lutilisateur se dplacer avec
le doigt sur le reste du plus gros cran. Le contrle Pivot quant lui permet plutt de
voir la mme donne sur plusieurs pages. La navigation entre les pages se fait en faisant
glisser le doigt, comme si lon tournait une page. Par exemple pour une application mto,
la premire page permet dafficher la mto du jour, la page suivante permet dafficher la
mto de demain, etc.
Dcouvrons prsent ces deux contrles.
291
Panorama
Le panorama est donc un contrle qui sert voir un petit bout dun plus gros cran
dont la taille dpasse celle de lcran du tlphone. On lillustre souvent avec une image
de ce genre (voir la figure 20.1).
PANORAMA
293
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Ce quon peut constater dj cest quil est compos de trois parties qui sont toutes
les trois des PanoramaItem. Un PanoramaItem - http://msdn.microsoft.com/fr-fr/
library/microsoft.phone.controls.panoramaitem(v=vs.92).aspx correspond donc
une vue de la totalit du Panorama. La navigation se passe entre ces trois lments.
Nous pouvons dailleurs voir dans le designer le rendu du premier PanoramaItem. Vous
pouvez galement voir le second en allant vous positionner dans le XAML au niveau
du second PanoramaItem, et de mme pour le troisime. Plutt pas mal, le rendu est
assez fidle.
294
PANORAMA
Nous pouvons galement constater que le contrle Panorama - http://msdn.microsoft.
com/fr-fr/library/microsoft.phone.controls.panorama(v=vs.92).aspx est dfini dans un espace de noms diffrent de ceux que nous avons dj utiliss, on voit
notamment quil est prfix par phone qui correspond :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
< phone : Panorama x : Name = " MonPanorama " Title = " Mes t ches " Loaded =
" Panorama_Loaded " SelectionChanged = "
P a n o r a ma _ S e l e c t i o nC h a n g e d " >
< phone : PanoramaItem Header = " Accueil " >
< StackPanel >
< TextBlock Text = " Blablabla " HorizontalAlignment = "
Center " / >
< Button Content = " Allez aujourd ' hui " Tap = "
Button_Tap " Margin = " 0 50 0 0 " / >
</ StackPanel >
</ phone : PanoramaItem >
< phone : PanoramaItem Header = " Aujourd ' hui " >
< ListBox >
< ListBoxItem > Tondre la pelouse </ ListBoxItem >
< ListBoxItem > Arroser les plantes </ ListBoxItem >
</ ListBox >
</ phone : PanoramaItem >
< phone : PanoramaItem Header = " Demain " >
< StackPanel >
< TextBlock Text = " Passer l ' aspirateur " Margin = " 30 50
0 60 " / >
< TextBlock Text = " Laver la voiture " Margin = " 30 50 0
60 " / >
</ StackPanel >
</ phone : PanoramaItem >
</ phone : Panorama >
Mon panorama contient trois lments, un accueil, des tches pour aujourdhui et des
tches pour demain. Je me suis abonn lvnement de chargement du panorama ainsi
qu lvnement de changement de slection. Ici, cela fonctionne un peu comme une
ListBox. Notons galement que lcran daccueil possde un bouton avec un vnement
de clic. Passons au code-behind prsent :
1
2
3
4
5
296
PANORAMA
}
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
La mthode Panorama_SelectionChanged est appele chaque changement de slection. Dans cette mthode, je stocke dans le rpertoire local lindex de la page en
cours, obtenu comme pour la ListBox avec la proprit SelectedIndex. Ce qui me
permet, au chargement du panorama, de me repositionner sur la dernire page visite
sil y en a une. Cela se fait grce la proprit DefaultItem que je renseigne avec le
PanoramaItem trouv lindice de la proprit Items, indice qui est celui stock dans le
rpertoire local. De la mme faon, je peux me positionner sur un PanoramaItem choisi
lorsque je clique sur le bouton. Mme si cest un peu plus rare, il est possible dutiliser
le binding avec le contrle Panorama. Reproduisons plus ou moins notre exemple prcdent en utilisant un contexte de donnes (je retire la page accueil et le bouton, ce
sera plus simple). Tout dabord le XAML :
1
2
3
4
5
6
7
< phone : Panorama x : Name = " MonPanorama " Title = " Mes t ches " Loaded =
" Panorama_Loaded " SelectionChanged = "
P a n o r a m a _ S e l e c t i on C h a n g e d " ItemsSource = " { Binding ListeEcrans
}">
< phone : Panorama . HeaderTemplate >
< DataTemplate >
< TextBlock Text = " { Binding Titre } " / >
</ DataTemplate >
</ phone : Panorama . HeaderTemplate >
< phone : Panorama . ItemTemplate >
297
8
9
10
11
12
13
14
15
16
17
18
Ici, cest comme pour la ListBox. Le contrle Panorama possde aussi des modles,
que nous pouvons utiliser. Il y a le modle HeaderTemplate qui nous permet de dfinir
un titre et le modle ItemTemplate qui nous permet de grer le contenu. Le contrle
Panorama a sa proprit ItemsSource qui est lie la proprit ListeEcrans que nous
retrouvons dans le code-behind :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
variable = valeur ;
N ot ifyPro perty Change d ( nomPropriete ) ;
return true ;
22
23
24
25
26
27
28
298
PANORAMA
29
public MainPage ()
{
I ni t i alizeComponent () ;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
DataContext = this ;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
299
Pivot
Passons maintenant lautre contrle trs pratique, le Pivot, qui est un peu le petit
frre du panorama. Il permet plutt de voir la mme donne sur plusieurs pages. La
navigation entre les pages se fait en faisant glisser le doigt, comme si lon tournait une
page. On pourrait le comparer un contrle de gestion donglets. On passe longlet
suivant en faisant glisser son doigt. . .
Voyons prsent comme fonctionne le contrle Pivot - http://msdn.microsoft.
com/fr-fr/library/microsoft.phone.controls.pivot(v=vs.92).aspx. Pour cela,
crez le deuxime type de projet que nous avons vu, savoir Application Pivot Windows Phone et dmarrons lapplication exemple (voir la figure 20.6). On constate
quon peut galement naviguer en faisant glisser la page sur la droite ou sur la gauche
avec le doigt (ou la souris).
Ici, visuellement, il y a seulement le titre des pages qui nous renseigne sur la prsence
dun autre lment. Voyons prsent le code XAML :
1
2
300
PIVOT
9
10
11
12
13
14
15
16
17
Ici, le principe est le mme que pour le Panorama. Le contrle Pivot est compos de
deux PivotItem - http://msdn.microsoft.com/fr-fr/library/microsoft.phone.
controls.pivotitem(v=vs.92).aspx, chacun faisant office de container. Dedans il
y a un LongListSelector mais tout autre contrle y trouve sa place. Encore une
fois, cest la proprit Header qui va permettre de donner un titre la page. Vous
pouvez galement voir dans le designer les diffrents rendus des PivotItem en vous
301
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< phone : Pivot Title = " Mes t ches " SelectedIndex = " { Binding
Index , Mode = TwoWay } " Loaded = " Pivot_Loaded " ItemsSource = "
{ Binding ListeEcrans } " >
< phone : Pivot . HeaderTemplate >
< DataTemplate >
< TextBlock Text = " { Binding Titre } " / >
</ DataTemplate >
</ phone : Pivot . HeaderTemplate >
< phone : Pivot . ItemTemplate >
< DataTemplate >
< ListBox ItemsSource = " { Binding ListeDesTaches } "
>
< ListBox . ItemTemplate >
< DataTemplate >
< TextBlock Text = " { Binding } " Margin =
" 0 20 0 0 " / >
</ DataTemplate >
</ ListBox . ItemTemplate >
</ ListBox >
</ DataTemplate >
</ phone : Pivot . ItemTemplate >
</ phone : Pivot >
</ Grid >
Cela ressemble beaucoup ce que nous avons fait pour le panorama. Une des premires
diffrences vient de la proprit SelectedIndex du Pivot, qui fonctionne comme pour
la ListBox. Je lai lie une proprit Index en mode TwoWay afin que la mise
jour de la proprit depuis le code-behind affecte le contrle mais quinversement, un
changement de valeur depuis le contrle mette jour la proprit. Du coup, je nai plus
besoin de lvnement de changement de slection qui existe galement sur le contrle
Pivot. Le reste du XAML est semblable au Panorama. Passons au code-behind :
1
2
3
4
5
6
7
302
PIVOT
8
9
10
11
12
if ( null != handler )
{
handler ( this , new P ro p e rt y C ha n g ed E v en t A rg s (
propertyName ) ) ;
}
13
14
15
16
17
18
19
20
21
variable = valeur ;
N o t i f yPro pertyC hange d ( nomPropriete ) ;
return true ;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public MainPage ()
{
I ni t i alizeComponent () ;
44
45
46
47
48
49
50
51
52
53
303
};
57
58
59
60
DataContext = this ;
61
62
63
64
65
66
67
68
69
Nous voyons que jai rajout une proprit Index, et qu lintrieur de son modificateur, jenregistre dans le rpertoire local la valeur de la slection. Ensuite, au chargement du pivot et lorsque la valeur existe, je positionne la proprit Index la valeur
enregistre lors dune visite prcdente. Et voil, vous pouvez admirer le rendu la
figure 20.7.
Vous pourriez trouver que les deux contrles se ressemblent, et ce nest pas compltement faux. Je vous rappelle juste que le contrle Panorama permet dafficher plusieurs
donnes sur une seule grosse page alors que le contrle Pivot est utilis pour prsenter
la mme donne sur plusieurs pages. Vous apprhenderez au fur et mesure la subtile
diffrence entre ces deux contrles.
En rsum
Le Panorama et le Pivot permettent de naviguer lintrieur des donnes.
Le Panorama sert voir un petit bout dun plus gros cran dont la taille dpasse
celle de lcran du tlphone.
Le Pivot permet plutt de voir la mme donne sur plusieurs pages.
Chaque changement de vue se fait grce un glissement de doigt.
Le contrle Pivot est particulirement bien adapt au binding.
304
PIVOT
305
306
Chapitre
21
Navigateur web
Difficult :
Malgr tous les superbes contrles dont dispose Windows Phone, vous allez parfois avoir
besoin dafficher du HTML ou bien directement une page web. Cest ainsi que le SDK
de Windows Phone dispose dun contrle bien pratique : le WebBrowser - http://msdn.
microsoft.com/fr-fr/library/microsoft.phone.controls.webbrowser(v=vs.92)
.aspx. Vous pouvez le voir comme un mini Internet Explorer que lon peut mettre o on
veut dans une page et qui na pas toute la gestion des barres dadresses, des favoris, . . .
Si nos tlphones possdent dj un navigateur web, en loccurrence Internet Explorer,
quoi pourrait bien servir un tel contrle ?
Les scnarios sont divers, cela peut aller de laffichage dun billet issu dun flux RSS une
authentification via un formulaire HTML, sur un rseau social par exemple. Ou pourquoi pas
un jeu en HTML5 ? De plus, il est galement possible de communiquer entre le Javascript
dune page web et notre page XAML. Regardons tout cela de plus prs.
307
Il est ensuite possible de naviguer sur une page web grce la mthode Navigate()
qui prend une URI en paramtre :
1
2
3
4
public MainPage ()
{
I ni t i alizeComponent () ;
MonWebBrowser . Navigate ( new Uri ( " http :// fr . openclassrooms .
com / informatique / cours / apprenez -a - developper - en - c " ,
UriKind . Absolute ) ) ;
}
Evnements de navigation
Le contrle WebBrowser possde galement des vnements qui permettent de savoir
par exemple quand une page est charge, il sagit de lvnement Navigated. Ce qui est
pratique si lon souhaite afficher un message dattente, ou si on veut nafficher vraiment
le WebControl quune fois la page compltement charge. Il y a galement un autre
vnement intressant qui permet de savoir si la navigation a chou, par exemple si
lutilisateur ne capte plus internet. Il sagit de lvnement NavigationFailed. Cet
vnement nous fournit notamment une exception qui peut nous donner plus dinformations sur lerreur.
Il est toujours intressant dindiquer lutilisateur si la navigation a chou. Il est
308
NAVIGATION INTERNE
Navigation interne
Mais nous pouvons galement crer notre propre HTML et lafficher grce la mthode
NavigateToString :
1
2
3
4
5
6
7
8
9
10
public MainPage ()
{
I ni t i al i zeComponent () ;
MonWebBrowser . NavigateToString (
@ " < html >
< body >
<h3 > Bonjour HTML ! </ h3 >
</ body >
</ html > " ) ;
}
Ensuite, dans les proprits du fichier, vrifiez que laction de gnration est contenu .
Puis, on peut utiliser le code suivant pour ajouter un fichier HTML dans le rpertoire
local :
1
2
3
4
public MainPage ()
{
I ni t i alizeComponent () ;
I n t e g r e H t m l D a n s R e p e r t o i r e L o c a l S i N o n P r e s e n t ( " hello . html " ) ;
310
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Le principe est de vrifier la prsence du fichier. Sil nexiste pas alors on le lit depuis
les ressources comme on la dj vu, puis on crit le contenu dans le rpertoire local. Il
ne restera plus qu naviguer sur ce fichier cr grce la mthode Navigate comme
on peut le voir plus haut.
< phone : WebBrowser x : Name = " MonWebBrowser " IsScriptEnabled = " True "
ScriptNotify = " M o n W e b B r o w s e r _ S c r i p t N o t i f y " / >
Pour que cela soit plus simple, je vais illustrer le fonctionnement avec du HTML et du
Javascript que jembarquerai dans mon application avec la mthode montre prcdemment. Mais il est bien sr possible de faire la mme chose avec une page sur internet.
Lvnement ScriptNotify est lev lorsque la page web invoque la mthode Javascript
window.external.notify(). Cette mthode accepte un paramtre sous la forme dune
chane de caractres qui pourra tre rcupre dans lvnement ScriptNotify. Pour
lillustrer, modifions notre page hello.html pour avoir :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1 . 0 Transitional // EN "
" http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " >
< html xmlns = " http :// www . w3 . org / 1999 / xhtml " >
< head >
< title > Demo javascript </ title >
< script type = " text / javascript " >
function EnvoyerMessage ()
{
window . external . notify ( " Bonjour , je suis " + prenom .
value ) ;
resultat . innerHTML = " Message bien envoy " ;
}
</ script >
</ head >
< body >
<h3 > Communication entre page web et XAML </ h3 >
<p > Saisissez votre pr nom : </p >
< input type = " text " id = " prenom " / >
< input type = " button " value = " Dire bonjour " onclick = "
EnvoyerMessage () ; " / >
< div id = " resultat " / >
</ body >
</ html >
Cette page possde une zone de texte pour saisir un prnom et un bouton qui invoque
la mthode Javascript EnvoyerMessage(). Cette mthode rcupre la valeur du champ
saisi, la concatne la chane Bonjour, je suis et lenvoie notre application Windows Phone via la mthode window.external.notify. Enfin, elle affiche un message
sur la page web pour indiquer que le message a bien t envoy. Ct code-behind,
nous avons juste naviguer sur notre page et rcuprer la valeur envoye :
1
2
3
4
5
6
312
private void I n t e g r e H t m l D a n s R e p e r t o i r e L o c a l S i N o n P r e s e n t (
string nomFichier , bool force )
{
I so l a tedStorageFile systemeDeFichier =
I solatedStorageFile . G e t U s e r S t o r e F o r A p p l i c a t i o n () ;
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Notez que jai rajout un paramtre la mthode permettant de stocker la page HTML
dans le rpertoire local, qui force lenregistrement afin dtre sr davoir toujours la
dernire version. Rappelez-vous, nous recevons la valeur envoye par la page web grce
lvnement ScriptNotify. Lorsque cette chane est reue, on laffiche simplement
avec une boite de message. Dmarrons lapplication, la page web saffiche, comme vous
pouvez le voir la figure 21.4.
313
< meta name = " viewport " content = " width = device - width , user scalable = no " / >
Elle permet de dfinir la taille de la fentre. On peut y mettre une valeur numrique
allant de 320 10000 ou lajuster directement la taille du tlphone avec la valeur
device-width. Remarquez, que la proprit user-scalable empchera lutilisateur de
pouvoir zoomer dans la page. Voici le rendu la figure 21.6.
Ce qui est beaucoup plus lisible ! Lautre solution est dutiliser une proprit CSS pour
ajuster la taille du texte :
1
< h3 style = " -ms - text - size - adjust : 300 % " > Communication entre page
web et XAML </ h3 >
314
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1 . 0 Transitional // EN "
" http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " >
< html xmlns = " http :// www . w3 . org / 1999 / xhtml " >
< head >
< meta name = " viewport " content = " width = device - width , user scalable = no " / >
< title > Demo javascript </ title >
< script type = " text / javascript " >
function ReceptionMessage ( texte , heure )
{
resultat . innerHTML = texte + " . Il est " + heure ;
return " OK " ;
}
</ script >
</ head >
< body >
<h3 > En attente d ' un envoi ... </ h3 >
< div id = " resultat " / >
</ body >
</ html >
Rajoutons ensuite dans notre XAML un bouton qui va permettre denvoyer des informations la page web :
1
2
3
4
5
6
7
8
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " auto " / >
</ Grid . RowDefinitions >
< phone : WebBrowser x : Name = " MonWebBrowser " IsScriptEnabled = "
True " ScriptNotify = " M o n W e b B r o w s e r _ S c r i p t N o t i f y " / >
< Button Content = " Envoyer l ' heure " Tap = " Button_Tap " Grid . Row
="1" />
</ Grid >
316
Figure 21.7 Rception par la page HTML du message envoy par lapplication
Windows Phone
Notez que le Javascript peut renvoyer une valeur au code C#. Ici je renvoie la chane
OK, que je stocke dans la variable retour pour une ventuelle interprtation. Remarquez quil est galement possible de passer des objets complexes grce au JSON. Le
principe consiste envoyer une version srialise dun objet la page web et la page
web dsrialise cet objet pour pouvoir lutiliser. Utilisons donc la bibliothque opensource JSON.NET que nous avions prcdemment utilise afin de srialiser un objet.
Rfrencez lassembly Newtonsoft.Json.dll et crez une classe avec des proprits :
1
2
3
4
5
317
3
4
5
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1 . 0 Transitional // EN "
" http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " >
< html xmlns = " http :// www . w3 . org / 1999 / xhtml " >
< head >
< meta name = " viewport " content = " width = device - width , user scalable = no " / >
< title > Demo javascript </ title >
< script type = " text / javascript " >
function ReceptionMessage ( objet )
{
var infos = JSON . parse ( objet ) ;
var d = new Date ( infos . Date ) ;
resultat . innerHTML = infos . Message + " . Il est " + d .
getHours () + 'h ' + d . getMinutes () ;
var retour = {
Resultat : " OK " ,
Succes : true
}
return JSON . stringify ( retour ) ;
}
</ script >
</ head >
< body >
<h3 > En attente d ' un envoi ... </ h3 >
< div id = " resultat " / >
</ body >
</ html >
En rsum
Le contrle WebBrowser nous permet facilement dafficher du HTML dans nos
applications Windows Phone.
Il est possible dinteragir entre lapplication et la page web grce du Javascript.
Grce au JSON, nous pourrons passer des paramtres complexes entre lapplication et la page web.
319
320
Chapitre
22
321
CORRECTION
dront la date de dernire publication (proprit LastUpdatedTime.DateTime),
le titre (proprit Title.Text) et lURL du billet (premier lment de la liste
Links, proprit Uri). Ensuite tout est une histoire de binding, ce qui nest pas
forcment le plus facile mais cest un point trs important o vous devez vous
entraner.
Enfin, la page avec le WebBrowser ne devrait pas tre trop complique faire,
le chapitre sur le WebBrowser tant tout frachement lu.
Noubliez pas que vous pouvez utiliser le dictionnaire dtat pour communiquer entre
les pages. Allez, jen ai beaucoup dit. Pour le reste, cest vous de chercher un peu.
Bon courage.
Correction
Ahhhh, une premire vraie application. Enfin ! Pas si facile finalement ? On se rend
compte quil y a plein de petites choses, plein de lgers bugs qui apparaissent au fur
et mesure de nos tests. . . Il faut avancer petit petit partir du moment o a se
complique un peu et lorsque lapplication commence grandir.
Il ny a pas une unique solution pour ce TP. Toute solution fonctionnelle est bonne.
Je vais vous prsenter la mienne. Jai port une attention quasi nulle la prsentation
histoire que cela soit assez simple. Jespre que de votre ct, vous en avez profit pour
faire quelque chose de joli !
Jai donc commenc par crer une nouvelle application, nomme TpFluxRss. tant
donn que nous avons besoin de manipuler des flux RSS, il faut rfrencer lassembly
System.ServiceModel.Syndication.dll. Voici la page de menu :
1
2
3
4
5
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
9
10
11
12
13
14
323
15
16
17
18
19
20
21
7
8
9
10
11
12
if ( I s ol at ed S to ra ge S et ti ng s . ApplicationSettings .
Contains ( " ListeUrl " ) )
{
P ho ne Ap p li ca ti o nS er v ic e . Current . State [ " ListeUrl " ] =
I so la te d St or ag e Se tt in g s . ApplicationSettings [ "
ListeUrl " ];
}
13
14
15
16
17
18
19
20
21
22
23
On observe dans le constructeur quon commence par charger un objet que lon met
directement dans le dictionnaire dtat. Le nom de la cl nous fait pressentir quil sagit
de la liste des URL de flux RSS que notre utilisateur a saisi dans notre application. Ce
qui nous permet de les faire persister dun lancement lautre. Pour le reste, il sagit
dafficher deux boutons qui nous renvoient sur dautres pages, les pages VoirFlux.xaml
et AjouterFlux.xaml (voir la figure 22.1).
Commenons par la page AjouterFlux.xaml qui, sans surprises, affiche une page per324
CORRECTION
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
10
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " TP Lecteur
de flux RSS " Style = " { StaticResource
P honeTextNormalStyle } " / >
< TextBlock x : Name = " PageTitle " Text = " Ajouter un flux "
Margin = "9 , -7 ,0 , 0 " Style = " { StaticResource
P honeTextTitle1Style } " / >
</ StackPanel >
11
12
13
14
15
16
17
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< StackPanel >
< TextBlock Text = " Saisir une url " / >
< TextBox x : Name = " Url " InputScope = " Url " / >
< Button Content = " Ajouter " Tap = " AjouterTap " / >
</ StackPanel >
325
18
19
Il permet dafficher une zone de texte, o le clavier sera adapt pour la saisie dURL
(InputScope="Url") et possdant un bouton pour faire lajout de lURL, comme vous
pouvez le voir sur la figure 22.2.
4
5
6
7
8
public AjouterFlux ()
{
I nitializeComponent () ;
}
9
10
11
12
13
14
326
CORRECTION
else
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
On commence par obtenir la liste des URL potentiellement dj charge, ensuite nous
lajoutons la liste si elle nexiste pas dj, puis nous mettons jour cette liste dans
le rpertoire local ainsi que dans le dictionnaire dtat.
Remarque : il pourrait tre judicieux de vrifier ici si lURL correspond vraiment un flux RSS.
Maintenant, il sagit de raliser la page VoirFlux.xaml, qui contient la liste des titres
des diffrents flux. Pour lexemple, je men suis ajout quelques uns, comme vous pouvez
le voir sur la figure 22.3.
Ici le XAML intressant se situe dans la deuxime grille :
1
2
3
4
5
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " TP Lecteur
de flux RSS " Style = " { StaticResource
327
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
328
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< Grid . RowDefinitions >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< TextBlock x : Name = " Chargement " HorizontalAlignment = "
Center " Foreground = " Red " FontSize = " 20 " FontWeight = "
Bold " / >
< ListBox x : Name = " ListBoxFlux " ItemsSource = " { Binding
ListeFlux } " Grid . Row = " 1 " SelectionChanged = "
L is t B ox _ S el e c ti o n C ha n g ed " >
< ListBox . ItemTemplate >
< DataTemplate >
< Grid >
< Grid . ColumnDefinitions >
< ColumnDefinition Width = " 50 " / >
< ColumnDefinition Width = " * " / >
CORRECTION
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
On y remarque un TextBlock qui servira dindicateur de chargement des flux, puis une
ListBox qui est lie la proprit ListeFlux. Le modle des lments de la ListBox
affiche limage du flux, via la liaison la proprit UrlImage, le titre via la liaison
la proprit Titre ainsi que la description. . . Notons un unique effet desthtique
permettant de sparer deux flux, via une magnifique ligne bleue. Passons au code
behind :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
329
19
20
21
22
23
24
25
26
27
variable = valeur ;
N ot ifyPro perty Change d ( nomPropriete ) ;
return true ;
28
29
30
31
32
33
public VoirFlux ()
{
I nitializeComponent () ;
DataContext = this ;
}
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
if ( listeUrl . Count == 0 )
{
MessageBox . Show ( " Vous devez d ' abord ajouter des
flux " ) ;
if ( NavigationService . CanGoBack )
NavigationService . GoBack () ;
}
else
{
Chargement . Text = " Chargement en cours ... " ;
Chargement . Visibility = Visibility . Visible ;
ListeFlux = new ObservableCollection < Flux >() ;
client = new WebClient () ;
55
56
57
58
59
60
330
CORRECTION
string rss = await client .
D ow nl o ad St ri n gT as kA s yn c ( uri ) ;
AjouteFlux ( rss ) ;
61
62
}
catch ( Exception )
{
MessageBox . Show ( " Impossible de lire le flux
l ' adresse : " + uri + " \ nV rifiez
votre connexion internet " ) ;
}
63
64
65
66
67
}
Chargement . Text = string . Empty ;
Chargement . Visibility = Visibility . Collapsed ;
68
69
70
71
72
73
}
base . OnNavigatedTo ( e ) ;
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
331
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
Cest le code-behind le plus long de lapplication. Nous voyons limplmentation classique de INotifyPropertyChanged ainsi quune proprit ListeFlux qui est une ObservableColl
de Flux. Lobjet Flux contiendra toutes les proprits dun Flux que nous souhaitons
afficher sur la prochaine page :
1
2
3
4
5
6
7
Un titre, lURL de limage, la description ainsi quune liste de billets, sachant que la
classe Billet sera :
1
2
3
4
332
CORRECTION
5
6
7
8
Ensuite, il y a le chargement des flux. Voyez comme cest facile grce await, une
simple boucle et on nen parle plus.
La mthode AjouteFlux cre un objet SyndicationFeed comme on la dj vu puis
assemble un objet Flux partir du SyndicationFeed. La liste dobjets Flux est ensuite mise jour dans le dictionnaire dtat. Notons que lors de lassemblage, je dois
dterminer si le billet a dj t lu ou non. Pour cela, je tente de lire dans le rpertoire
local la liste de tous les billets dj lus, identifis par leur id. Si je le trouve, cest que
le billet est dj lu. Cette liste est alimente lorsquon visionne rellement le billet.
Il serait judicieux de ne lire quune unique fois la liste des billets dj lus
depuis le rpertoire local, par exemple dans la mthode OnNavigatedTo, afin
damliorer les performances. Je ne lai pas fait ici pour que cela soit plus
clair, mais nhsitez pas le faire.
Enfin, lvnement de slection dun flux soccupe de rcuprer le flux slectionn, de le
mettre dans le dictionnaire dtat et de naviguer sur la page VoirFluxPivot.xaml. Finalement, ce nest pas trs compliqu. Il faut juste enchaner tranquillement les actions
sans rien oublier.
Passons prsent la page VoirFluxPivot.xaml o le but est dafficher dans un pivot
la liste des flux, en se positionnant sur celui choisi. Ce qui nous permettra de naviguer
de flux en flux en faisant un glissement de doigt. Chaque vue du pivot contiendra une
ListBox avec tous les billets du flux en cours. Notons au passage que jai choisi de
marquer les billets dj lus en italique (voir la figure 22.4).
Ici cest le XAML qui est sans doute le plus compliqu. Nous avons besoin du contrle
Pivot. Notre contrle Pivot est li la proprit ListeFlux :
1
2
3
4
5
6
7
8
9
10
11
12
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< phone : Pivot x : Name = " PivotFlux " ItemsSource = " { Binding
ListeFlux } " Loaded = " PivotFlux_Loaded " >
< phone : Pivot . HeaderTemplate >
< DataTemplate >
< TextBlock Text = " { Binding Titre } " / >
</ DataTemplate >
</ controls : Pivot . HeaderTemplate >
< phone : Pivot . ItemTemplate >
< DataTemplate >
< StackPanel >
< TextBlock Text = " { Binding Titre } "
FontWeight = " Bold " FontSize = " 20 " / >
< ListBox ItemsSource = " { Binding ListeBillets
} " SelectionChanged = "
ListeBoxBillets_SelectionChanged ">
333
Figure 22.4 La liste des billets dun flux du lecteur de flux RSS
13
14
15
16
17
18
19
20
21
22
23
CORRECTION
1
2
3
7
8
9
10
11
12
9
10
11
12
13
14
15
16
17
18
335
20
21
22
23
24
25
variable = valeur ;
N ot ifyPro perty Change d ( nomPropriete ) ;
return true ;
26
27
28
29
30
31
public VoirFluxPivot ()
{
I nitializeComponent () ;
DataContext = this ;
}
32
33
34
35
36
37
38
base . OnNavigatedTo ( e ) ;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
336
CORRECTION
60
61
62
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " TP Lecteur
de flux RSS " Style = " { StaticResource
P honeTextNormalStyle } " / >
</ StackPanel >
10
11
12
13
14
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< phone : WebBrowser x : Name = " PageBillet " NavigationFailed =
" PageBillet_NavigationFailed " />
</ Grid >
</ Grid >
Nous nous sommes quand mme abonns lvnement derreur de navigation pour
afficher un petit message, au cas o. . . Dans le code-behind, nous aurons juste besoin
de dmarrer la navigation et de marquer le billet comme lu :
1
2
337
3
4
public VoirBillet ()
{
I nitializeComponent () ;
}
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
I so la te d St or ag e Se tt i ng s . ApplicationSettings [ "
ListeDejaLus " ] = dejaLus ;
PageBillet . Navigate ( billet . Url ) ;
base . OnNavigatedTo ( e ) ;
27
28
29
30
31
32
Noublions pas de faire persister la liste des billets lus dans le rpertoire local. . . Et
voici le rsultat la figure 22.5.
Et voil, notre application commence tre fonctionnelle. Jespre que vous aurez
russi matriser notamment les histoires de binding et de slection dlments. Cest
un travail trs classique dans la cration dapplication Windows Phone avec le XAML.
Ce sont des lments que vous devez matriser. Nhsitez pas refaire ce TP si vous ne
lavez pas compltement russi. Vous pouvez aussi complter cette application qui est
loin dtre parfaite, vous entraner faire des jolies interfaces dans le style Modern UI,
rajouter des transitions, des animations, etc.
338
339
340
Chapitre
23
Grer lorientation
Difficult :
Jusqu prsent, nous avons toujours utilis notre tlphone (enfin, surtout lmulateur)
dans sa position portrait, o les boutons sont orients vers le bas, le tlphone ayant son
ct le plus long dans le sens vertical, droit devant nous. Il peut se tenir aussi horizontalement, en mode paysage. Suivant les cas, les applications sont figes et ne peuvent se
tenir que dans un sens. Dans dautres cas, elles offrent la possibilit de tenir son tlphone
dans plusieurs modes, rvlant au passage une interface lgrement diffrente. Si on tient le
tlphone en mode paysage, il y a plus de place en largeur, il peut tre pertinent dafficher
plus dinformations. . .
341
Cela indique que lapplication supporte le mode portrait et que la page dmarre en
mode portrait. Il est possible de changer les valeurs de ces proprits. On peut par
exemple affecter les valeurs suivantes la proprit SupportedOrientation :
Portrait
Landscape
PortraitOrLandscape
qui signifient respectivement portrait, paysage et portrait-ou-paysage. Ainsi, si lon positionne cette dernire valeur, lapplication va automatiquement ragir au changement
dorientation. Modifions donc cette proprit pour utiliser le mode portrait et paysage :
S u p p o r t e d Orien tation s = " PortraitOrLandscape " Orientation = "
Portrait "
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
342
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " MON
APPLICATION " Style = " { StaticResource
PhoneTextNormalStyle } " / >
< TextBlock x : Name = " PageTitle " Text = " Hello World " Margin
= "9 , -7 ,0 , 0 " Style = " { StaticResource
PhoneTextTitle1Style } " / >
11
12
13
14
15
16
17
18
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< StackPanel >
< TextBlock Text = " Bonjour tous " / >
< Button Content = " Cliquez - moi " / >
</ StackPanel >
</ Grid >
</ Grid >
Figure 23.1 Emulateur en mode portrait avec les boutons de lmulateur pour le
faire pivoter
Il est possible de simuler un changement dorientation avec lmulateur, il suffit de
cliquer sur les boutons disponibles dans la barre en haut droite de lmulateur, comme
indiqu sur limage du dessus. Lcran est retourn et linterface est automatiquement
adapte la nouvelle orientation, comme vous pouvez le voir la figure 23.2.
Ceci est possible grce la proprit que nous avons ajoute. Les contrles se redessinent automatiquement lors du changement dorientation. Remarquez que lorsquon
retourne le tlphone dans lautre mode paysage, le principe reste le mme.
Ici, le changement dorientation reste globalement lgant. Mais si nous avions utilis
un contrle en positionnement absolu grce un Canvas par exemple, il est fort possible
343
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
10
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " MON
APPLICATION " Style = " { StaticResource
PhoneTextNormalStyle } " / >
< TextBlock x : Name = " PageTitle " Text = " Hello World " Margin
= "9 , -7 ,0 , 0 " Style = " { StaticResource
PhoneTextTitle1Style } " / >
</ StackPanel >
11
12
13
14
15
16
17
18
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< Canvas >
< TextBlock x : Name = " MonTextBlock " Text = " Bonjour
tous " Canvas . Left = " 160 " / >
< Button x : Name = " MonBouton " Content = " Cliquez - moi "
Canvas . Left = " 140 " Canvas . Top = " 40 " / >
</ Canvas >
</ Grid >
</ Grid >
Alors que si on le retourne, on peut voir un beau trou droite (voir la figure 23.3).
344
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
switch ( Orientation )
{
case PageOrientation . Landscape :
case PageOrientation . LandscapeLeft :
case PageOrientation . LandscapeRight :
MessageBox . Show ( " Mode paysage " ) ;
break ;
case PageOrientation . Portrait :
case PageOrientation . PortraitDown :
case PageOrientation . PortraitUp :
MessageBox . Show ( " Mode portrait " ) ;
break ;
}
345
Et, bien souvent plus utile, il est possible dtre notifi des changements dorientation.
Cela pourra permettre par exemple de raliser des ajustements. Pour tre prvenu, il
suffit de substituer la mthode OnOrientationChanged :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
346
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< StackPanel >
< TextBlock x : Name = " MonTextBlock " Text = " Bonjour tous "
H orizontalAlignment = " Center " / >
< Button x : Name = " MonBouton " Content = " Cliquez - moi "
H orizontalAlignment = " Center " / >
</ StackPanel >
</ Grid >
Mais modifier des proprits de contrles permet quand mme de pouvoir faire des
choses intressantes. Prenez lexemple suivant o nous positionnons des contrles dans
une grille :
1
2
3
4
5
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
347
10
11
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< Grid . ColumnDefinitions >
< ColumnDefinition Width = " * " / >
< ColumnDefinition Width = " * " / >
< ColumnDefinition Width = " * " / >
</ Grid . ColumnDefinitions >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " * " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< Button x : Name = " Accueil " Content = " Accueil " / >
< Button Grid . Column = " 1 " x : Name = " Cours " Content = " Cours "
/>
< Button Grid . Column = " 2 " x : Name = " MesMPs " Content = " Mes
MPs " / >
< Image x : Name = " ImageSdz " Grid . Row = " 1 " Grid . RowSpan = " 2 "
Grid . ColumnSpan = " 3 " Source = " http :// open -e - education 2013 . openclassrooms . com / img / logos / logo openclassrooms . png " / >
</ Grid >
</ Grid >
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
9
10
11
348
12
13
14
15
16
}
else
{
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
}
base . O n O r ientationChanged ( e ) ;
349
et sur la PagePaysage.xaml :
1
2
3
4
5
6
7
8
Linconvnient est que cela fait empiler beaucoup de pages dans la navigation. Il faut
alors retirer la page prcdente de la pile de navigation. Il suffit de redfinir la mthode
OnNavigatedTo et dutiliser la mthode RemoveBackEntry :
1
2
3
4
5
Dans le mme style, nous pouvons crer des contrles utilisateurs ddis une orientation, que nous affichons et masquons en fonction de lorientation. Un contrle utilisateur
est un bout de page que nous pouvons rutiliser dans nimporte quelle page. Pour crer
un nouveau contrle utilisateur, on utilise le modle Contrle utilisateur Windows
Phone lors dun clic droit sur le projet, ajouter, nouvel lment (voir la figure 23.6).
Le contrle utilisateur portrait pourra contenir le XAML suivant :
1
2
3
4
5
351
5
6
7
8
9
10
public MainPage ()
{
I nitializeComponent () ;
controlePortrait = new ControlePortrait () ;
controlePaysage = new ControlePaysage () ;
11
12
13
14
15
352
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Le principe est dinstancier les deux contrles et de les ajouter ou de les retirer la
grille en fonction de lorientation. Linconvnient, comme pour la prcdente stratgie,
est quil faut potentiellement dupliquer pas mal de code dans chacun des contrles.
Enfin, nous pouvons utiliser le gestionnaire dtat. De la mme faon que nous lavons
vu dans la partie prcdente pour les contrles, une page peut avoir plusieurs tats.
Il suffit de considrer que ltat normal est celui en mode portrait et que nous allons
crer un tat pour le mode paysage. Pour cela, le plus simple est dutiliser Blend.
Dmarrons-le et commenons crer notre page (voir la figure 23.7).
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< TextBlock Text = " Mode Portrait " HorizontalAlignment = " Center
" />
< Button Content = " Cliquez - moi " Width = " 200 " VerticalAlignment
= " Bottom " HorizontalAlignment = " Right " / >
</ Grid >
Maintenant, nous allons crer un nouvel tat. Slectionnez la page dans larbre visuel
(en bas gauche) puis dans longlet tat, cliquez sur le petit bouton droite permettant
dajouter un groupe dtat, comme indiqu sur la figure 23.8.
355
356
2
3
4
5
6
7
8
9
10
< TextBlock x : Name = " textBlock " Text = " Mode Portrait "
H or i zo n t alAlignment = " Center " Rend erTra nsform Origi n = " 0 .5 , 0 . 5 "
>
< TextBlock . RenderTransform >
< C om positeTransform / >
</ TextBlock . RenderTransform >
</ TextBlock >
< Button x : Name = " button " Content = " Cliquez - moi " Width = " 200 "
Verti calAlignment = " Bottom " HorizontalAlignment = " Right "
R e n d e r T r a nsfor mOrigi n = " 0 .5 , 0 . 5 " >
< Button . RenderTransform >
< C om positeTransform / >
</ Button . RenderTransform >
</ Button >
8
9
10
357
11
12
13
14
15
Nous pouvons constater quil sopre des changements de coordonnes via translations, ainsi que la modification du texte du TextBlock. cet tat, ajoutons un tat
ModePortrait vide pour signifier ltat de dpart, le plus simple ici est de le faire dans
le XAML, avec :
1
2
3
4
5
6
7
8
Enfin, vous allez avoir besoin dindiquer que vous grez le multi-orientation et que vous
dmarrez en mode portrait avec :
S u p p o r t e d Orien tation s = " PortraitOrLandscape " Orientation = "
Portrait "
11
12
13
358
base . OnOrientationChanged ( e ) ;
En rsum
Un tlphone sait dtecter les changements dorientation, ainsi une application
peut sexcuter en mode portrait ou en mode paysage.
Pour tre averti dun changement dorientation, il suffit de redfinir la mthode
OnOrientationChanged.
Il faut toujours tester fond notre application avec diffrentes orientations si
lon souhaite grer le changement dorientation.
359
360
Chapitre
24
361
Taille
480x800
768x1280
720x1280
Format
15/9
15/9
16/9
Cest aussi le cas de lmulateur, que nous pouvons dmarrer suivant plusieurs rsolutions, en la changeant dans la liste droulante, comme indiqu sur la figure 24.1.
Hauteur
800
800
853
Largeur
480
480
480
Facteur dchelle
100
160
150
Les images
tant donn que nous avons diffrentes rsolutions, il se pose la question des images.
Mon image va-t-elle tre jolie dans toutes les rsolutions ? La premire ide tentante
serait dinclure 3 images diffrentes, chacune optimise pour une rsolution dcran.
Nous pourrions alors crire un petit helper qui nous dtecterait la rsolution et nous
permettrait de mettre la bonne image au bon moment :
1
2
3
4
5
8
9
10
11
12
13
14
15
16
17
if ( ResolutionHelper . EstWvga )
MonImage . Source = new BitmapImage ( new Uri ( " / Assets / Images /
Wvga / fond . png " , UriKind . Relative ) ) ;
if ( ResolutionHelper . EstWxga )
MonImage . Source = new BitmapImage ( new Uri ( " / Assets / Images /
Wxga / fond . png " , UriKind . Relative ) ) ;
if ( ResolutionHelper . Est720p )
MonImage . Source = new BitmapImage ( new Uri ( " / Assets / Images /
720p / fond . png " , UriKind . Relative ) ) ;
Cest une bonne solution sauf que cela augmentera considrablement la taille de notre
.xap et la consommation mmoire de notre application. tant donn que le facteur est
364
LES IMAGES
le mme entre WVGA et WXGA, il est possible de ninclure que les images optimises
pour la rsolution WXGA et de laisser le systme redimensionner automatiquement
les images pour la rsolution WVGA. De mme, si on peut faire en sorte de ne pas
inclure dimages en 720p et que ce soit la mise en page qui soit lgrement diffrente
pour cette rsolution, cest toujours une image en moins de gagne dans le .xap final
et en mmoire dans lapplication. Cependant, il peut parfois tre justifi dinclure les
images en diffrentes rsolutions et dutiliser notre petit helper.
noter que nous pouvons utiliser notre helper pour choisir la bonne image dans le
XAML galement. Crons une nouvelle classe :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
< Application
x : Class = " DemoResolution . App "
...
xmlns : local = " clr - namespace : DemoResolution " >
365
6
7
8
9
[...]
</ Application >
10
11
En rsum
Windows Phone 8 apporte 3 rsolutions diffrentes que nous devons grer en
tant que dveloppeur pour offrir la meilleure qualit dapplication possible.
Les diffrentes stratgies pour grer les rsolutions multiples sont les mmes que
pour grer les diffrentes orientations.
Il est possible dutiliser des images de diffrentes rsolutions dans son application
mais gardez lesprit quelles occuperont de la mmoire et augmenteront la taille
du .xap.
366
Chapitre
25
Lapplication Bar
Difficult :
Nous ne lavons pas encore vue, mais vous la connaissez srement si vous possdez un
tlphone quip de Windows Phone. La barre dapplication, si elle est prsente, est situe
en bas de lcran et possde des boutons que nous pouvons cliquer. Elle fait office plus ou
moins de menu, accessible tout le temps, un peu comme le menu en haut des fentres qui
existaient sur nos vieilles applications Windows.
Elle peut savrer trs pratique et est plutt simple daccs, deux bonnes raisons pour
pousser un peu plus loin sa dcouverte.
367
Prsentation et utilisation
Si vous utilisez le SDK pour Windows Phone 7, vous lavez srement dj vue dans le
code XAML sans vraiment y faire attention. Il y a un exemple dutilisation comment
dans chaque nouvelle page cre :
1
2
3
4
5
6
7
8
9
10
11
Si vous d-commentez ces lignes ou que vous les recopiez dans votre page Windows
Phone 8, que vous dmarrez lmulateur, vous aurez la figure 25.1.
La barre dapplication est bien sr ce que jai encadr en rouge. Ce XAML doit tre
au mme niveau que la page, cest--dire hors du conteneur racine :
1
2
3
4
5
6
7
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
...
</ Grid >
8
9
10
11
12
Le XAML est plutt facile comprendre. On constate que la barre est visible, que le
menu est activ et quelle possde deux boutons, bouton 1 et bouton 2 , ainsi
que deux lments de menu, lmentMenu 1 et lmentMenu 2 . Pour afficher
les lments de menu, il faut cliquer sur les trois petits points en bas droite. Cela
permet galement de voir le texte associ un bouton, comme vous pouvez le voir sur
la figure 25.2.
368
PRSENTATION ET UTILISATION
PRSENTATION ET UTILISATION
Figure 25.4 La barre dapplication subit une rotation lors du changement dorientation du tlphone
371
4
5
6
7
8
9
10
Ici, nous utilisons lvnement Click, il nexiste pas dvnement Tap pour
la barre dapplication.
Avec :
1
2
3
4
5
6
7
8
9
PRSENTATION ET UTILISATION
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
6
7
8
9
10
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock Text = " MON APPLICATION " Style = " {
StaticResource PhoneTextNormalStyle } " Margin = " 12 , 0 "
/>
< TextBlock Text = " nom de la page " Margin = "9 , -7 ,0 , 0 "
Style = " { StaticResource PhoneTextTitle1Style } " / >
</ StackPanel >
11
12
13
14
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< Canvas >
< TextBlock Text = " Je suis cach " Foreground = " Red "
FontSize = " 50 " Canvas . Top = " 500 " / >
373
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Si vous dmarrez lapplication, le texte rouge est invisible car il est derrire la barre
dapplication. Si vous changez lopacit en mettant par exemple 0.5 :
1
< shell : ApplicationBar IsVisible = " True " IsMenuEnabled = " True "
Opacity = " 0 . 5 " >
Pour les lments de menu, le principe est le mme que pour les boutons.
Notons juste quil est possible de sabonner un vnement qui permet de savoir si ltat
de la barre change, cest--dire quand les lments de menu sont affichs ou non. Cela
permet par exemple de faire en sorte que certaines infos soient affiches diffremment
si jamais le menu les cache. Il sagit de lvnement StateChanged :
1
2
3
4
374
PRSENTATION ET UTILISATION
5
6
7
// ...
Enfin, remarquons une dernire petite chose qui peut-tre vous a intrigu. Il sagit de
lendroit dans le XAML o est dfinie la barre dapplication :
1
2
3
4
5
6
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
...
</ Grid >
7
8
9
10
11
Jen ai parl un peu en haut mais vous avez vu ? Elle est au mme niveau que la grille !
Alors que nous avons dit quun seul conteneur racine tait autoris. Cest parce que
lobjet ApplicationBar ne drive pas de FrameworkElement, pour notre plus grand
malheur dailleurs. La proprit ApplicationBar de la PhoneApplicationPage est une
proprit de dpendance : http://msdn.microsoft.com/fr-fr/library/microsoft.
375
Appliquer le Databinding
tant donn que notre barre dapplication nest pas un FrameworkElement, elle ne
sait pas grer la liaison de donnes. Il nest donc pas possible dutiliser les extensions
de balisage {Binding} ni les commandes sur cet lment. Ce qui pose un problme
lorsque lon fait du MVVM ou mme quand il sagit de traduire notre application. Il
y a cependant une petite astuce pour rendre notre barre application fonctionnelle avec
la liaison de donnes ainsi quavec le systme de commandes. Il suffit de dvelopper
une nouvelle classe qui encapsule les fonctionnalits de la classe ApplicationBar. On
appelle communment ce genre de classe un wrapper.
Nous nallons pas faire cet exercice ici vu que dautres personnes lont dj fait pour
nous. Cest le cas par exemple de la bibliothque BindableApplicationBar que nous
pouvons trouver cet emplacement : http://bindableapplicationb.codeplex.com/.
Vous pouvez tlcharger cette bibliothque ou tout simplement utiliser NuGet (voir la
figure 25.7).
Il ne reste plus qu importer lespace de nom suivant :
xmlns : barre = " clr - namespace : Bin da ble Ap pli cat io nBa r ; assembly =
B i n d a bl eA ppl ica ti onB ar "
4
5
6
7
8
APPLIQUER LE DATABINDING
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
variable = valeur ;
N o t i f yPro pertyC hange d ( nomPropriete ) ;
return true ;
19
20
21
377
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public MainPage ()
{
I nitializeComponent () ;
SupprimerCommand = new RelayCommand ( OnSupprimer ) ;
ElementCommand = new RelayCommand ( OnElement ) ;
EstBarreVisible = true ;
40
41
42
43
44
45
46
47
48
DataContext = this ;
49
50
51
52
53
54
55
56
57
58
59
Notez que vous aurez besoin dune classe RelayCommand, venant de votre framework
MVVM prfr ou bien lexemple simple que nous avons cr prcdemment. Grce
cette classe, nous pouvons dsormais respecter correctement le pattern MVVM, chose
qui tait plus difficile sans.
Le framework Ultralight MVVM que nous avons cit dans un chapitre prcdent propose une solution pour grer la liaison de donnes avec la barre
dapplication.
378
Nous pouvons modifier ici sa valeur en mettant False. Ou bien par code, en utilisant la classe statique SystemTray - http://msdn.microsoft.com/en-us/library/
microsoft.phone.shell.systemtray(v=vs.92).aspx :
1
Cela permet de rcuprer 16 pixels en hauteur. Vous aurez besoin dinclure lespace de
nom suivant :
1
En rsum
La barre dapplication est un contrle utile lorsquil y a besoin de faire des
actions rcurrentes dans une application.
Elle fonctionne un peu comme un menu, accessible de partout.
Ne supportant pas la liaison de donnes par dfaut, il est possible dutiliser des
wrappers pour la rendre fonctionnelle avec le binding.
Il est recommand de ne pas masquer la barre systme, mais cest cependant
possible pour passer en mode plein cran.
379
380
Chapitre
26
381
PERFORMANCEPROGRESSBAR
PerformanceProgressBar
Je souhaitais vous parler de la barre de progression PerformanceProgressBar car
cest un trs bon exemple de la puissance du toolkit. La barre de progression qui tait
originellement prsente avec le SDK pour Windows Phone 7.X posait des problmes
de performances. Celle du toolkit profite de toutes les optimisations possibles et gre
galement beaucoup mieux les threads. Nous parlerons des Threads dans un prochain
chapitre. Toujours est-il que pour Windows Phone 7, ctait cette barre de progression
qui tait recommande un peu partout sur le net et par Microsoft (pour la petite histoire, cest un dveloppeur de Microsoft qui a cr cette nouvelle barre de progression).
Elle a depuis t intgre dans le SDK de Windows Phone 8 afin de tirer parti de
ces amliorations. Je vais vous montrer ici comment sen servir dans une application
pour Windows Phone 7 et aprs je rebasculerai sur Windows Phone 8. Crez donc une
application qui cible le SDK 7.1. Ensuite, pour utiliser la barre, rien de plus simple, il
vous suffit dimporter lespace de nom du toolkit :
1
< toolkit : P e r f orm anc eP rog re ssB ar IsIndeterminate = " True " / >
La barre de progression nen est en fait pas vraiment une, du moins pas dans le sens o
on les connait : en loccurrence, elle naffiche pas un pourcentage de progression sur une
tche dont on connait la dure totale. Il sagit plutt dune petite animation qui montre
quil se passe un chargement, sans que lon sache vraiment o nous en sommes. Vous
pouvez voir son fonctionnement dans le designer de Visual Studio, la barre sanime et
affiche des points, comme indiqu sur la figure 26.2.
La barre est visible dans un tat o la progression est indtermine. Cest pour cela
que la proprit sappelle IsIndeterminate et permet dindiquer si elle est visible ou
non. Passez la False pour la voir se masquer. En gnral, ce que vous ferez, cest
dans un premier temps mettre la proprit vrai, dmarrer quelque chose de long de
manire asynchrone, par exemple un tlchargement, et une fois termin vous passerez
la proprit faux. Nous pouvons simuler ce fonctionnement avec un DispatcherTimer http://msdn.microsoft.com/fr-fr/library/system.windows.threading.dispatchertimer(v=
vs.95).aspx, il sagit dune classe qui va nous permettre dappeler une mthode une
frquence dtermine. Nous en reparlerons plus tard, mais par exemple ici, mon Timer
va me permettre de masquer ma barre de progression au bout de 7 secondes :
1
2
3
4
5
6
7
8
383
9
10
11
12
13
14
P r o p e r t y C h a n g e d E v e n t H a n d l e r handler = PropertyChanged ;
if ( null != handler )
{
handler ( this , new P ro p e rt y C ha n g ed E v en t A rg s (
propertyName ) ) ;
}
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public MainPage ()
{
I nitializeComponent () ;
DataContext = this ;
31
32
384
ChargementEnCours = true ;
LISTPICKER
33
34
35
36
37
38
39
40
41
42
43
Noubliez pas dinclure lespace de noms suivant pour pouvoir utiliser le DispatcherTimer :
1
Remarquez quil est possible de changer facilement la couleur des points grce la
proprit Foreground. noter que son utilisation est globalement la mme avec le SDK
pour Windows Phone 8, on utilisera cependant le contrle ProgressBar directement.
Sachant que pour reproduire exactement le mme fonctionnement, il faudra masquer
la barre de progression une fois son statut indtermin activ :
1
Usez et abusez de cette barre ds quil faut avertir lutilisateur que quelque chose de
potentiellement long se passe.
ListPicker
Le contrle ListPicker est une espce de ListBox simplifie. Il est lquivalent dun
contrle connu mais qui manquait dans les contrles Windows Phone, la ComboBox.
Ce ListPicker permet de choisir un lment parmi une liste dlments relativement
restreinte. Puissant grce son systme de modle, il permet de prsenter linformation
de manire volue. Voyons prsent comment il fonctionne.
La manire la plus simple de lutiliser est de le lier une liste de chanes de caractres :
1
385
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
variable = valeur ;
N ot ifyPro perty Change d ( nomPropriete ) ;
return true ;
22
23
24
25
26
27
28
29
public MainPage ()
{
I nitializeComponent () ;
DataContext = this ;
30
31
32
33
34
35
36
37
Langues = new List < string > { " Fran ais " , " English " , "
Deutsch " , " Espa ol " };
< toolkit : ListPicker ItemsSource = " { Binding Langues } " x : Name = "
Liste " SelectionChanged = " Lis te _Se le cti onC ha nge d " / >
386
LISTPICKER
public MainPage ()
{
I ni t i alizeComponent () ;
DataContext = this ;
5
6
7
8
Langues = new List < string > { " Fran ais " , " English " , "
Deutsch " , " Espa ol " };
Liste . SelectedIndex = 2 ;
9
10
11
12
13
14
15
16
LISTPICKER
1
< toolkit : ListPicker ItemsSource = " { Binding Langues } " Header = "
Langue : " FullModeHeader = " Choisir une langue : "
ExpansionMode = " FullScreenOnly " / >
389
sachant que les images correspondant aux drapeaux de chaque langue sont inclues dans
le rpertoire Images, sous le rpertoire Assets, dans notre solution (en ayant chang
laction de gnration Contenu ). Je peux alors modifier le XAML pour avoir :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
< toolkit : ListPicker ItemsSource = " { Binding Langues } " Header = "
Langue : " FullModeHeader = " Choisir une langue : "
ExpansionMode = " FullScreenOnly " >
< toolkit : ListPicker . ItemTemplate >
< DataTemplate >
< StackPanel Orientation = " Horizontal " >
< Border BorderThickness = " 2 " BorderBrush = " Beige "
Background = " Azure " >
< TextBlock Text = " { Binding Code } " Foreground
= " Blue " / >
</ Border >
< TextBlock Margin = " 20 0 0 0 " Text = " { Binding
Langue } " / >
</ StackPanel >
</ DataTemplate >
</ toolkit : ListPicker . ItemTemplate >
< toolkit : ListPicker . FullModeItemTemplate >
< DataTemplate >
< StackPanel Orientation = " Horizontal " >
< TextBlock Margin = " 20 0 0 0 " Text = " { Binding
Langue } " Style = " { StaticResource
PhoneTextTitle1Style } " / >
< Image Source = " { Binding Url } " / >
</ StackPanel >
</ DataTemplate >
</ toolkit : ListPicker . FullModeItemTemplate >
</ toolkit : ListPicker >
LISTPICKER
WrapPanel
Au mme titre que le StackPanel, le WrapPanel du toolkit est un conteneur de contrles
qui a une fonctionnalit intressante. Il est capable de passer automatiquement la ligne
ou la colonne suivante si les contrles prsents lintrieur dpassent du conteneur.
Prenons par exemple le XAML suivant et rutilisons les images de lexemple prcdent :
1
2
3
4
5
6
Figure 26.9 Lcran nest pas assez large pour voir les 4 images avec un StackPanel
392
WRAPPANEL
Oh diantre, cest plutt embtant, on ne voit que 3 images sur les 4 promises. . . ! Eh
oui, il ny a pas assez de place sur lcran et la troisime image dpasse du conteneur.
Changeons maintenant juste le conteneur et remplaons-le par un WrapPanel :
1
2
3
4
5
6
393
< Image Source = " / Assets / Images / usa . png " Width = " 150 " Height = "
150 " Margin = " 10 " / >
< Image Source = " / Assets / Images / allemagne . png " Width = " 150 "
Height = " 150 " Margin = " 10 " / >
< Image Source = " / Assets / Images / espagne . png " Width = " 150 "
Height = " 150 " Margin = " 10 " / >
</ toolkit : WrapPanel >
Le WrapPanel est trs pratique combin avec une ListBox ou mme un ListPicker.
Dans lexemple fourni avec le toolkit, on peut le voir utilis lintrieur dun Pivot.
Nhsitez pas vous servir de ce conteneur ds que vous aurez besoin dafficher une
liste dlments dont vous ne maitrisez pas forcment le nombre.
Et je ne sais pas si vous vous souvenez, mais je vous ai fait une capture dcran prcdemment lorsque je parlais des diffrentes rsolutions des Windows Phone o javais
ajout plein de boutons les uns la suite des autres. Ils taient dans un WrapPanel et
salignaient alors automatiquement, les uns la suite des autres.
394
LONGLISTSELECTOR
LongListSelector
Avant de sarrter sur lexploration des contrles de ce toolkit, regardons encore le
contrle LongListSelector. Bien que jaie choisi de prsenter ce contrle dans le chapitre sur le toolkit Windows Phone, le LongListSelector existe dans le SDK de Windows Phone 8. Eh oui, cest comme pour le ProgressBar, voici un contrle qui nexistait
pas avec le SDK pour Windows Phone 7, qui a t cr et approuv par la communaut, et qui trouve naturellement sa place dans le SDK pour Windows Phone 8. Il
permet damliorer encore la ListBox, notamment quand celle-ci contient normment
de valeurs. Grce lui, nous pouvons regrouper des valeurs afin que chacune soit plus
facilement accessible. Ce type de contrle est utilis par exemple avec les contacts dans
notre tlphone, lorsque nous commenons en avoir beaucoup.
La figure 26.12 montre le rsultat que nous allons obtenir la fin de ce chapitre, les
prnoms sont regroups suivant leur premire lettre.
List < string > liste = new List < string > { " Emma " , " Manon " , " Chlo
" , " Camille " , " L a " , " Lola " , " Louise " , " Zo " , " Jade " , " Clara
" , " Lena " , " Eva " , " Ana s " , " Cl mence " , " Lilou " , " In s " , "
395
Le principe est de faire une liste de liste groupe dlments grce loprateur Linq
join :
IEnumerable < List < string > > prenoms = from prenom in liste
group prenom by prenom [ 0 ]. ToString () into p
orderby p . Key
select new List < string >( p ) ;
1
2
3
4
5
Ici, jai choisi de regrouper les prnoms en fonction de leur premire lettre, mais on pourrait trs bien imaginer une liste de villes regroupes en fonction de leur pays dappartenance. . . ou quoi que ce soit dautre. . . Pour utiliser le binding avec ce LongListSelector,
nous devons avoir la proprit suivante :
1
2
3
396
LONGLISTSELECTOR
4
5
6
Cot XAML cest un peu plus compliqu. Nous avons premirement besoin de lier la
proprit ItemsSource du LongListSelector notre proprit ListePrenoms :
1
2
Ensuite, nous rajoutons un modle pour les groupes visibles dans la liste. Il sagit du
modle GroupHeaderTemplate. Ici nous devons afficher la premire lettre du groupe,
entoure dans un rectangle dont le bord correspond la couleur daccentuation :
1
2
3
4
5
397
7
8
9
10
Remarquez qutant donn que la liaison se fait sur la List<string>, jutilise un converter pour nafficher que la premire lettre. Ce converter est dfini classiquement en
ressource :
1
Le converter quant lui est trs simple, il prend simplement la premire lettre du
premier lment de la liste :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
398
LONGLISTSELECTOR
2
Enfin, il reste le style de la liste des groupes, qui apparat lorsquon clique sur un groupe.
Il sagit du style LongListSelectorJumpListStyle que nous avons prcdemment vu,
qui est galement mettre en ressources :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Ici, le principe est le mme, on utilise le converter pour afficher la premire lettre. Elle
sera dans un cadre au fond du thme daccentuation. Ce qui nous donne le code XAML
complet suivant :
1
2
3
4
5
399
6
7
8
9
10
11
12
13
14
Cest vrai, je le reconnais, il fait un peu peur ! Nous allons le simplifier en mettant nos
DataTemplate en ressource. Il suffit de les dclarer ainsi :
1
2
4
5
6
7
8
10
11
12
...
</ phone : P honeApplicationPage . Resources >
13
14
Noubliez pas quil faut imprativement une cl un lment prsent dans les ressources.
Nous pourrons alors simplifier lcriture du contrle ainsi :
1
400
Ce contrle est plutt pratique. Jai choisi dutiliser un converter pour afficher le titre
dun groupe en utilisant la premire lettre des prnoms. Ce qui se fait aussi cest
de construire un objet directement liable possdant une proprit Titre et une liste
dlments, en gnral quelque chose comme a :
1
2
3
4
5
6
7
8
9
10
set ;
402
En rsum
Le toolkit pour Windows Phone est une bibliothque de contrles fournie gratuitement qui permet denrichir vos applications avec des contrles trs pratiques.
Il y a beaucoup de bibliothques qui existent et qui proposent des contrles
complets, sadaptant beaucoup de situation. Certaines sont gratuites, dautres
payantes. Nhsitez pas les consulter, il y a souvent de bonnes surprises.
403
404
Chapitre
27
405
Prsentation et utilisation
Pour utiliser le contrle Map, le plus simple est de le faire glisser depuis la boite outils
pour le mettre par exemple lintrieur de la grille, comme indiqu la figure 27.1.
PRSENTATION ET UTILISATION
Si vous dmarrez lmulateur tout de suite, vous allez avoir un problme. Visual Studio
nous lve une exception de type :
1
En fait, pour utiliser le contrle de cartes, nous devons dclarer notre application comme
utilisatrice du contrle de cartes. Cela permettra notamment aux personnes qui veulent
tlcharger notre application de savoir quelle utilise le contrle de carte. On appelle
cela les capacits. Pour dclarer une capacit, nous allons avoir besoin de double-cliquer
sur le fichier WMAppManifest.xml (sous Properties dans lexplorateur de solutions) et
daller dans longlet Capacits. Ensuite, il faut cocher la capacit ID_CAP_MAP, comme
lindique la figure 27.3.
Et voil, maintenant en dmarrant lmulateur, nous allons avoir une jolie carte du
monde (si vous tes connects Internet) - voir la figure 27.4.
407
8
9
10
11
12
13
14
15
16
17
Vous pouvez voir que nous pouvons facilement zoomer ou d-zoomer en utilisant les
boutons de la barre dapplication, et tout a grce la proprit ZoomLevel. De plus,
nous pouvons nous dplacer sur la carte en faisant glisser notre doigt (ou notre souris !),
comme indiqu la figure 27.5.
409
Tout au long de lutilisation, sur un tlphone, nous pouvons galement zoomer et dzoomer grce au geste qui consiste ramener ses deux doigts vers le centre de lcran
ou au contraire les carter pour d-zoomer (geste que lon appelle le Pinch-to-zoom
ou le Stretch-to-zoom). Cest par contre un peu plus difficile faire la souris dans
lmulateur, sachant que nous avons quand mme la possibilit de zoomer en doublecliquant. . . Mais cela sera quand mme bien plus simple dans lmulateur avec la barre
dapplication.
Nous pouvons aussi centrer la carte un emplacement prcis. Pour cela, on utilise la proprit Center qui est du type GeoCoordinate - http://msdn.microsoft.
com/fr-fr/library/system.device.location.geocoordinate.aspx. Il sagit dune
classe contenant des coordonnes GPS, avec notamment la latitude et la longitude.
Nous pouvons utiliser des coordonnes pour centrer la carte un emplacement dsir.
Par exemple :
1
2
3
4
5
6
public MainPage ()
{
I ni t i alizeComponent () ;
Carte . ZoomLevel = 17 ;
Carte . Center = new GeoCoordinate { Latitude = 48 . 858115 ,
Longitude = 2 . 294710 };
}
410
La carte est galement disponible en mode satellite (ou arien), il suffit de changer la
proprit CartographicMode du contrle pour passer en mode arien avec :
1
413
3
4
5
6
7
Et le code suivant :
1
2
3
4
5
public MainPage ()
{
I ni t i alizeComponent () ;
Carte . ZoomLevel = 12 ;
Carte . Center = new GeoCoordinate { Latitude = 48 . 863134 ,
Longitude = 2 . 320518 };
6
7
8
414
La punaise est bien sr stylisable souhait, car celle-l est un peu triste. Prenez par
exemple celle-ci, permettant de remplacer la grosse punaise par un petit point bleu :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
6
7
415
4
5
416
4
5
public MainPage ()
{
I ni t i al i zeComponent () ;
Carte . ZoomLevel = 12 ;
Carte . Center = new GeoCoordinate { Latitude = 48 . 863134 ,
Longitude = 2 . 320518 };
Po si ti onT ourEiffel = new GeoCoordinate { Longitude = 2 .
321747 , Latitude = 48 . 842276 };
DataContext = this ;
}
Avec :
1
2
417
4
5
6
Et :
Texte = " La tour Eiffel " ;
< ControlTemplate x : Key = " P ush pi nCo ntr ol Tem pl ate " TargetType = "
toolkitcarte : Pushpin " >
< StackPanel >
< ContentPresenter Content = " { TemplateBinding Content } "
/>
< Ellipse Fill = " { TemplateBinding Background } "
HorizontalAlignment = " Center "
VerticalAlignment = " Center "
Width = " 20 "
Height = " 20 "
Stroke = " { TemplateBinding Foreground } "
StrokeThickness = " 3 " / >
418
Et le contrle serait :
1
2
3
4
5
419
7
8
9
10
11
Il faudra ensuite lier par exemple une liste de positions ce MapItemsControl via
code-behind :
1
2
3
4
5
6
8
9
Comme ceci, cela fonctionne et donne le rsultat que vous voyez sur la figure 27.14.
Personnellement, jadore ces punaises !
Elles peuvent galement ragir un clic, ce qui nous laisse lopportunit dafficher par
exemple des informations complmentaires sur cette position. On utilisera lvnement
Tap du contrle Pushpin. Sauf quen gnral, si on utilise une liste de positions comme
on la fait juste au-dessus, nous ne disposons pas dinformations suffisantes pour savoir quelle punaise a t clique. Ce quon peut faire ce moment-l, cest utiliser
la proprit Tag du contrle, qui est une espce dobjet fourre-tout pour passer des
informations.
La proprit Tag est une proprit hrite de la classe FrameworkElement.
Tous les contrles possdent donc cette proprit fourre-tout.
Illustrons ce point en crant une nouvelle classe :
1
2
3
4
5
420
421
7
8
9
10
11
Afficher un itinraire
Bonne nouvelle, avec Windows Phone 8, il est trs facile de calculer et dafficher un
itinraire entre deux points. Prenons une carte classique :
1
4
5
422
public MainPage ()
AFFICHER UN ITINRAIRE
Figure 27.15 Le clic sur une punaise nous dclenche laffichage dun message
I ni t i alizeComponent () ;
Carte . ZoomLevel = 13 ;
Carte . Center = new GeoCoordinate { Latitude = 48 . 863134
, Longitude = 2 . 320518 };
coordonnesTrajet = new List < GeoCoordinate >() ;
9
10
11
12
13
14
Ca lc ulerItineraire () ;
15
16
17
18
19
20
21
22
23
24
25
26
423
29
geocodeQuery . QueryCompleted +=
geocodeQuery_QueryCompleted ;
geocodeQuery . QueryAsync () ;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
6
7
424
AFFICHER UN ITINRAIRE
8
9
10
11
12
13
};
14
geocodeQuery . QueryCompleted -=
qu er yCo mpl et edd Ha ndl er ;
if ( e . Error != null )
taskCompletionSource . TrySetException ( e . Error ) ;
else
taskCompletionSource . TrySetResult ( e . Result ) ;
15
16
17
18
19
20
21
22
23
24
25
26
27
425
};
33
34
35
36
37
38
39
40
Et ensuite de faire :
1
2
3
4
5
6
7
public MainPage ()
{
I nitializeComponent () ;
Carte . ZoomLevel = 13 ;
Carte . Center = new GeoCoordinate { Latitude = 48 . 863134
, Longitude = 2 . 320518 };
coordonnesTrajet = new List < GeoCoordinate >() ;
9
10
11
12
13
14
CalculerItineraire () ;
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
try
{
30
31
426
AFFICHER UN ITINRAIRE
coordonnesTrajet . Add ( resultat [ 0 ]. GeoCoordinate ) ;
routeQuery . Waypoints = coordonnesTrajet ;
var route = await routeQuery . QueryRouteAsync () ;
Carte . AddRoute ( new MapRoute ( route ) ) ;
32
33
34
35
36
37
38
39
40
41
}
catch ( Exception )
{
}
Nous pouvons mme avoir les instructions de dplacement. Rajoutons une ListBox dans
le XAML :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< maps : Map x : Name = " Carte " / >
< ListBox x : Name = " ListeDirections " Grid . Row = " 1 " >
< ListBox . ItemTemplate >
< DataTemplate >
< TextBlock Text = " { Binding } " / >
</ DataTemplate >
</ ListBox . ItemTemplate >
</ ListBox >
</ Grid >
try
{
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
List < string > routeList = new List < string >() ;
foreach ( RouteLeg leg in route . Legs )
{
foreach ( RouteManeuver maneuver in leg . Maneuvers )
{
routeList . Add ( maneuver . InstructionText ) ;
}
}
19
20
427
}
catch ( Exception )
{
}
En rsum
Le contrle Map est un contrle trs puissant qui nous permet dexploiter les
cartes du monde entier dans nos applications.
Il est possible dpingler des points dintrts grce aux objets PushPin du toolkit Windows Phone.
Le contrle de carte fournit de quoi calculer un itinraire, que lon peut afficher
sur la carte.
428
Chapitre
28
429
On peut donc prciser le nom de la ville dans le paramtre q, le type de format souhait
et le nombre de jours dinformations mtos souhaits (maxi 5). Jobtiens un JSON en
retour, du genre :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
430
431
} }
25
Correction
Ah voil une petite application quelle est sympathique. Et utile en plus ! Cest toujours
pratique de pouvoir savoir sil vaut mieux prendre son parapluie ou ses tongues. Pour
raliser cette correction, nous allons commencer par crer la page qui permet dajouter
une ville, je lappelle Ajouter.xaml. Voici le XAML :
1
2
3
4
5
6
7
8
9
10
432
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
CORRECTION
11
12
13
14
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12
, 17 ,0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " M t o en
direct " Style = " { StaticResource
PhoneTextNormalStyle } " / >
< TextBlock x : Name = " PageTitle " Text = " Ajouter une
ville " Margin = "9 , -7 ,0 , 0 " Style = " { StaticResource
PhoneTextTitle2Style } " / >
</ StackPanel >
15
16
17
18
19
20
21
22
23
24
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 ,
12 , 0 " >
< StackPanel >
< TextBlock Text = " Nom de la ville " / >
< TextBox x : Name = " NomVille " / >
< Button Content = " Ajouter " Tap = " Button_Tap " / >
</ StackPanel >
</ Grid >
</ Grid >
</ phone : PhoneApplicationPage >
Elle nest pas trs complique, nous avons une zone de saisie permettant dindiquer
une ville et un bouton permettant dajouter la ville. Le code-behind est :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
433
23
24
25
26
27
28
29
if ( NavigationService . CanGoBack )
NavigationService . GoBack () ;
Aprs un test pour vrifier quil y a bien un lment dans la zone de saisie, jenregistre
la ville dans le rpertoire local, en tant que dernire ville consulte et dans la liste
totale des villes dj enregistres. Bien sr, si cette liste nexiste pas, je la cre. Je
mautorise mme une petite navigation arrire aprs lenregistrement, fainant comme
je suis, pour viter davoir appuyer sur le bouton de retour arrire (voir la figure
28.2).
434
CORRECTION
6
7
8
9
10
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
11
12
13
14
15
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12
, 17 ,0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " M t o en
direct " Style = " { StaticResource
PhoneTextNormalStyle } " / >
< TextBlock x : Name = " PageTitle " Text = " Choisir une
ville " Margin = "9 , -7 ,0 , 0 " Style = " { StaticResource
PhoneTextTitle2Style } " / >
</ StackPanel >
16
17
18
19
20
21
22
23
24
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 ,
12 , 0 " >
< toolkit : ListPicker x : Name = " Liste " ItemsSource = " {
Binding ListeVilles } "
Header = " Ville choisie : "
CacheMode = " BitmapCache " >
</ toolkit : ListPicker >
</ Grid >
</ Grid >
</ phone : PhoneApplicationPage >
4
5
6
7
8
9
10
11
12
13
14
15
16
17
435
variable = valeur ;
N ot ifyPro perty Change d ( nomPropriete ) ;
return true ;
22
23
24
25
26
27
28
29
30
31
32
33
34
public ChoisirVille ()
{
I nitializeComponent () ;
DataContext = this ;
}
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
436
if ( I s ol at ed S to ra ge S et ti ng s . ApplicationSettings .
Contains ( " DerniereVille " ) )
{
string ville = ( string ) I so la t ed St o ra ge Se t ti ng s .
ApplicationSettings [ " DerniereVille " ];
int index = ListeVilles . IndexOf ( ville ) ;
if ( index >= 0 )
Liste . SelectedIndex = index ;
}
Liste . SelectionChanged += L is te_ Se lec ti onC han ge d ;
CORRECTION
62
63
64
}
base . OnNavigatedTo ( e ) ;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
On commence par un petit test, sil ny a pas de ville choisir alors, nous navons rien
faire ici. Ensuite nous associons la proprit ListeVilles au contenu du rpertoire
local et nous rcuprons la dernire ville afin de prslectionner le ListPicker avec la
ville dj choisie. Attention, lorsque nous slectionnons un lment ainsi, lvnement
de changement de slection est lev. Ce qui ne mintresse pas. Cest pour cela que
je me suis abonn cet vnement aprs avoir modifi la proprit SelectedIndex.
Pour la propret du code, ceci implique que je me dsabonne de ce mme vnement
lorsque je quitte la page. Enfin, en cas de changement de slection, jenregistre la ville
slectionne dans le rpertoire local. Pas trs compliqu non plus, part peut-tre la
petite astuce pour viter que lvnement de slection ne soit lev. De toute faon, ce
genre de chose se voit trs rapidement lorsque nous testons notre application, comme
vous pouvez le constater sur la figure 28.3.
Enfin, il reste la page affichant les conditions mto. Voici ma classe Meteo utilise,
ainsi que les classes gnres pour le mapping des donnes JSON :
1
2
3
4
5
6
7
8
9
10
11
12
437
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
438
CORRECTION
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
4
5
6
7
8
9
10
11
12
13
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
14
15
16
17
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12
, 17 ,0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " M t o en
direct " Style = " { StaticResource
PhoneTextNormalStyle } " / >
</ StackPanel >
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
440
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 ,
12 , 0 " >
< Grid . RowDefinitions >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< ProgressBar IsIndeterminate = " { Binding
ChargementEnCours } " Visibility = " { Binding
ChargementEnCours , Converter ={ StaticResource
VisibilityConverter }} " / >
< TextBlock Text = " { Binding NomVille } " Style = " {
StaticResource PhoneTextTitle2Style } " / >
< phone : Pivot Grid . Row = " 1 " ItemsSource = " { Binding
ListeMeteo } " >
< phone : Pivot . HeaderTemplate >
< DataTemplate >
< TextBlock Text = " { Binding Date } " / >
</ DataTemplate >
</ phone : Pivot . HeaderTemplate >
< phone : Pivot . ItemTemplate >
< DataTemplate >
< StackPanel >
< TextBlock Text = " { Binding
TemperatureMin } " / >
< TextBlock Text = " { Binding
TemperatureMax } " / >
< TextBlock Text = " { Binding Temps } "
/>
CORRECTION
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Tout dabord, regardons la barre dapplication tout en bas. Elle possde deux boutons avec deux icnes. Il faudra bien sr rajouter ces icnes dans notre application,
en action de gnration gale contenu et en copie si plus rcent. Les deux boutons
permettent de naviguer vers nos deux pages, cres prcdemment. Ensuite, nous avons
une barre de progression, lie la proprit ChargementEnCours, que ce soit sa proprit IsIndeterminate ou sa proprit Visibility. Nous avons galement le Pivot,
li la proprit ListeMeteo. Lentte du Pivot sera le nom du jour et les lments du
corps du pivot sont les diverses proprits de lobjet Meteo. Accompagnant le XAML,
nous aurons le code-behind suivant :
1
2
3
4
5
6
7
8
9
10
11
12
441
17
18
19
20
21
variable = valeur ;
N ot ifyPro perty Change d ( nomPropriete ) ;
return true ;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public MainPage ()
{
I nitializeComponent () ;
DataContext = this ;
}
49
50
51
52
53
54
55
56
57
442
CORRECTION
try
{
58
59
60
61
ChargementEnCours = false ;
string resultatMeteo = await client .
D ow nl o ad St ri n gT as kA s yn c ( new Uri ( string .
Format ( " http :// free . worldweatheronline . com /
feed / weather . ashx ? q ={ 0 }& format = json &
num_of_days = 5 & key = MA_CLE_API " , NomVille .
Replace ( ' ', '+ ') ) , UriKind . Absolute ) ) ;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
}
else
}
catch ( Exception )
{
MessageBox . Show ( " Impossible de r cup rer les
informations de m t o , v rifiez votre
connexion internet " ) ;
}
Information . Visibility = Visibility . Visible ;
90
443
92
base . OnNavigatedTo ( e ) ;
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
On commence par tester si la dernire ville consulte existe bien. Si ce nest pas le
cas, nous affichons un petit message pour dire quoi faire. Puis nous dmarrons le tlchargement des conditions de mto, sans oublier danimer la barre de progression.
Aprs avoir attendu la fin du tlchargement (mot cl await), nous pouvons utiliser
JSON.NET pour extraire les conditions mto et les mettre dans la proprit lie au
Pivot. Nous remarquons au passage ma technique hautement labore pour obtenir une
traduction de la description du temps. . . Quoi il manque des traductions ? Nhsitez
pas complter avec les vtres . . . Enfin, les deux mthodes de clic sur les boutons
de la barre dapplication appellent simplement le service de navigation (voir la figure
28.4).
Et si vous griez lorientation multiple maintenant ?
444
CORRECTION
445
446
Quatrime partie
447
Chapitre
29
La gestuelle
Difficult :
Au contraire de la gnration prcdente, Windows Mobile, les Windows Phone sont utilisables exclusivement avec les doigts. Cela peut paraitre vident, mais un doigt est beaucoup
plus large que le pointeur dune souris. Pour les dveloppeurs qui sont habitus crer des
applications ou des sites web utilisables avec une souris, il faut prendre conscience que les
zones qui sont touchables par un doigt doivent tre tailles en consquence. De plus, les
crans des Windows Phone sont multipoints, cest--dire que nous pouvons exercer plusieurs points de pressions simultans, avec notamment plusieurs doigts. Ce qui offre tout
une gamme de nouvelles faons dapprhender linteraction avec lutilisateur. Malheureusement, il est difficile de faire du multipoint avec une souris dans lmulateur. Il est prfrable
dans ce cas dutiliser directement un tlphone.
449
Le simple toucher
Nous lavons vu plusieurs reprises, cest le mode dinteraction le plus pratique et
le plus naturel pour lutilisateur. Il utilise un doigt pour toucher lcran. Geste trs
classique qui ressemble trs fortement un clic dune souris. Le doigt est utilis pour
slectionner un lment. En gnral, les contrles qui ont besoin dtre slectionns par
une pression exposent un vnement Tap. Cest le cas par exemple des boutons que
nous avons vu :
1
< Button x : Name = " MonBouton " Content = " Cliquez - moi " Tap = "
MonBouton_Tap " / >
< Button x : Name = " MonBouton " Content = " Cliquez - moi " Click = "
MonBo uton_Click_1 " / >
Nous lavons vu par exemple sur la barre dapplication, mais il est prsent un peu
partout. Cet vnement est hrit de Silverlight pour PC, il reste cependant utilisable
mais il est dconseill pour des raisons notamment de performance. Nous lui prfrerons
lvnement Tap, comme on la dj vu. Il existe dautres vnements, toujours hrits
de Silverlight, comme lvnement MouseLeftButtonDown :
1
< Rectangle Width = " 200 " Height = " 200 " Fill = " Aqua "
M ou s e LeftButtonDown = " R e c t a n g l e _ M o u s e L e f t B u t t o n D o w n " / >
Il correspond lvnement qui est lev lorsque lon touche un contrle. Lvnement
MouseLeftButtonUp est quant lui lev quand le doigt est relev. Mais le toucher
simple ne sert pas qu cliquer , il permet galement darrter un dfilement. Voyez
par exemple lorsque vous faites dfiler une ListBox bien remplie, si vous touchez la
ListBox et que vous lancez le doigt vers le bas, la liste dfile vers le bas en fonction de la
vitesse laquelle vous avez lanc le doigt (ce mouvement sappelle le Flick ). Si vous
retouchez la ListBox, le dfilement sarrtera. Tous ces toucher sont grs nativement
par beaucoup de contrles XAML. Il est alors trs simple de ragir un toucher.
GESTUELLE AVANCE
un tourner de page. Ce flick est galement utilis dans la ListBox pour effectuer un
fort dfilement. Notons encore un autre toucher, le touch and hold qui correspond
un clic long . On maintient le doigt appuy pendant un certain temps. En gnral,
cela fait apparatre un menu contextuel. Enfin, nous avons le pinch et le stretch qui
consistent, avec deux doigts rapprocher ou carter ses doigts. Cest ce mouvement
qui est utilis pour zoomer et d-zoomer.
Il ny a pas de support pour ces gestuelles volues dans les contrles Windows Phone,
aussi si nous souhaitons les utiliser nous allons devoir implmenter par nous-mme ces
gestuelles. Certaines sont plus ou moins faciles. Pour ceux par exemple qui ont dj
implment un drag & drop dans des applications Windows, il devient assez facile dimplmenter le Pan grce aux vnements MouseLeftButtonDown, MouseLeftButtonUp
et MouseMove (qui correspond la souris qui bouge).
Gestuelle avance
Dautres vnements un peu plus complexes sont galement disponibles sur nos
contrles, il sagit des vnements ManipulationStarted, ManipulationDelta, et
ManipulationCompleted. Ce qui est intressant dans ces vnements cest quils
fournissent un paramtre avec beaucoup dinformations sur le toucher. Lvnement
ManipulationStarted est lev au dmarrage de la manipulation fournissant la position dun ou plusieurs points de pression. Au fur et mesure de la gestuelle, cest
lvnement ManipulationDelta qui est lev fournissant des informations par exemple
sur les translations opres. Enfin, la fin de la manipulation, cest lvnement
ManipulationCompleted qui est lev. Par exemple, on pourrait se servir de ces vnements pour dterminer la gestuelle du flick car cet vnement fourni la vlocit
finale du mouvement ainsi que la translation totale. La translation nous renseigne sur
la direction du mouvement et la vlocit nous permet de savoir sil sagit rellement
dun flick et sa puissance .
Bref, ces vnements peuvent fournir beaucoup dinformations sur la gestuelle en cours,
mais cest nous de fournir du code pour interprter ces mouvements, ce qui nest pas
toujours simple. . .
Je pourrais vous faire une petite dmonstration, mais . . . il y a mieux !
Le toolkit la rescousse
Heureusement, dautres personnes ont raliss ces calculs pour nous. Ouf ! Mme si cela
pourrait tre trs intressant de prendre en compte des considrations de moteur physique pour dterminer la puissance dun flick, il savre que cest une tche fastidieuse.
Cest l quintervient nouveau le toolkit et ses contrles de gestuelle.
Prenez justement le Flick, il suffit de faire dans le XAML :
1
2
< Rectangle Width = " 300 " Height = " 300 " Fill = " Aqua " >
< toolkit : GestureService . GestureListener >
451
3
4
5
6
Description
Simple toucher
Deux touchers rapprochs
Mouvement rapide dans une direction
Utiliss pour le mouvement du Pan
Reprsente le toucher long
Pour le mouvement du zoom
Classe de base pour toutes les gestuelles
LE TOOLKIT LA RESCOUSSE
1
2
3
4
5
6
7
8
< Rectangle Width = " 300 " Height = " 300 " Fill = " Aqua " >
< Rectangle . RenderTransform >
< C om positeTransform x : Name = " Transformation " / >
</ Rectangle . RenderTransform >
< toolkit : GestureService . GestureListener >
< toolkit : GestureListener DragDelta = "
G e s t u re L i s t e n e r _ Dr a g D e l t a " / >
</ toolkit : GestureService . GestureListener >
</ Rectangle >
Difficile dillustrer ce mouvement avec une copie dcran, mais nhsitez pas tester
cet exemple. Vous verrez que le rectangle bouge en fonction de votre mouvement de
type Pan.
Merci le Windows Phone Toolkit !
En rsum
Les Windows Phone tant utilisables exclusivement avec les doigts, il est important de bien grer les gestuelles en utilisant les vnements des contrles.
Le Windows Phone Toolkit nous aide fortement dans limplmentation de ces
gestuelles.
453
454
Chapitre
30
Lacclromtre
Difficult :
Chaque Windows Phone est quip dun acclromtre. Il sagit dun capteur qui permet
de mesurer lacclration linaire suivant les trois axes dans lespace. Ainsi, tout moment,
on peut connaitre la direction et lacclration de la pesanteur qui sexerce sur le tlphone.
Ceci peut nous permettre de raliser des petites applications sympathiques en nous servant
de lorientation du tlphone comme dune interface avec lutilisateur. Dautres capteurs
facultatifs existent sur un Windows Phone, comme le gyroscope ou le compas.
Voyons comment nous en servir.
455
Utiliser lacclromtre
Si le tlphone est pos sur la table et que la table est bien horizontale, nous allons
pouvoir dtecter une acclration d1g sur laxe des Z, qui correspond la force de
lapesanteur. Si lcran est tourn vers le haut, alors lacclration sera de (0, 0, -1) voir la figure 30.1.
tant donn que lacclromtre fourni un objet de Type Vector3, qui fait partie
de la bibliothque XNA, nous aurons besoin dajouter une rfrence lassembly
Microsoft.Xna.Framework.dll (uniquement dans les versions 7.X car pour le SDK
8, la rfrence est dj ajoute).
Il suffit ensuite de sabonner lvnement de changement de valeur et de dmarrer
lacclromtre :
1
2
3
4
456
5
6
7
8
9
10
I ni t i alizeComponent () ;
accelerometre = new Accelerometer () ;
accelerometre . CurrentValueChanged +=
accelerometre_CurrentValueChanged ;
accelerometre . Start () ;
11
12
13
14
15
16
On utilisera le Dispatcher pour pouvoir mettre jour notre contrle dans le thread
ddi linterface :
1
Cet vnement nous fournit les 3 valeurs des diffrents axes. Par contre, partir du
moment o nous dmarrons lacclromtre, nous recevrons un paquet de positions
trs rgulirement. Il est important de pouvoir faire du tri l-dedans. Ne vous inquitez pas si vos valeurs oscillent dans une petite fourchette, cest normal. Mme
si vous tes le plus immobile possible. Suivant vos besoins, vous aurez peut-tre besoin de lisser les informations obtenus, par exemple en faisant une moyenne sur les
X dernires valeurs. Une autre solution est dutiliser une formule un peu plus compliqu, issue du traitement du signal. Je ne rentrerai pas dans ces dtails car nous
nen aurons pas besoin mais vous pouvez retrouver quelques informations en anglais
cette adresse - http://windowsteamblog.com/windows_phone/b/wpdev/archive/
2010/09/08/using-the-accelerometer-on-windows-phone-7.aspx.
Figure 30.3 En dplaant le rond orange, nous simulons une acclration du tlphone
458
EXPLOITER LACCLROMTRE
tlphone afin de faciliter lutilisation de lacclromtre. De mme, la liste en bas
droite permet de simuler un secouage de tlphone. . .
Exploiter lacclromtre
Maintenant que nous savons titiller lacclromtre de lmulateur, utilisons ds prsent les valeurs brutes de lacclromtre pour raliser une petite application o nous
allons faire bouger une balle en bougeant notre tlphone. Nous avons dit que lorsquon
tient le tlphone plat, cran vers le haut, nous avons une acclration de (0,0,-1).
Lorsquon incline le tlphone vers la gauche, on tend vers lacclration suivante (1,0,0). Lorsquon incline vers la droite, on tend vers lacclration (1,0,0). De la mme
faon, lorsquon incline le tlphone vers lavant, on tend vers (0,1,0) et lorsquon incline
vers nous, on tend vers (0,-1,0).
On peut donc utiliser la force des composantes du vecteur pour faire bouger notre balle.
Utilisons un Canvas et ajoutons un cercle dedans :
1
2
3
4
5
6
7
< Canvas x : Name = " LayoutRoot " Background = " Transparent " Width =
" 480 " Height = " 800 " >
< Ellipse x : Name = " Balle " Fill = " Blue " Width = " 50 " Height = "
50 " / >
</ Canvas >
8
9
4
5
6
7
public MainPage ()
{
I ni t i alizeComponent () ;
8
9
10
11
12
13
459
14
15
16
17
18
19
20
21
22
if ( x
x
if ( y
y
if ( x
x
if ( y
y
23
24
25
26
27
28
29
30
<= 0 )
= 0;
<= 0 )
= 0;
>= LayoutRoot . Width - Balle . Width )
= LayoutRoot . Width - Balle . Width ;
>= LayoutRoot . Height - Balle . Height )
= LayoutRoot . Height - Balle . Height ;
31
32
33
34
35
}) ;
36
37
38
39
40
41
42
43
44
45
46
47
48
460
double vitesse = 3 . 5 ;
double x = ( double ) Balle . GetValue ( Canvas . LeftProperty ) + e .
SensorReading . Acceleration . X * vitesse ;
La balle va cette fois-ci un peu plus vite. Mais elle pourrait avoir un peu plus dinertie, et
notamment freiner lorsquon redresse le tlphone. Noubliez pas que plus le tlphone
est plat et plus Z tend vers -1. On peut donc trouver une formule o le fait que le
tlphone soit plat ralentisse la balle, en divisant par exemple par la valeur absolue de
Z:
1
2
3
4
Bon, on est loin dun vrai moteur physique simulant lacclration, mais cest dj un
peu mieux.
Attention faire en sorte que Z soit toujours diffrent de zro, sinon cest la
mga honte. Je crois que diviser par zro cest vraiment la pire des exceptions
que lon peut avoir.
Attention, noubliez pas darrter lacclromtre quand vous avez fini avec lui grce
la mthode Stop() afin dconomiser la batterie. Cest ce que je fais dans la mthode
OnNavigatedFrom().
if (! Compass . IsSupported )
{
MessageBox . Show ( " Votre t l phone ne poss de pas de compas " )
;
}
De mme, le gyroscope est facultatif sur les Windows Phone. Il sert mesurer la
vitesse de rotation suivant les trois axes. Il est diffrent de lacclromtre. Pour voir la
diffrence entre les deux, imaginez-vous debout avec le tlphone en position portrait
devant vous, face au nord. Si vous faites un quart de tour vers la droite, vous vous
retrouvez face lest, le tlphone na pas chang de position dans vos mains, mais il
461
if (! Gyroscope . IsSupported )
{
MessageBox . Show ( " Votre t l phone ne poss de pas de
gyroscope " ) ;
}
La motion API
Travailler avec tous ces capteurs en mme temps est plutt complexe. De plus, si jamais
il manque au tlphone un capteur que vous souhaitez utiliser, il vous faut revoir vos
calculs pour adapter votre application. Cest l quintervient la motion API, que lon
peut traduire en API de mouvement. Elle permet de grer toute la logique mathmatique associe ces trois capteurs afin de fournir des valeurs facilement exploitables.
Au final, on arrive trs facilement dterminer comment le tlphone est orient dans
lespace. Cela permet par exemple de transposer le tlphone dans un monde 3D virtuel, permettant les applications de ralit augmente, les jeux et pourquoi pas des
applications auxquelles nous navons pas encore pens. . .
La motion API sutilise grosso modo comme lacclromtre. Elle nous fournit plusieurs
valeurs avec notamment une proprit Attitude que lon peut traduire en assiette ,
dans le langage de laviation, qui permet dobtenir lorientation de lavion dans lespace. Cette proprit nous fournit plusieurs valeurs intressantes qui, toujours dans le
domaine de laviation, sont :
Yaw : qui indique la direction par rapport au nez de lavion, afin de savoir si
lavion tourne droite ou gauche ;
Pitch : qui indique si le nez de lavion monte ou descend ;
Roll : qui permet de savoir si lavion bascule sur la droite ou la gauche.
Grosso modo, imaginons que vous ayez le tlphone pos sur la table devant vous, avec
les boutons proches de vous :
Si vous lui faite faire une rotation sur la table, tout en le conservant pos sur la
table, alors vous changez le Yaw.
Si vous levez le tlphone pour lavoir en position verticale, alors vous changez
le pitch.
Si vous basculez le tlphone pour le mettre sur sa tranche, alors vous changez
le roll.
On peut le reprsenter ainsi (voir la figure 30.4).
Mme si je ne doute pas de la qualit de mon dessin ( :- ), le mieux pour comprendre
est de lexprimenter sur un vrai tlphone. Pour obtenir ces valeurs, il vous suffit
462
LA MOTION API
Avec le code-behind :
1
2
3
4
5
6
7
8
public MainPage ()
{
I ni t i alizeComponent () ;
}
9
10
11
12
13
14
463
16
return ;
17
if ( motion == null )
{
motion = new Motion { TimeBetweenUpdates = TimeSpan
. FromMilliseconds ( 20 ) };
motion . CurrentValueChanged +=
motion_CurrentValueChanged ;
}
18
19
20
21
22
23
try
{
24
25
26
27
28
29
30
31
32
motion . Start () ;
}
catch ( Exception ex )
{
MessageBox . Show ( " Impossible de d marrer l ' API . " ) ;
}
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
}) ;
464
LA MOTION API
Vous ne pourrez malheureusement pas tester lAPI motion dans lmulateur,
celle-ci nest pas supporte. Et vous ne savez pas encore comment dployer
une application sur votre tlphone, sauf si vous tes alls vers la fin du cours
en avance !
En plus de lassiette, lAPI motion fourni dautres valeurs :
DeviceAcceleration, qui est la mme chose que ce que lon obtient avec lacclromtre.
DeviceRotationRate, qui est la mme chose que ce que lon obtient avec le
gyroscope.
Gravity, qui renvoie un vecteur en direction du centre de la terre, pour reprsenter la gravit, comme avec lacclromtre.
Vous avez compris que ces valeurs peuvent tre obtenues avec les mthodes propres
aux capteurs et que ce qui est vraiment intressant, ce sont les valeurs calcules de
lassiette.
En rsum
Lacclromtre est un capteur obligatoire sur tout tlphone Windows Phone
qui nous offre de nouvelles faons dinteragir avec notre utilisateur.
Il est facile muler grce aux outils de lmulateur Windows Phone.
Dautres capteurs facultatifs existent, comme le gyroscope ou le compas.
La motion API nous simplifie grandement la dtection de lorientation du tlphone dans lespace et nous ouvre les portes de la ralit augmente.
465
466
Chapitre
31
467
469
La mthode GetPosition nous fournit la position du doigt par rapport la page courante, que nous pouvons obtenir grce la proprit RootVisual de lapplication - http:
//msdn.microsoft.com/fr-fr/library/system.windows.application.rootvisual(v=
vs.95).aspx. Ainsi, il sera possible de dterminer les lments qui sont slectionns et
les supprimer de devant le TextBlock.
Passons maintenant au secouage. Comment dtecter que lutilisateur secoue son tlphone ? Il y a plusieurs solutions. Celle que jai choisi consister dtecter un cart
significatif entre les deux dernires acclrations du tlphone. Si cet cart se reproduit
plusieurs fois, alors je peux considrer quil sagit dun secouage. Par contre, si lcart
passe sous un certain seuil, alors je dois arrter dimaginer un potentiel secouage.
Allez, cest vous de jouer.
Correction
Alors, vous avez trouv comment ? Facile ? Difficile ? Ce nest pas toujours facile de
se confronter directement ce genre de situations, surtout lorsquon a lhabitude de
raliser des applications clientes lourdes ou web, ou mme lorsquon a pas du tout
lhabitude de raliser des applications.
Voici la correction que je propose. Tout dabord le menu, vous savez faire, il sagit de
ma page MainPage.xaml qui renvoie vers deux autres pages :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " TP Jeux de
hasard " Style = " { StaticResource PhoneTextNormalStyle }
"/>
< TextBlock x : Name = " PageTitle " Text = " Menu " Margin = "9 , -7 ,
0 , 0 " Style = " { StaticResource PhoneTextTitle1Style } " / >
</ StackPanel >
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< StackPanel >
< Button Content = " Grattage ... " Tap = " Button_Tap " / >
< Button Content = " Secouage ... " Tap = " Button_Tap_1 "
/>
</ StackPanel >
</ Grid >
</ Grid >
CORRECTION
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
4
5
6
7
8
9
10
11
12
13
14
15
16
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12
, 17 ,0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " Grattage
" Style = " { StaticResource PhoneTextNormalStyle } "
/>
</ StackPanel >
< Canvas x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0
, 12 , 0 " >
< TextBlock x : Name = " TextBlock1 " Width = " 100 " Height = "
100 " Canvas . Top = " 10 " Canvas . Left = " 40 " Margin = " 20
30 0 0 " >
< toolkit : GestureService . GestureListener >
< toolkit : GestureListener DragStarted = "
G e s t u r e L i s t e n e r _ D r a g S t a r t e d " DragDelta = "
G e s t u r eL i s t e n e r _ D ra g D e l t a " DragCompleted
=" GestureListener_DragCompleted " />
471
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Comme je lai propos, jai simplement ajout trois TextBlock dans un Canvas. Remarquez que jai spcifi exhaustivement les largeurs et les hauteurs de chacun. Sur
chaque TextBlock, je suis galement lcoute des trois vnements de drag & drop.
Rien de bien compliqu. Cest cot code-behind que cela se complique.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
472
public Grattage ()
{
I nitializeComponent () ;
random = new Random () ;
}
CORRECTION
16
17
18
19
20
21
22
23
base . OnNavigatedTo ( e ) ;
Nous dclarons dans un premier temps plusieurs variables qui vont nous servir dans la
classe. Il y a notamment un gnrateur de nombre alatoires, initialis dans le constructeur. Ensuite, cela se passe dans la mthode Init(). Il faut dans un premier temps
crer plein de petits rectangles afficher par-dessus chaque TextBlock :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
nbRects = 0 ;
for ( double j = 0 ; j < textBlock . Height ; j +=
largeurRectangle )
{
for ( double i = 0 ; i < textBlock . Width ; i +=
largeurRectangle )
{
double width = largeurRectangle ;
double height = largeurRectangle ;
if ( i + width > textBlock . Width )
width = textBlock . Width - i ;
if ( j + height > textBlock . Height )
height = textBlock . Height - j ;
473
33
34
35
36
37
38
39
40
Le principe est de rcuprer la position de chaque TextBlock dans le Canvas puis de gnrer plein de petits rectangles qui couvrent la surface du TextBlock. Chaque rectangle
est positionn dans le Canvas et ajout celui-ci. Notez que jen profite pour rattacher
chaque rectangle son TextBlock grce la proprit Tag, cela sera plus simple par
la suite pour dterminer quel rectangle on peut supprimer. Remarquons au passage
que nous utilisons le gnrateur de nombre alatoire pour dterminer quel TextBlock
est le gagnant. Viens ensuite le grattage en lui-mme. Cest lors du dmarrage de la
gestuelle drag & drop que nous allons pouvoir dterminer le TextBlock choisi. Comme
je lavais indiqu, jutilise la mthode FindElementsInHostCoordinates partir des
coordonnes du doigt. Puis, je peux utiliser le mme principe lors de lexcution de la
gestuelle, rcuprer le Rectangle cette position et lenlever du Canvas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
474
CORRECTION
RootVisual ) ;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Enfin, quand la gestuelle est termine, je peux dterminer combien il reste de rectangles
qui recouvrent le TextBlock choisi, et au-dessous dun certain taux, je peux afficher si
cest gagn ou pas. Reste plus qu rinitialiser tout pour offrir la possibilit de rejouer :
1
2
3
4
5
6
7
8
475
Et voil, le grattage est termin. Passons maintenant la partie secouage. Cot XAML
cest plutt simple :
1
2
3
4
5
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " Secouage "
Style = " { StaticResource PhoneTextNormalStyle } " / >
</ StackPanel >
7
8
9
10
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< Grid . RowDefinitions >
< RowDefinition Height = " 100 " / >
< RowDefinition Height = " 100 " / >
< RowDefinition Height = " 100 " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< TextBlock Text = " Secouez le t l phone ... " / >
< ProgressBar x : Name = " Barre " Grid . Row = " 1 " Visibility = "
Collapsed " / >
< TextBlock x : Name = " Resultat " Grid . Row = " 2 "
HorizontalAlignment = " Center " / >
< TextBlock x : Name = " Total " Grid . Row = " 3 " / >
</ Grid >
</ Grid >
11
12
13
14
15
16
17
18
19
20
21
22
23
476
CORRECTION
private int cpt ;
10
11
public Secouage ()
{
I ni t i alizeComponent () ;
accelerometre = new Accelerometer () ;
accelerometre . CurrentValueChanged +=
accelerometre_CurrentValueChanged ;
timer = new DispatcherTimer { Interval = TimeSpan .
FromSeconds ( 2 ) };
random = new Random () ;
}
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Attention, noubliez pas darrter lacclromtre lorsque nous nen avons plus
besoin afin dconomiser la batterie.
Il ne reste plus qu grer la dtection du secouage. Comme je vous lai indiqu, il suffit
de comparer la diffrence dacclration suivant un axe entre deux mesures. Si celle-ci
dpasse un certain seuil, alors il y a un premier secouage, si par contre elle repasse
sous un autre seuil, la dtection est interrompue. Jai fix arbitrairement ces valeurs
0.8 et 0.1 car je trouve quelles simulent des valeurs acceptables. Pour mesurer la
diffrence dacclration, je prends la valeur absolue de la diffrence entre la dernire
valeur dacclration sur un axe et la prcdente. Si un changement brutal est dtect,
alors on incrmente le compteur. Sil dpasse 4 alors nous considrons quil sagit dun
vrai secouage de tlphone.
1
2
3
4
477
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
}) ;
if ( derniereAcceleration == null )
{
derniereAcceleration = accelerationEnCours ;
return ;
}
double seuilMax = 0 . 8 ;
double seuilMin = 0 . 1 ;
int maxSecouage = 3 ;
if ( cpt <= maxSecouage && (
Math . Abs ( accelerationEnCours . X derniereAcceleration . X ) >= seuilMax ||
Math . Abs ( accelerationEnCours . Y derniereAcceleration . Y ) >= seuilMax ||
Math . Abs ( accelerationEnCours . Z derniereAcceleration . Z ) >= seuilMax ) )
{
Resultat . Text = string . Empty ;
cpt ++;
if ( cpt > maxSecouage )
{
cpt = 0 ;
Barre . Visibility = Visibility . Visible ;
Barre . IsIndeterminate = true ;
timer . Start () ;
}
}
else
{
if ( Math . Abs ( accelerationEnCours . X derniereAcceleration . X ) >= seuilMin ||
Math . Abs ( accelerationEnCours . Y derniereAcceleration . Y ) >= seuilMin ||
Math . Abs ( accelerationEnCours . Z derniereAcceleration . Z ) >= seuilMin )
{
cpt = 0 ;
}
}
derniereAcceleration = accelerationEnCours ;
Et voil. Un petit jeu qui nous a permis de plonger doucement dans la gestuelle et dans
lutilisation de lacclromtre !
480
Chapitre
32
La golocalisation
Difficult :
De plus en plus de matriels technologiques sont quips de systmes de localisation,
notamment grce aux GPS. Cest galement le cas des tlphones quips de Windows
Phone dont les spcifications imposent la prsence dun GPS. Mais le systme de localisation
est un peu plus pouss que le simple GPS, qui a ses limites. En effet, on se trouve souvent
lintrieur dun immeuble ou entours par des gros murs qui peuvent bloquer le signal
du GPS. . . heureusement, la triangulation base des rseaux WIFI peut prendre la relve
pour indiquer la position dun tlphone. Nous allons pouvoir exploiter la position de notre
utilisateur et raliser ainsi des applications golocalises, nous allons voir dans ce chapitre
comment faire.
481
Dterminer sa position
Il est trs facile de rcuprer sa position, on parle de golocalisation. Pour ce faire, on
pourra utiliser la classe Geolocator - http://msdn.microsoft.com/en-us/library/
windows/apps/windows.devices.geolocation.geolocator qui est le point daccs
au service de localisation. Nous aurons besoin dans un premier temps dindiquer que
notre application utilise le service de localisation en rajoutant la capacit ID_CAP_LOCATION.
Il suffit de la slectionner en double-cliquant sur le fichier WMAppManifest.xml, comme
indiqu sur la figure 32.1.
DTERMINER SA POSITION
Ensuite, il faut avoir une instance de la classe Geolocator et potentiellement indiquer
des paramtres comme la prcision. Utilisons dans un premier temps ce XAML :
1
2
3
4
5
try
{
6
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
}
catch ( U n a u t h o r i z e d A c c e s s E x c e p t i o n )
{
MessageBox . Show ( " Le service de location est d sactiv
dans les param tres du t l phone " ) ;
}
catch ( Exception ex )
{
}
4
5
6
7
8
public MainPage ()
{
I nitializeComponent () ;
}
9
10
11
12
13
14
15
16
17
base . OnNavigatedTo ( e ) ;
18
19
20
21
22
23
24
25
26
base . OnNavigatedFrom ( e ) ;
27
28
29
30
31
32
33
34
35
484
DTERMINER SA POSITION
36
37
38
39
40
41
42
43
44
45
46
47
break ;
case PositionStatus . Initializing :
status = " En cours d ' initialisation " ;
break ;
case PositionStatus . Ready :
status = " Service de localisation pr t " ;
break ;
case PositionStatus . NotAvailable :
case PositionStatus . NotInitialized :
case PositionStatus . NoData :
break ;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Il faut toujours vrifier la bonne disponibilit du GPS, car il peut arriver que lutilisateur veuille explicitement le dsactiver. Cest le cas par exemple lorsque le statut est
gal Disabled. Pour afficher le statut, jai lgrement modifi mon XAML :
1
2
3
En mode par dfaut, le tlphone utilise essentiellement les bornes wifi et les antennes
radios pour faire une triangularisation, ce qui est relativement peu consommateur de
batterie. En mode de prcision forte, le tlphone va utiliser lensemble des moyens
dont il dispose pour nous golocaliser en ngligeant la consommation de batterie. Il
utilisera notamment la puce GPS pour un reprage par satellite.
noter que lon peut indiquer partir de quelle distance (en mtres par rapport la
dernire position trouve) le service de localisation envoie un vnement pour nous indiquer un changement de position. Cela se fait via la proprit MovementThreshold qui
est 0 mtre par dfaut, ce qui implique quun vnement de changement de position
est envoy chaque changement de position. Nous avons galement notre disposition
la proprit DesiredAccuracyInMeters qui permet dindiquer le niveau de prcision
souhait (en mtres) pour les donnes renvoyes depuis le service de localisation.
487
7
8
9
10
}) ;
En rsum
Le service de localisation est accessible partir du moment o il a t dclar
et accept par lutilisateur.
La classe Geolocator permet dobtenir les informations issues du service de
localisation.
On peut utiliser le contrle de carte pour afficher sa position, en utilisant la
classe GeoCoordinate.
488
Chapitre
33
489
Les choosers
Les choosers, comme le nom le suggre aux anglophones, permettent de choisir une
information. Plus prcisment, il sagira de dmarrer une fonctionnalit qui va nous
renvoyer quelque chose dexploitable, par exemple un contact dans le rpertoire. Voici
une liste des choosers des Windows Phone 8 :
Chooser
AddressChooserTask
AddWalletItemTask
CameraCaptureTask
EmailAddressChooserTask
GameInviteTask
PhoneNumberChooserTask
PhotoChooserTask
SaveContactTask
SaveEmailAddressTask
SavePhoneNumberTask
SaveRingtoneTask
Description
Dmarre lapplication Contacts pour
choisir une adresse physique
Dmarrer lapplication Wallet
(portefeuille) afin de permettre dy
ajouter un produit
Dmarre lappareil photo pour pouvoir
prendre une photo
Dmarre lapplication Contacts pour
choisir une adresse email
Permet dinviter des autres joueurs
participer un jeu en ligne
Dmarre lapplication Contacts pour
choisir un numro de tlphone
Permet de slectionner une photo du
tlphone
Dmarre lapplication Contacts pour
enregistrer un contact
Dmarre lapplication Contacts pour
enregistrer un email
Dmarre lapplication Contacts pour
enregistrer un numro de tlphone
Dmarre lapplication Sonneries
Je ne vais pas tous vous les prsenter en dtail, car ce serait un peu fastidieux, dautant
plus que la description est globalement assez explicite. Sachez cependant que lmulateur ne permet pas de simuler toutes les tches et que vous aurez parfois besoin
dun tlphone pour vous rendre vraiment compte du rsultat. Limportant est que les
choosers renvoient un lment exploiter. Donc globalement, il faudra instancier la
tche, sabonner lvnement de fin de tche et exploiter le rsultat. Par exemple,
pour slectionner une photo disponible dans le tlphone, nous pourrons utiliser le code
suivant :
1
2
3
4
5
6
7
490
public MainPage ()
{
I nitializeComponent () ;
LES CHOOSERS
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Comme vous pouvez le constater, la photo slectionne est dans le paramtre de lvnement. Celui-ci possde galement un rsultat de tche, par exemple, nous naurons
une valeur dans la proprit ChosenPhoto que si lutilisateur est all au bout de la
tche, et qugalement le rsultat soit OK. Cot XAML, nous pourrons avoir :
1
2
3
4
Dans lmulateur, nous avons quelques valeurs bouchonnes pour cette tche, voyez
plutt sur la figure 33.1.
Illustrons encore les choosers avec la tche CameraCaptureTask qui permet de prendre
une photo depuis votre application :
1
2
3
4
5
6
7
8
9
10
public MainPage ()
{
I ni t i alizeComponent () ;
camer aCaptureTask = new CameraCaptureTask () ;
camer aCaptureTask . Completed +=
cameraCaptureTask_Completed ;
}
11
491
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Ici aussi, lmulateur fonctionne en mode bouchon et nous propose une image factice
pour simuler la prise dune photo, comme on peut le voir sur la figure 33.2.
Vous pourrez prendre la photo depuis lmulateur en cliquant avec le bouton droit.
492
LES LAUNCHERS
Les launchers
Les launchers permettent de dmarrer une application sur le tlphone, par exemple
envoyer un mail ou un SMS. Ils fonctionnent comme les choosers mais nattendent pas
dinformations en retour.
Ici aussi, les descriptions parlent delles-mmes. Dans notre application de lecteur de
flux RSS, il aurait par exemple t possible dutiliser le WebBrowserTask au lieu dembarquer le contrle WebBrowser dans nos pages. Il sutilise ainsi :
1
qui dmarre donc Internet Explorer avec la page demande (voir la figure 33.3).
493
Launcher
BingMapsDirectionsTask
BingMapsTask
ConnectionSettingsTask
EmailComposeTask
MapDownloaderTask
MapsDirectionsTask
MapsTask
MapUpdaterTask
MarketplaceDetailTask
MarketplaceHubTask
MarketplaceReviewTask
MarketplaceSearchTask
MediaPlayerLauncher
PhoneCallTask
SaveAppointmentTask
SearchTask
ShareLinkTask
ShareMediaTask
ShareStatusTask
SmsComposeTask
WebBrowserTask
494
Description
Permet de dmarrer lapplication carte
de Windows Phone 7 pour afficher un
itinraire
Permet de dmarrer la carte de
Windows Phone 7, centre sur une
position
Permet dafficher la page de
configuration du rseau
Permet de composer un nouvel email
via lapplication de messagerie
Permet de tlcharger les cartes pour
une utilisation hors ligne
Permet de dmarrer lapplication de
carte pour afficher un itinraire entre
deux points
Permet de dmarrer lapplication de
carte centre sur un emplacement
Permet de tlcharger les mises jour
de cartes
Permet dafficher le dtail dune
application dans le Marketplace
Dmarre lapplication Marketplace
Permet datteindre la fiche des avis
dune application
Affiche les rsultats dune recherche
Marketplace
Dmarre le lecteur de mdia
Permet de passer des appels
Permet denregistrer un rendez-vous
Dmarre une recherche sur le web
Partage un lien sur un rseau social
Permet de partager une photo ou
vido avec les applications qui se sont
enregistres pour les exploiter
Partage un message de statut sur un
rseau social
Permet de composer un SMS
Dmarre le navigateur web
LES LAUNCHERS
ETAT DE LAPPLICATION
calculer litinraire. Vous pouvez affecter la proprit mapsDirectionsTask.Start afin
de prciser un point de dpart diffrent de la position courante de lutilisateur. Vous
pouvez galement spcifier des coordonnes GPS comme point darrive, et dans ce
cas-l, la chane passe est utilise comme tiquette :
1
2
Il est de bon ton dencadrer la mthode Show() dun launcher ou dun chooser
par un try/catch, surtout si lappel la mthode Show() est fait dans
un bouton. Si vous dmarrez deux tches en mme temps, par exemple en
appuyant deux fois rapidement sur le bouton, vous aurez une exception qui
fera planter lapplication.
Etat de lapplication
Comme nous lavons dj appris, lorsquest dmarre une nouvelle application, lapplication en cours passe en mode suspendu et peut potentiellement tre termine. Cela
veut dire que lorsque nous dmarrons un chooser ou un launcher, il est possible que
votre application soit arrte. Il faut donc que vous veilliez enregistrer ltat de votre
application au cas o celle-ci serait arrte. Mais en plus, dans le cas du chooser, il
pourrait arriver que votre application soit termine avant davoir rcupr la rponse
du chooser, ce qui pose un problme. Pour viter cela, en instanciant un chooser, Windows Phone est capable de vrifier la prsence dune information dans celui-ci. Cela
implique que lvnement de fin de choix soit dfini sur une variable dinstance de la
classe et non dans une mthode, comme ce que jai montr dans les exemples de chooser. On ne doit pas dclarer un chooser par exemple dans le constructeur de notre page.
Linstanciation correcte du chooser doit donc tre :
1
2
3
4
5
6
7
8
9
10
public MainPage ()
{
I ni t i alizeComponent () ;
e m a i l Ad d re ss C ho os er T as k = new E ma i lA dd re s sC ho o se rT as k ()
;
e m a i l Ad d re ss C ho os er T as k . Completed +=
emailAddressChooserTask_Completed ;
}
11
12
497
13
14
15
16
if ( e . TaskResult == TaskResult . OK )
MessageBox . Show ( " Adresse choisie : " + e . Email ) ;
17
18
19
20
21
22
En rsum
Les launchers et les choosers offrent une solution pour interagir avec dautres
applications du tlphone trs facilement.
Ils permettent davoir une exprience utilisateur propre et cohrente pour utiliser
les applications internes du tlphone.
Un chooser doit tre dclar dans la porte dune page.
498
Chapitre
34
Les tuiles
Difficult :
Les tuiles, ce sont les icnes reprsentant nos applications prsentes sur la page daccueil
dun Windows Phone. Elles sont un raccourci pour dmarrer les applications prsentes dans
notre tlphone, un peu comme les icnes prsentes sur le bureau de nos vieux Windows.
Pour linstant, rien dextraordinaire vous me direz !
Mais elles sont un peu plus quune simple icne permettant de dmarrer une application.
Elles peuvent avoir une icne mais galement du texte fournissant des informations sur
lapplication ou son contexte. Elles peuvent galement tre animes et sont une des grandes
forces de Windows Phone. Dailleurs, Windows 8 sest empress de se les rcuprer.
Prsentes en une seule taille avec Windows Phone 7.5, elles se dclinent en trois tailles
partir de Windows Phone 7.8, pour le plus grand plaisir des utilisateurs qui les ont adoptes
avec intrt.
Dcouvrons prsent ces fameuses tuiles.
499
Figure 34.3 Notre application est pingle et nous voyons sa tuile sur la page daccueil
501
Flip et cycle
159x159
336x336
691x336
Iconic
110x110
202x202
-
Nul besoin de vous soucier des diffrentes rsolutions, Windows Phone soccupe de
redimensionner tout pour nous, vous navez besoin que dajouter les images pour la
rsolution XWGA.
5
6
7
8
9
10
505
11
12
13
14
15
16
17
18
19
20
21
22
23
On y retrouve les diverses urls relatives vers nos images de tuiles, mais aussi dautres
choses. Modifions par exemple la balise count pour mettre la valeur 3 la place de 0 :
1
public MainPage ()
{
I ni t i alizeComponent () ;
4
5
6
506
7
8
9
10
11
12
13
14
15
16
17
18
19
Une fois la mise jour de la tuile faite, nous pourrons avoir un nouveau rendu, illustr
dans la figure 34.11.
Du coup, je vous montre la tuile en grande taille. Notez la prsence du chiffre 4 en
haut droite qui correspond la proprit Count. Mettre 0 ou null dans la proprit
effacera le nombre qui apparat.
Attention : le fait de mettre jour la tuile par dfaut par code npingle pas
pour autant lapplication sur lcran daccueil. Il faut que ce soit une action
volontaire de lutilisateur. Cela changera juste son apparence.
507
508
510
< Message > Venez vite d couvrir Zozor ! </ Message >
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Grid . RowDefinitions >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< StackPanel >
< Button Content = " Grattage ... " Tap = " Button_Tap " / >
< Button Content = " Secouage ... " Tap = " Button_Tap_1 " / >
</ StackPanel >
< StackPanel Grid . Row = " 1 " VerticalAlignment = " Bottom " >
< Button Content = " Cr er tuile grattage " Tap = "
Button_Tap_2 " / >
< Button Content = " Cr er tuile secouage " Tap = "
Button_Tap_3 " / >
</ StackPanel >
</ Grid >
Nous utiliserons grosso modo le mme code et le mme principe pour crer une tuile
secondaire :
511
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Pour viter dajouter plusieurs fois la mme tuile, on pourra se baser sur la proprit
NavigationUri des tuiles existantes, afin de vrifier si elles ont dj t ajoutes. Il ne
reste plus qu cliquer sur nos boutons. Vous verrez que lorsque la tuile secondaire
est cre, nous sommes renvoys sur la page daccueil pour voir le rsultat (voir figure
512
3
4
5
6
7
8
9
10
513
Vous pouvez voir ce que donne ce bout de code sur la figure 34.17.
Bien sr, vous pouvez crer des tuiles secondaires dans tous les modles que vous
souhaitez. Illustrons par exemple le modle cyclique :
1
2
3
4
5
6
7
8
9
10
514
};
14
15
16
17
ShellTile . Create ( new Uri ( " / VieZozor . xaml " , UriKind . Relative
) , tuile , false ) ;
2
3
4
5
6
7
8
9
10
11
Il nest par contre pas possible de modifier lURL de la page afficher. Dans ce cas,
il faudra la supprimer puis la recrer. Supprimer une tuile secondaire est trs facile, il
suffit dutiliser la mthode Delete. Par exemple, si nous souhaitons supprimer la tuile
du secouage, nous pourrons crire :
1
2
3
Lutilisateur pourra bien sr faire la mme chose tout seul depuis lcran daccueil.
Attention, on peut supprimer une tuile secondaire, par contre il est impossible
de supprimer la tuile principale par code.
515
En rsum
Les tuiles se trouvent sur la page daccueil dun Windows Phone et sont un
raccourci volu permettant de dmarrer une application.
Elles sont disponibles en plusieurs tailles : petite, moyenne ou grande.
Il existe plusieurs modles de tuiles : tuile icne ( iconic ), tuile cyclique ( cyclic ), tuile qui se retourne ( flip ).
Il est possible de crer des tuiles secondaires, qui permettent daccder une
application laide de raccourcis supplmentaires.
516
Chapitre
35
Les notifications
Difficult :
Le principe des notifications nest pas vraiment nouveau mais est globalement plutt simple.
Imaginons que jinstalle une application qui me permette de consulter les cours de la plateforme OpenClassrooms. Ca y est, jai lu tous les cours qui mintressent et jai hte que de
nouveaux cours voient le jour pour que je puisse assouvir ma soif dapprendre. Sauf que je
ne vais pas dmarrer lapplication toutes les 5 minutes histoire de voir si un nouveau cours
est en ligne . . . a serait bien si quelquun me prvenait ds quun nouveau cours est mis
en ligne. Et tout a, mme si lapplication nest pas dmarre ou pingle . . .
517
1.
2.
3.
4.
Envoi immdiat
Tile
Toast
Raw
1
2
3
Dlai de 450
secondes (7
minutes et demie)
11
12
13
Dlai de 15
minutes
21
22
23
Par exemple, pour envoyer une notification Toast immdiatement, je devrais avoir
len-tte HTTP suivante :
1
2
Enfin, pour envoyer un message de type tile, nous aurons le XML suivant :
<?xml version="1.0" encoding="utf-8"?>
<wp:Notification xmlns:wp="WPNotification">
521
<wp:Tile>
<wp:BackgroundImage>Url image de fond</wp:BackgroundImage>
<wp:Count>Numro en haut droite</wp:Count>
<wp:Title>Titre</wp:Title>
<wp:BackBackgroundImage>Url image de fond du dos de la tuile</wp:BackBackgroundImage
<wp:BackTitle>Titre du dos de la tuile</wp:BackTitle>
<wp:BackContent>Contenu du dos de la tuile</wp:BackContent>
</wp:Tile>
</wp:Notification>
Nous allons voir dans le chapitre suivant comment envoyer ces beaux messages et
surtout ce quil faut faire ct Windows Phone pour crer un canal et ragir aux
notifications.
Note : Si vous devez mettre des caractres spciaux dans vos messages, alors
vous devez les encoder en XML, par exemple < devient < ;
public MainPage ()
{
I ni t i alizeComponent () ;
4
5
6
7
8
9
10
11
if ( canal == null )
{
// si le canal n ' est pas trouv , on le cr e
canal = new H tt p No ti fi c at io nC h an ne l ( nomCanal ) ;
12
13
14
canal . ChannelUriUpdated += ca na l _C ha nn e lU ri Up d at ed ;
canal . ErrorOccurred += canal_ErrorOccurred ;
15
16
522
17
18
19
canal . Open () ;
20
21
22
23
}
else
{
24
25
26
27
28
29
30
31
32
33
34
35
36
Si le canal existe dj, alors on obtient son URL qui normalement devra tre envoye
notre serveur de notififcation. Ici, je vais simplement lafficher dans la console de sortie
pour viter de devoir crer un serveur de notification. Je vais ainsi pouvoir rcuprer
lURL et lutiliser dans une application tierce qui enverra la requte au serveur de
notification de Microsoft. Pour linstant, implmentez les vnements ainsi :
1
2
3
4
5
6
7
8
10
11
523
13
14
15
16
Puis dmarrez lapplication en debug, lURL saffiche dans la fentre de sortie de Visual
Studio comme dans la figure 35.2.
<? xml version = " 1 . 0 " encoding = " utf - 8 " ? >
< wp : Notification xmlns : wp = " WPNotification " >
< wp : Toast >
< wp : Text1 > Texte 1 youpi </ wp : Text1 >
< wp : Text2 > Texte 2 joie </ wp : Text2 >
< wp : Param >/ MainPage . xaml ? cle = parametre </ wp : Param >
</ wp : Toast >
</ wp : Notification >
Le principe est donc de faire une requte POST, avec les bons headers, contenant le
message de type toast, et de le poster lurl rcupre. Voici le code C# permettant
de raliser ceci dans une application console :
1
2
3
4
5
6
try
{
7
8
9
10
11
12
13
14
15
16
17
525
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
}
catch ( Exception ex )
{
Console . WriteLine ( " Erreur d ' envoi : " + ex ) ;
}
Et nous verrons la notification Toast safficher sur notre Windows Phone (voir figure
35.3).
Et ce qui est intressant, cest que si lon clique sur la notification toast, alors notre
application se lance et navigue sur la page passe en paramtre. Ceci nous permet galement de rcuprer les paramtres de la query string (voir code et figure qui suivent).
1
2
526
string valeur ;
if ( NavigationContext . QueryString . TryGetValue ( " cle " , out
valeur ) )
{
MessageBox . Show ( valeur ) ;
}
base . OnNavigatedTo ( e ) ;
canal . BindToShellToast () ;
canal . BindToShellTile () ;
Pour les notifications raw, il ny a rien de spcial faire sur le canal. Il faudra par
contre sabonner lvnement HttpNotificationReceived :
1
2
3
4
5
6
7
8
9
10
11
[...]
canal . H t t p N o t i f ic a t io n R e ce i v ed +=
canal_HttpNotificationReceived ;
[...]
private void c a n a l _ H t t p N o t i f i c a t i o n R e c e i v e d ( object sender ,
H t t p N o t i f i c a t i o n Ev e n t A r g s e )
{
using ( System . IO . StreamReader reader = new System . IO .
StreamReader ( e . Notification . Body ) )
{
string message = reader . ReadToEnd () ;
Dispatcher . BeginInvoke (() = > MessageBox . Show ( "
Notification raw re ue : " + message ) ) ;
}
}
Remarque : Il est demand de pouvoir dsactiver les notifications depuis lapplication. Pensez rajouter une interface qui permet lutilisateur de se
dsabonner.
En rsum
Les notifications permettent denvoyer un message ou une demande de mise
jour de tuile.
La notification de type toast peut-tre reue mme si lapplication nest pas
dmarre.
Le dveloppeur aura besoin de crer un serveur de notification, accessible
tout moment, afin de maintenir une liste de canaux de communication avec les
tlphones intresss pour recevoir des notifications.
529
530
Chapitre
36
531
En rsum, je vous propose de raliser les lments suivants : 1. Utiliser le GPS pour
permettre de vous golocaliser, 2. Rajouter un bouton dans la barre dapplication pour
afficher la mto votre position, 3. Rajouter deux tuiles de raccourci affichant la
mto Paris et Toulouse.
Voil, vous avez tout. vous de jouer.
Correction
Je suis certain que vous vous en tes trs bien sorti avec ce petit exercice sympathique.
Voici ma correction, je ne vais pas tout re-dtailler mais simplement les choses qui ont
chang par rapport au TP prcdent dapplication mto.
1. Utiliser le GPS pour vous golocaliser Nous avons premirement besoin dutiliser le GPS afin de nous golocaliser. Vous devez utiliser la classe Geolocator, via par
exemple une variable prive :
1
532
CORRECTION
Vous initialisez cette variable geolocator dans le constructeur :
1
2
3
4
5
6
public MainPage ()
{
I ni t i al i zeComponent () ;
geolocator = new Geolocator () ;
DataContext = this ;
}
4
5
6
7
Pour la peine, je me suis ralis une petite image pour symboliser le GPS. Vous ne
manquerez pas dadmirer ma matrise de Paint (image dans le chapitre suivant) ! Noubliez pas de changer les proprits de limage pour mettre laction de gnration
Contenu , et la proprit Copier dans le rpertoire Copier si plus rcent .
Lorsque lon clique sur le bouton, une mthode est appele pour dmarrer le service de
localisation :
1
2
3
4
5
6
533
8
9
10
11
12
13
14
15
16
17
18
}
catch ( Exception )
{
MessageBox . Show ( " Vous devez activer le GPS pour pouvoir
utiliser cette fonctionnalit " ) ;
ChargementEnCours = false ;
}
8
9
10
11
12
13
14
15
16
534
CORRECTION
}
}
liste . Add ( meteo ) ;
17
18
19
20
21
22
23
}
ListeMeteo = liste ;
Charg ementEnCours = false ;
11
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< Grid . RowDefinitions >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< toolkit : ListPicker x : Name = " Liste " ItemsSource = " { Binding
ListeVilles } "
Header = " Ville choisie : "
CacheMode = " BitmapCache " >
</ toolkit : ListPicker >
< Button Grid . Row = " 1 " VerticalAlignment = " Bottom " Content = "
Epingler " x : Name = " BoutonEpingle " Tap = " BoutonEpingle_Tap "
/>
</ Grid >
5
6
7
8
9
10
11
12
13
14
15
Bien sr, dans la query string, on indique le nom de la ville afin de pouvoir lexploiter
535
7
8
9
9
10
11
12
13
14
15
16
17
18
19
20
536
26
}
else
27
28
29
TraiteResultats ( resultatMeteo ) ;
}
catch ( Exception )
{
MessageBox . Show ( " Impossible de r cup rer les
informations de m t o , v rifiez votre connexion
internet " ) ;
}
Information . Visibility = Visibility . Visible ;
30
31
32
base . OnNavigatedTo ( e ) ;
Remarquez quune fois que jai extrait lventuelle ville passe en paramtre
dans la query string, je la supprime afin que lapplication ne soit pas bloque
sur cette ville.
Et le tour est jou. Voici une belle application mto qui exploite les infos de golocalisation et qui nous permet mme davoir des raccourcis vers nos villes favorites. Pas
mal comme TP, non ?
537
10
11
12
13
14
15
16
17
18
19
20
21
TimeSpan . FromSeconds ( 10 ) ) ;
position = geoposition . Coordinate . Latitude . ToString (
NumberFormatInfo . InvariantInfo ) + " ," + geoposition .
Coordinate . Longitude . ToString ( NumberFormatInfo .
InvariantInfo ) ;
string resultatMeteo = await client .
D ow nl oa d St ri n gT as kA s yn c ( new Uri ( string . Format ( " http
:// free . worldweatheronline . com / feed / weather . ashx ? q ={
0 }& format = json & num_of_days = 5 & key = MA_CLE_API " ,
position , UriKind . Absolute ) ) ) ;
TraiteResultats ( resultatMeteo ) ;
}
catch ( Exception )
{
MessageBox . Show ( " Vous devez activer le GPS pour pouvoir
utiliser cette fonctionnalit " ) ;
ChargementEnCours = false ;
return ;
}
try
{
string json = await client . Do w nl oa dS t ri ng T as kA sy n c ( new
Uri ( string . Format ( " http :// maps . googleapis . com / maps /
api / geocode / json ? latlng ={ 0 }& sensor = true " , position ) ,
UriKind . Absolute ) ) ;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
538
41
42
43
44
45
46
47
}
catch ( Exception )
{
MessageBox . Show ( " Impossible de d terminer le g ocodage
invers " ) ;
}
539
540
Chapitre
37
541
Le thread dinterface
Le thread dinterface (UI Thread) va servir mettre jour linterface ; ce quon voit
lcran. En loccurrence, il va servir crer les objets depuis le XAML et dessiner
tous les contrles. Il gre galement toutes les interactions avec lutilisateur, notamment tous les touchers. Il est donc trs important que ce thread soit le moins charg
possible afin que lapplication reste ractive, notamment aux actions de lutilisateur. Si
ce thread contient une longue srie de codes excuter, alors linterface sera bloque
et lutilisateur ne pourra plus rien faire, ce qui est fortement dplaisant et risque de le
faire trs vite dsinstaller votre application. . . Essayez plutt de rpartir les tches, en
imaginant que vous avez deux boutons dans votre page : lun qui fait une action longue
et lautre qui affiche simplement un message dans une bote. Voici le code de la bote
contenant les deux boutons :
1
2
3
4
10
11
12
542
LE THREAD DINTERFACE
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Ceci nous permet de simuler un traitement long tout en conomisant des lignes de
codes, do le code-behind devient :
1
2
3
4
5
6
7
8
9
8
9
10
11
12
13
14
15
16
17
18
Note : Cette faon de crer des threads nest pas la plus optimale, nous
verrons dautres solutions pour crer des threads.
Maintenant, si vous dmarrez votre application, vous pourrez voir que lexcution du
code long ne bloque plus le traitement du clic sur lautre bouton. joie, merci les
threads ! En fait, notre code est un peu bte ! On fait des calculs mais ils ne nous
servent rien ici . . . Je suis sr que, comme moi, vous seriez trs curieux de connatre
le plus grand nombre premier infrieur 10 millions, nest-ce pas ? Ok, ressortons notre
mthode, utilisons notre thread et affichons le rsultat dans un TextBlock :
1
2
3
544
Sauf que, si vous dmarrez lapplication, que vous lancez le calcul, votre application
va se mettre planter avec une belle erreur du nom de UnauthorizedAccessException
(que lon peut apercevoir dans la figure 37.1).
Pour une simple et bonne raison et je crois quon peut la mettre en avertissement :
Seul le thread UI a le droit de mettre jour linterface. Si nous tentons de
mettre jour un lment de linterface depuis un autre thread, comme un
thread darrire-plan, nous aurons une erreur.
545
Utiliser le Dispatcher
Nous avons dj rapidement vu comment rsoudre ce problme lorsque nous avons utilis des oprations asynchrones (HttpWebRequest et WebClient) et que nous avons d
mettre jour linterface. Nous avons rsolu le problme grce au Dispatcher - http://
msdn.microsoft.com/fr-fr/library/system.windows.threading.dispatcher(v=vs.
95).aspx.
Ce dispatcher permet dexcuter des actions sur le thread auquel il est associ, grce sa
mthode BeginInvoke. En loccurrence, chaque DependyObject possde un dispatcher
et donc, la PhoneApplicationPage possde galement un dispatcher par hritage, qui a
t cr depuis le thread UI. Ainsi, lappel BeginInvoke depuis un thread darrireplan sur le dispatcher de la page excutera automatiquement laction sur le thread UI.
Voyons ceci dans le code et le rsultat illustr suivants.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Utiliser un BackgroundWorker
Je vous ai dit quutiliser directement la classe Thread ntait pas la solution la plus
lgante pour crer des threads. Cest vrai (je ne mens jamais) ! Il existe dautres
classes particulirement adaptes pour raliser des traitements longs sur un thread
darrire-plan, cest le cas par exemple de la classe BackgroundWorker - http://msdn.
microsoft.com/fr-fr/library/system.componentmodel.backgroundworker(v=vs.
546
UTILISER UN BACKGROUNDWORKER
private BackgroundWorker bw ;
public MainPage ()
{
I ni t i al i zeComponent () ;
4
5
6
7
8
9
bw = new BackgroundWorker { W o r k e r S u p p o r t s C a n c e l l a t i o n =
true , Work erRepo rtsPr ogress = true };
bw . DoWork += bw_DoWork ;
bw . ProgressChanged += bw_ProgressChanged ;
bw . R un Wor kerCompleted += bw_R unWork erComp leted ;
Ici, nous lui indiquons quil est autoris dannuler le thread et que celui-ci peut tmoigner de son avancement. Ensuite nous dclarons des vnements. DoWork contiendra le
547
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int max = 0 ;
int derniereValeur = 0 ;
for ( int i = 0 ; i < 10000000 ; i ++)
{
if ( worker . CancellationPending )
{
e . Cancel = true ;
break ;
}
int pourcentage = i * 100 / 10000000 ;
if ( pourcentage != derniereValeur )
{
derniereValeur = pourcentage ;
worker . ReportProgress ( pourcentage ) ;
}
if ( EstNombrePremier ( i ) )
max = i ;
}
e . Result = max ;
On peut retrouver notre long calcul des nombres premiers. On y trouve galement
plusieurs choses, comme de vrifier sil naurait pas t demand notre thread de se
terminer prmaturment. Cela se fait en testant la proprit CancellationPending. Si
elle vaut vrai, alors on peut arrter le calcul et marquer le BackgroundWorker comme
tant annul, grce largument de lvnement. Ensuite, la mthode ReportProgress
nous offre lopportunit dindiquer lavancement du calcul. Ici, je lui indique le pourcentage davancement par rapport au max calculer. Remarquez que je nappelle la
mthode ReportProgress que si le pourcentage davancement a chang car sinon je
lappellerai normment de fois inutilement, ce qui ralentirait considrablement mon
calcul. Enfin, je peux utiliser la proprit Result pour stocker le rsultat de mon calcul.
Vous avez donc compris que lvnement ProgressChanged tait lev lorsque nous appelions la mthode ReportProgress. Cela nous permet de mettre jour un affichage
par exemple pour montrer lavancement du thread :
1
2
3
4
548
UTILISER UN BACKGROUNDWORKER
Notez quici, il ny a pas besoin de Dispatcher pour mettre jour linterface, malgr
lutilisation dun thread darrire-plan. Tout cela est gr par le BackgroundWorker
Enfin, il reste la mthode qui est appele lorsque le calcul est termin, RunWorkerCompleted :
1
2
3
4
5
6
7
8
9
549
550
3
4
5
6
7
8
9
10
11
12
13
14
Rien de bien compliqu, mais il y a cependant une petite astuce pour utilisateurs avancs. Il sagit de lutilisation de la variable numThread. On pourrait croire quelle ne sert
rien et quon pourrait utiliser juste la variable i la place, mais que nenni. Si vous
lenlevez, vous naurez que des threads numrots 10. Tout a, cause dune histoire de
closure que je vais vous pargner, mais si vous tes curieux, vous pouvez trouver une explication en anglais ici - http://blogs.msdn.com/b/ericlippert/archive/2009/11/
12/closing-over-the-loop-variable-considered-harmful.aspx. Vous trouverez
le rsultat en images dans la figure 37.4.
Figure 37.4 Lexcution des threads a t prise en charge par le pool de thread
551
Le DispatcherTimer
Nous avons dj utilis cette classe prcdemment mais sans lavoir vraiment dcrite.
La classe DispatcherTimer - http://msdn.microsoft.com/fr-fr/library/system.
windows.threading.dispatchertimer(v=vs.95).aspx va nous permettre dappeler
une mthode intervalles rguliers. Lintrt va tre de pouvoir excuter une tche en
arrire-plan et de manire rptitive. Imaginons par exemple une tche de synchronisation, qui toutes les 5 minutes va enregistrer le travail de lutilisateur sur le cloud . . .
Lexemple le plus classique est la cration dune horloge, dont lheure est mise jour
toutes les secondes :
1
1
2
3
4
5
public MainPage ()
{
I ni t i alizeComponent () ;
6
7
8
9
10
11
12
13
14
15
Voil notre TextBlock qui est mis jour toutes les secondes. Lavantage de ce timer
cest quil utilise la file dattente du dispatcher, donc nul besoin dutiliser le Dispatcher
pour pouvoir mettre jour linterface, ceci est pris en charge automatiquement. Linconvnient, cest que rien ne nous garantit que la mthode soit effectivement appele
exactement toutes les secondes. Vous pourrez observer quelques variations en fonction
de lexistence dautres timers ou dlments dans le Dispatcher. Si vous laissez tourner
un peu votre application, vous verrez que, de temps en temps, il se dcale dune seconde, ce qui nest pas dramatique, et au pire, nous pouvons augmenter la frquence de
mise jour. Mais le timer va nous permettre aussi dillustrer un autre point important
de Windows Phone, utilisons-le par exemple pour faire bouger un rectangle sur notre
cran. Le XAML est le suivant :
552
LE DISPATCHERTIMER
1
2
3
4
5
6
public MainPage ()
{
I ni t i alizeComponent () ;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Si vous dmarrez lapplication, vous pourrez voir le rectangle qui sanime horizontalement. Ceci pourrait tre une bonne solution pour animer un objet, sauf que . . . cliquez
voir un peu sur le bouton qui bloque le thread UI en simulant un long calcul . . . et paf !
a ne bouge plus. Ah bravo ! Franchement, a ne se fait pas de bloquer le thread UI ! ! !
553
Thread de composition
Vous me direz, il suffit de mettre le calcul dans un thread et je vous rpondrai que oui,
cela fonctionne sans problme. Mais il y a dautres solutions pour faire en sorte quune
animation fonctionne malgr un long calcul. Vous vous rappelez comment on dfinit
une animation via un StoryBoard ?
1
2
3
4
5
6
7
8
9
10
11
12
6
7
MonStoryBoard . Begin () ;
9
10
11
12
13
14
En rsum
Les threads sont importants matriser afin davoir une application fluide et
ractive.
Il nest pas possible de mettre jour linterface depuis un thread darrire-plan.
On utilisera le Dispatcher.
Il existe des classes puissantes du framework .NET pour grer les threads darrireplan.
556
Chapitre
38
557
4
5
6
7
8
558
if ( tuileParDefaut != null )
{
FlipTileData flipTileData = new FlipTileData
{
};
11
12
13
14
15
16
17
NotifyComplete () ;
Vous pouvez constater que nous affichons simplement un message sur le dos de la tuile
avec lheure de dernire mise jour de la tuile. De mme, on dtermine un nombre
alatoire quon affichera dans le cercle en haut droite de la tuile.
Mais ceci ne suffit pas. Il va falloir au moins un premier lancement de lapplication
afin de pouvoir dmarrer la tche et ventuellement permettre de larrter. Dans mon
application de dmo, je vais donc crer deux boutons permettant de respectivement de
dmarrer la tche et de larrter. Voici le XAML :
1
2
3
4
5
6
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 " >
< StackPanel >
< Button Content = " D marrer " Tap = " Button_Tap " / >
< Button Content = " Arr ter " Tap = " Button_Tap_1 " / >
</ StackPanel >
</ Grid >
559
9
10
11
12
13
14
15
16
17
18
19
20
21
La constante nous sert identifier notre tche de manire unique. Maintenant, pour
dmarrer la tche, nous aurons besoin dinstancier un objet de la classe PeriodicTask http://msdn.microsoft.com/en-us/library/windowsphone/develop/microsoft.phone.
scheduler.periodictask, qui comme son nom lindique, est une tche priodique :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
560
15
16
17
18
19
20
21
22
23
24
25
}
catch ( I n v a l id O p e r a t i o n E xc e p t i o n )
{
MessageBox . Show ( " Impossible d ' ajouter la t che p
riodique , car il y a d j trop d ' agents dans le
t l phone " ) ;
}
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Il suffit dinstancier la classe PeriodicTask avec le nom de la tche, de lui donner une
description et de lajouter au service. Faites attention toujours encadrer lajout dune
tche dun try/catch car une exception peut tre leve si nous avons atteint le nombre
maximum dagents que votre tlphone peut supporter. Ensuite, pour nous faciliter le
dbogage, il est possible de dmarrer la tche immdiatement, ceci se fait grce la
mthode LaunchForTest. Cette mthode ne doit pas tre appele directement lorsque
lapplication est termine et prte tre publie.
Remarque : il pourrait tre tout fait judicieux dentourer cette instruction
des instructions conditionnelles de dbug :
1
2
3
# if DEBUG
S c h e d u l e d A ct ion Se rvi ce . LaunchForTest ( NomTache , new TimeSpan
(0 , 0 , 1 ) ) ;
# endif
Vous aurez remarqu quavant de dmarrer la tche, je commence par larrter, si jamais
561
Figure 38.3 Les tches darrire plan dans les paramtres de lmulateur
563
11
12
13
NotifyComplete () ;
5
6
7
8
9
10
11
12
13
toast . Show () ;
14
15
16
17
18
NotifyComplete () ;
Vous voyez, on ne fait rien de formidable, juste crer un nouvel objet de type ShellToast, y mettre lheure et envoyer la notification. Ce serait bien sr lemplacement
idal pour aller voir sur internet sil y a des nouvelles informations envoyer. Ensuite,
lenregistrement de lagent se fait de manire classique dans lapplication :
1
2
3
4
5
6
public MainPage ()
{
565
7
8
StopTache () ;
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
a peut tre plutt pratique et cest quand mme simple mettre en place, sans serveur
de notification (voir la notification darrire-plan dans la figure 38.5).
En rsum
Les Background Agent permettent dexcuter des tches en arrire-plan, des
tches priodiques ou des tches aux ressources intensives.
Ces tches peuvent nous permettre facilement de mettre jour une tuile ou
denvoyer une notification sans que lutilisateur nait besoin de dmarrer lapplication.
Une tche a une dure de vie de 2 semaines, renouvelable chaque fois que
lapplication est dmarre.
566
567
568
Chapitre
39
569
571
SE CONNECTER FACEBOOK
principe de fonctionnement dOAuth est illsutr dans la figure 39.5.
Se connecter Facebook
Pour authentifier un utilisateur, nous allons devoir naviguer sur la page dauthentification de Facebook. Mais comment accder cette fameuse page ? Pour le savoir,
nous allons utiliser le package SDK, mais avant a, nous aurons besoin de rajouter un
WebBrowser dans notre page XAML :
1
< phone : WebBrowser x : Name = " wb " Visibility = " Collapsed " Navigated =
" wb_Navigated " / >
Celui-ci est masqu au chargement de la page (Visibility Collapsed). Nous avons galement associ une mthode lvnement de navigation termin, qui nous permettra
de traiter lauthentification et de rcuprer le jeton. Puis nous allons crer une variable
prive dans notre page, du type FacebookClient pour reprsenter lutilisateur que lon
souhaite authentifier :
1
573
Enfin, nous allons naviguer sur lURL obtenue grce au package SDK. Pour ce faire,
nous allons devoir spcifier un certain nombre de paramtres en crant un dictionnaire
dobjets :
1
2
3
public MainPage ()
{
I ni t i alizeComponent () ;
5
6
7
8
9
10
11
12
13
14
15
16
17
SE CONNECTER FACEBOOK
publish_stream, qui va me permettre de poster un message sur le mur de
lutilisateur.
Attention, demander ces permissions nest pas anodin. Cela permet daccder aux informations personnelles de lutilisateur. On ne peut pas faire cela
dans son dos, il faut que lutilisateur autorise notre application accder
ces informations. Cela se fait juste aprs la connexion de lutilisateur (nous
verrons une copie dcran illustrant ce propos). Ce qui fait que si on demande
trop dinformations, notre utilisateur risque de prendre peur et de rejeter nos
demandes. On se retrouvera ainsi sans la moindre possibilit dexploiter les
donnes de lutilisateur. Il faut donc que nos demandes de permissions soient
le plus proche possible des besoins de lapplication !
Puis nous fournissons lURL de redirection Facebook ainsi que lidentifiant de notre
application, dans le paramtre client_id. Ainsi, aprs lapprobation de nos permissions par lutilisateur, la relation de confiance entre le compte Facebook et notre
application Facebook va pouvoir se crer. Enfin, nous instancions un objet FacebookClient. La mthode GetLoginUrl() va nous retourner lURL de la page de connexion
adquate sur Facebook afin que notre utilisateur puisse sy connecter avec son compte.
Cette mthode ne fait rien dextraordinaire part concatner tous les paramtres. Nous
nous retrouvons avec une URL de la sorte :
1
et il ne reste plus qu naviguer sur cette URL avec le WebBrowser. . . Nous arrivons
sur une page ressemblant celle prsente dans la figure 39.6.
Cest bien une page du site de Facebook. Cest donc Facebook qui nous authentifie
grce sa fentre de login. Entrons nos informations de connexion et validons. Une
fois que lon est connect, Facebook nous demande si nous acceptons la demande de
permission de lapplication Facebook (voir figure 39.7).
Une fois la demande de permission accepte, nous sommes redirigs sur une page
blanche marque success.
Parfait tout a. . . mais, le jeton ? Comment on le rcupre ?
Eh bien cela se fait dans lvnement de navigation auquel nous nous sommes abonns
au dbut. Dans cet vnement, nous allons utiliser la mthode TryParseOAuthCallbackURL de la classe FacebookOAuthResult pour extraire le jeton :
1
575
SE CONNECTER FACEBOOK
3
4
5
6
7
8
9
10
11
12
13
14
Remarque : il est normal que vous nayez pas besoin de ressaisir vos informations chaque fois, le navigateur de lmulateur conserve les cookies de
session.
Toujours est-il quune fois que lURL de ce jeton est rcupre, nous allons pouvoir
faire tout ce que nous voulons. Chouette. Commenons par masquer le WebBrowser,
nous nen aurons plus besoin.
ce moment-l, je trouve quil est plus propre de changer de page en stockant le jeton
dans le dictionnaire dtat et en le rcuprant la page suivante.
1
2
3
4
5
6
7
8
9
10
11
12
13
Remarquez que le jeton a une dure de vie limite. Il est possible de le renouveler
rgulirement avec une requte qui nous retourne un nouveau jeton, voire le mme si
577
public Page1 ()
{
I nitializeComponent () ;
}
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
base . OnNavigatedTo ( e ) ;
578
SE CONNECTER FACEBOOK
11
12
13
Cest une bonne ide de lancer une requte de ce genre chaque connexion de lutilisateur afin de prolonger la dure de vie du jeton, ou pourquoi pas dans une tche
priodique que nous avons vu dans la partie prcdente. . .
Oui mais moi, jaime bien les mthodes asynchrones async et await . . .
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
579
6
7
8
9
10
11
try
{
12
13
14
15
16
17
}
catch ( Exception )
{
MessageBox . Show ( " Impossible de renouveler le token " ) ;
}
18
19
20
21
22
23
24
25
base . OnNavigatedTo ( e ) ;
Pratique , non ?
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " * " / >
< RowDefinition Height = " * " / >
</ Grid . RowDefinitions >
< Grid >
< Grid . ColumnDefinitions >
< ColumnDefinition Width = " 100 " / >
< ColumnDefinition Width = " * " / >
</ Grid . ColumnDefinitions >
< Grid . RowDefinitions >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " auto " / >
</ Grid . RowDefinitions >
< Image x : Name = " ImageUtilisateur " Grid . RowSpan = " 2 " / >
< TextBlock x : Name = " NomUtilisateur " Grid . Column = " 1 " / >
< TextBlock x : Name = " Da t e Na i s s an c e Ut i l is a t eu r " Grid . Row = "
1 " Grid . Column = " 1 " / >
</ Grid >
</ Grid >
Pour obtenir ces infos, nous allons interroger le graphe social. On utilise pour cela
la mthode Get de lobjet FacebookClient, que nous avons dj utilise (ou plutt la
mthode dextension que nous avons cre). Le principe est de faire un appel REST la
ressource suivante : https://graph.facebook.com/me, et de rcuprer le rsultat. Ce
rsultat sobtient avec la mthode GetResultData qui retourne un JsonObject. Nous
pourrons alors accder aux informations contenues dans cet objet, comme lidentifiant,
le nom, le prnom ou la date de naissance.
1
2
try
{
3
4
5
6
7
8
9
10
11
12
13
581
catch ( Exception )
{
MessageBox . Show ( " Impossible d ' obtenir les informations sur
moi " ) ;
}
8
9
10
11
Remarquez que vous naurez une valeur dans le champ de date de naissance que si
vous avez demand la permission user_birthday, do la vrification de lexistence de
la cl avant son utilisation. Remarquez que limage dune personne sobtient grce
son identifiant : https://graph.facebook.com/id_utilisateur/picture (voir figure
39.8).
Cette collection est compose dobjets reprsentant chaque utilisateur. Chaque objet
Utilisateur est dfini de la manire suivante :
1
2
582
public
public
public
public
Je vais complter les informations de chaque objet Utilisateur grce aux informations
reues par lAPI. Je dmarre donc la requte permettant davoir la liste de mes amis.
Une fois la liste reue, jextrais la liste des identifiants de chaque ami et je rinterroge
lAPI pour avoir le dtail de chaque utilisateur. Une fois le dtail reu, je lajoute
mon ObservableCollection.
1
2
3
4
5
6
7
8
9
10
try
{
583
11
12
13
14
15
16
}
}
catch ( Exception )
{
MessageBox . Show ( " Impossible d ' obtenir les informations sur
les amis " ) ;
}
Ouf ! Vous naurez bien sr pas oubli de faire les initialisations adquates :
1
2
3
public Page1 ()
{
I ni t i alizeComponent () ;
4
5
6
7
Noubliez pas non plus de dclarer laffichage de notre liste dans une ListBox dans la
page XAML :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
< ListBox ItemsSource = " { Binding UtilisateurList } " Grid . Row = " 1 " >
< ListBox . ItemTemplate >
< DataTemplate >
< Grid >
< Grid . ColumnDefinitions >
< ColumnDefinition Width = " 100 " / >
< ColumnDefinition Width = " * " / >
</ Grid . ColumnDefinitions >
< Grid . RowDefinitions >
< RowDefinition Height = " auto " / >
< RowDefinition Height = " auto " / >
</ Grid . RowDefinitions >
< Image Source = " { Binding Image } " Grid . RowSpan = " 2
" />
< TextBlock Text = " { Binding Nom } " Grid . Column = " 1 "
/>
< TextBlock Text = " { Binding DateNaissance } " Grid .
Row = " 1 " Grid . Column = " 1 " / >
</ Grid >
</ DataTemplate >
</ ListBox . ItemTemplate >
</ ListBox >
Et voil, nous pouvons afficher la liste de nos amis. Par respect pour les miens, je
ne prsenterai pas de copie dcran avec leurs ttes et leurs anniversaires, mais vous
pouvez essayer avec les vtres, cela fonctionne trs bien !
584
< Grid x : Name = " LayoutRoot " Background = " Transparent " >
< Grid . RowDefinitions >
< RowDefinition Height = " Auto " / >
< RowDefinition Height = " * " / >
< RowDefinition Height = " Auto " / >
</ Grid . RowDefinitions >
7
8
9
10
< StackPanel x : Name = " TitlePanel " Grid . Row = " 0 " Margin = " 12 , 17 ,
0 , 28 " >
< TextBlock x : Name = " ApplicationTitle " Text = " TP du jeu du
plus ou du moins " Style = " { StaticResource
P honeTextTitle2Style } " / >
</ StackPanel >
11
12
13
14
15
16
17
18
19
20
21
22
< Grid x : Name = " ContentPanel " Grid . Row = " 1 " Margin = " 12 ,0 , 12 , 0 "
>
< StackPanel >
< TextBlock Text = " Veuillez saisir une valeur ( entre
0 et 500 ) " Style = " { StaticResource
PhoneTextNormalStyle } " HorizontalAlignment = "
Center " / >
< TextBox x : Name = " Valeur " InputScope = " Number " / >
< Button Content = " V rifier " Tap = " Button_Tap_1 " / >
< TextBlock x : Name = " Indications " Height = " 50 "
TextWrapping = " Wrap " / >
< TextBlock x : Name = " NombreDeCoups " Height = " 50 "
TextWrapping = " Wrap " Style = " { StaticResource
PhoneTextNormalStyle } " / >
< Button x : Name = " BoutonFb " Content = " Publier mon
score sur Facebook " Tap = " Button_Tap " IsEnabled = "
False " / >
</ StackPanel >
</ Grid >
< Button Content = " Rejouer " Tap = " Button_Tap_2 " Grid . Row = " 2 "
/>
585
23
8
9
10
11
public Page1 ()
{
I nitializeComponent () ;
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
586
try
{
}
catch ( Exception )
{
40
41
42
43
}
base . OnNavigatedTo ( e ) ;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
587
13
14
15
16
17
18
Nous pourrons alors poster sur le mur en passant un message dans la proprit message,
puis en envoyant tout a en REST sur ladresse du mur. Une fois que lenvoi est termin,
on est en mesure de dterminer si lenvoi est bien pass ou pas :
1
2
3
4
5
6
7
8
9
10
11
12
13
588
Figure 39.9 Le message est post sur Facebook depuis lapplication Windows Phone
Ct Facebook, nous pouvons constater lapparition du message sur mon mur comme
je vous le montre dans la figure 39.10.
589
590
5
6
En rsum
Il faut crer une application Facebook afin de pouvoir interagir avec Facebook
depuis notre application Windows Phone.
On utilise le contrle WebBrowser pour tablir lauthentification OAuth.
Les permissions, si elles sont acceptes, nous permettent daccder aux informations du graphe social.
Le SDK nous simplifie laccs aux ressources REST du graphe social.
On peut utiliser des launchers pour partager trs facilement des informations
sur les rseaux sociaux.
592
Chapitre
40
593
595
596
598
599
601
603
604
Ainsi, vous pourrez vrifier si lapplication est en mode dessai avec le code suivant :
1
2
Aprs, libre vous de faire ce que vous voulez en fonction de la valeur du boolen.
Peut-tre voudrez-vous limiter le nombre de fonctionnalits ? Peut-tre voudrez-vous
limiter lapplication dans le temps ? Dans tous les cas, une fois la priode termine, vous
aurez intrt renvoyer lutilisateur vers le Windows Phone Store afin quil achte votre
application, comme nous lavons vu cest avec le launcher MarketplaceDetailTask. Remarquez que, pendant la phase de dveloppement, la variable boolenne IsTrial() vaut
toujours Vrai. Vous pourrez encapsuler cet appel dans une instruction conditionnelle
pour vos diffrents tests :
1
2
3
4
5
6
7
8
9
605
Application . Current . Host . Settings . Ena ble Fr ame Ra teC ou nte r = true
;
608
Vous avez galement votre disposition un outil danalyse de performance qui se trouve
en bas de longlet des tests automatiss. Vous pouvez dmarrer cette analyse automatique sur votre tlphone, elle gnre un rapport avec des informations intressantes
comme par exemple le temps de dmarrage de lapplication, si lapplication rpond
rapidement, etc. Cela peut vous donner des pistes damliorations de votre application
(voir le rapport de performance prsent dans la figure 40.20).
Le Store Test Kit constitue donc une espce de grande check-list qui va nous permettre
de vrifier que notre application fonctionne dans toutes les situations dcrites. Cela
va nous faire gagner du temps, car si nous dtectons une anomalie, il sera possible de
la corriger rapidement. Dans le cas contraire, cest Microsoft qui la dtectera et qui
bloquera la publication de notre application tant que le problme ne sera pas corrig.
noter que nous serons avertis du rapport de certification par e-mail.
609
Figure 40.19 Les images de lapplication sont dfinies dans le Store Test Kit
610
611
613
614
617
618
622