Windows Phone 7.
Développez pour Windows Phone 7 en C# et Xaml. Cours complet
Publié le 19 octobre 2012
VIII. Comment faire
VIII-A. SplashScreen
VIII-B. Image de fond de page, icône
VIII-C. Positionnement dynamique des contrôles
VIII-D. Navigation entre pages, transfert de paramètres
VIII-E. Validation de caractère dans un TextBox
VIII-F. Créer ses propres contrôles
VIII-G. Gérer le BackButton
VIII-H. Saisie tactile, gesture
VIII-H-1. Evènements souris
VIII-H-2. Evenements de bas niveau
VIII-H-3. Evènements de haut niveau
VIII-H-4. Gestures du toolkit
VIII-I. Perdre du temps
VIII-J. Sortir de l'application
VIII-K. Application démonstration ou payée
VIII-L. Mes trucs
IX. Compilation, test, distribution
IX-A. Compilation
IX-B. Test sur un Windows Phone
IX-C. La distribution
VIII. Comment faire
VIII-A. SplashScreen
C'est une fenêtre qui s'ouvre au démarrage d'un programme, qui montre simplement une belle image, ensuite la fenêtre 'Splash' disparaît et la fenêtre principale apparaît.
En WP c'est simple :
Il y a dans l'explorateur de solution un fichier nommé SplashScreenImage.jpg, il fait 480*800 pixels. Il suffit de double-cliquer dessus pour se retrouver dans Paint et modifier le SplashScreen.
Dans ses propriétés, 'Action de génération' doit être à 'contenu'.
Dans ses propriétés, 'Action de génération' doit être à 'contenu'.
S'il n'y a pas ce fichier, il n'y a pas de SplashScreen.
Si on veut que le SplashScreen reste plus longtemps il faut, dans le constructeur de la page (sous InitializeComponent) mettre une Thread.Sleep (voir chapitre 'perdre du temps').
Si on veut que le SplashScreen reste plus longtemps il faut, dans le constructeur de la page (sous InitializeComponent) mettre une Thread.Sleep (voir chapitre 'perdre du temps').
|
VIII-B. Image de fond de page, icône
Dans le projet il y a déjà par défaut :
ApplicationIcon.png : icône de l'application (62*62 pixels) qui sera affichée dans la liste des applications ;
Background.png : icône qui sera affichée lorsque l'application est "épinglée" (pinned) sur la page d'accueil du téléphone (173*173 pixels).
ApplicationIcon.png : icône de l'application (62*62 pixels) qui sera affichée dans la liste des applications ;
Background.png : icône qui sera affichée lorsque l'application est "épinglée" (pinned) sur la page d'accueil du téléphone (173*173 pixels).
Dans les propriétés du projet (menu "Projet" puis "Propriétés de") on peut modifier cela.

Dans l'explorateur de solution à droite, il faut double-cliquer sur le nom d'une de ces deux images pour se retrouver dans Paint (ou Paint.Net ici) et ainsi la modifier.

Pour ses deux icônes si on veut un fond ayant la couleur du thème il faut, au lieu de mettre un fond coloré, mettre un fond transparent, un avant plan blanc et sauvegarder votre image en .PNG avec support de la transparence (sauvegarde en 32 bits). J'utilise Paint.Net pour cela.

Ici on a la liste des applications avec les icônes (ApplicationIcon.png de 63x63 px), WP ajoute le nom de l'application à droite.

Ici, pour l'icône épinglée (Background.png 173x173 px) WP ajoute sur l'image le nom de l'application ('My app' ici) avec des caractères de 20 px de hauteur, à 7 px du bord gauche, et 7 px du bas.
Comment mettre une image de fond dans une page Panorama ou Pivot ?
|
Pour un panorama, si l'image à une largeur de deux pages mais que le panorama a quatre pages, le fond se déroulera lentement et s'affichera sur les quatre pages.
Comment mettre un fond sur une page simple ?
Il faut mettre l'image dans le background de la grille racine :
Il faut mettre l'image dans le background de la grille racine :
|
Le problème est que parfois on a (si on utilise un thème avec arrière-fond clair) une bande blanche en haut.

Dans ce cas il ne faut pas afficher le SystemTray et il ne faut pas mettre de taille dans la Grid LayoutRoot (ainsi elle remplira la totalité de l'espace).
Si on a modifié la Grid à la souris, il apparaît la propriété Height, ensuite on a du mal à gérer, il vaut donc mieux enlever 'Height=" ".
Si on a modifié la Grid à la souris, il apparaît la propriété Height, ensuite on a du mal à gérer, il vaut donc mieux enlever 'Height=" ".
|
Comment mettre en fond de page une couleur 'aléatoire' :
|
VIII-C. Positionnement dynamique des contrôles
Layout Absolu
Dans un positionnement en Layout Absolu, les éléments sont placés dans un canvas à une position exacte absolue relative à leur élément parent.
Cela ne prend pas en compte les dimensions de l'écran.
Dans un positionnement en Layout Absolu, les éléments sont placés dans un canvas à une position exacte absolue relative à leur élément parent.
Cela ne prend pas en compte les dimensions de l'écran.
Layout dynamique
Permet un positionnement quel que soit la résolution de l'écran.
On utilise un StackPanel ou surtout une Grid.
Dans les cellules, on met des contrôles avec les propriétés Width et Height= Auto. Ils occupent toute la cellule (Margin permet de laisser un espace autour).
S'il y a un texte à afficher en totalité on donne une valeur à MinHeight et MinWidth pour que le texte ne soit pas tronqué.
On donne des dimensions relatives pour les colonnes et les lignes de la Grid (dans RowDefinition et ColumnDefinition) à l'aide des *.
Permet un positionnement quel que soit la résolution de l'écran.
On utilise un StackPanel ou surtout une Grid.
Dans les cellules, on met des contrôles avec les propriétés Width et Height= Auto. Ils occupent toute la cellule (Margin permet de laisser un espace autour).
S'il y a un texte à afficher en totalité on donne une valeur à MinHeight et MinWidth pour que le texte ne soit pas tronqué.
On donne des dimensions relatives pour les colonnes et les lignes de la Grid (dans RowDefinition et ColumnDefinition) à l'aide des *.
L'utilisateur utilise son doigt pour toucher les éléments visuels ; il est conseillé d'agrandir la zone de touché bien au-delà de la zone visuelle. Les éléments trop rapprochés les uns des autres introduisent un risque pour l'utilisateur d'appuyer sur le mauvais bouton.
Les contrôles de silverlight sont déjà optimisés par nature, en ayant naturellement une Margin importante.
Il y a des contraintes de taille et Microsoft donne les conseils suivants :
une cible doit être au moins un carré de 34 px avec un espacement d'au moins 8 px. L'agrandissement de la zone de touché doit être d'au moins 60 % de la taille de l'élément. Pour les éléments textuels touchables, la taille de police doit être d'au moins 15 pts.
Il y a des contraintes de taille et Microsoft donne les conseils suivants :
une cible doit être au moins un carré de 34 px avec un espacement d'au moins 8 px. L'agrandissement de la zone de touché doit être d'au moins 60 % de la taille de l'élément. Pour les éléments textuels touchables, la taille de police doit être d'au moins 15 pts.
VIII-D. Navigation entre pages, transfert de paramètres
La page de démarrage est par défaut 'MainPage.xaml'.
Si on veut en mettre une autre, il faut dans l'explorateur de solution, cliquer sur 'Properties' puis double-cliquer sur 'WMAppManifest.xml' et modifier la ligne :
Si on veut en mettre une autre, il faut dans l'explorateur de solution, cliquer sur 'Properties' puis double-cliquer sur 'WMAppManifest.xml' et modifier la ligne :
|
Comment dans une page ouvrir une autre page nommée 'PageConvert.xaml' ?
En C# :
|
La Classe NavigationService contient ce qu'il faut pour naviguer. Les méthodes Navigate mais aussi GoBack, GoForward…
En XAML : on peut aussi utiliser un hyperlinkButton :
|
Exemple complet
On met trois boutons dans une page, cliquer sur un des boutons ouvre la page correspondante.
On met trois boutons dans une page, cliquer sur un des boutons ouvre la page correspondante.
Code XAML des boutons :
|
Code C# :
|
Comment passer un texte ?
Quand on clique sur button1, ouvrir SecondPage.xaml. Passer 'montexte' de la page actuelle à la page SecondPage.xaml.
Quand on clique sur button1, ouvrir SecondPage.xaml. Passer 'montexte' de la page actuelle à la page SecondPage.xaml.
On va utiliser les QueryString : pour l'appel d'une nouvelle page avec NavigationService.Navigate, on ajoute le texte à l'URI (querystring= 'msg', valeur="montexte"). C'est comme pour une page Web, on utilise le point d'interrogation suivi d'une clé et de sa valeur. Dans la page qui s'ouvre on récupère le texte par NavigateContext.QueryString :
|
Dans SecondPage :
|
La méthode OnNavigatedTo de la page s'exécute lorsque la page devient active. Elle est préférable à la méthode 'Loaded' qui peut s'exécuter plusieurs fois.
On surcharge donc cette méthode pour récupérer le QueryString.
On surcharge donc cette méthode pour récupérer le QueryString.
On peut mettre plusieurs textes séparés par '&'.
|
Comment passer un objet ?
En utilisant le dictionnaire d'état temporaire avec PhoneApplicationService.Current.State permettant de stocker les données de l'application, un objet en particulier.
Il faut au préalable inclure l'espace de noms Microsoft.Phone.Shell.
|
Dans la page de départ :
|
Ouvrir la seconde page et surcharger OnNavigateTo dans celle-ci. Récupérer l'objet dans les données de l'application.
|
Comment retourner à la page précédente avec du code ?
|
Bien sûr il y a le bouton de gauche qui est le bouton 'back'.
Comment détourner l'usage du 'back Button', exécuter du code et annuler son effet ?
En surchargeant la méthode OnBackKeyPress :
Comment détourner l'usage du 'back Button', exécuter du code et annuler son effet ?
En surchargeant la méthode OnBackKeyPress :
|
VIII-E. Validation de caractère dans un TextBox
Problème récurrent.
Je veux permettre la saisie des chiffres de 0 à 9 (uniquement) et permettre l'effacement (back) dans un TextBox nommé 'entree1', comment faire ?
Je veux permettre la saisie des chiffres de 0 à 9 (uniquement) et permettre l'effacement (back) dans un TextBox nommé 'entree1', comment faire ?
Premièrement, il faut bien choisir le clavier virtuel (InputScope). On utilise 'Digit'.
|
Quand le TextBox à le focus, le clavier suivant apparaît :

Ce clavier ne permet de saisir que des chiffres mais parfois il y a d'autres caractères possible qu'il faut éliminer (le point ici).
On va donc intercepter l'évènement KeyUp (KeyUp="TesteTouche" dans le XAML précédent) qui se déclenche quand on appuie sur une touche, cela exécutera 'TesteTouche' ; cette routine va accepter les seules touches permises.
|
keys est une string qui contient les touches permises.
Je caste le sender en TextBox.
Je regarde si chaque caractère du TextBox fait partie des caractères autorisés ; sinon je l'élimine.
Enfin je remets le curseur à la fin.
Je caste le sender en TextBox.
Je regarde si chaque caractère du TextBox fait partie des caractères autorisés ; sinon je l'élimine.
Enfin je remets le curseur à la fin.
Si la saisie doit permettre les nombres fractionnaires, il faut accepter le bon séparateur décimal. Une méthode est de lire ce séparateur ('.' ou ',') dans la currentCulture et de l'ajouter à keys.
|
Comment remplacer un caractère par un autre au cours de la saisie ?
Ici on va utiliser TextChanged :
Ici on va utiliser TextChanged :
|
Et dans le code behind :
|
Une autre méthode se trouve sur Internet.
Dans la routine C# on déclare un tableau contenant les Key (touches du clavier) à accepter.
Ensuite on teste si la touche tapée (qui est dans e.Key) est dans le tableau.
Si IndexOf retourne -1 , la touche n'y est pas.
Dans ce cas on indique d'annuler le traitement de la touche (e.Handled= true) :
Dans la routine C# on déclare un tableau contenant les Key (touches du clavier) à accepter.
Ensuite on teste si la touche tapée (qui est dans e.Key) est dans le tableau.
Si IndexOf retourne -1 , la touche n'y est pas.
Dans ce cas on indique d'annuler le traitement de la touche (e.Handled= true) :
|
Elle ne fonctionne pas si on utilise les codes touche keyD1, KeyD2… Il faut utiliser Key.NumPad1, KeyNumPad2… (e.Key retourne la touche mais avec les InputScope, le même code est retourné pour plusieurs touches ! Cela fonctionne avec l'exemple précédent mais pas avec toutes les touches).
Autre exemple plus complexe :
L'utilisateur tape du texte dans une TextBox nommée entree.
Eliminer '*', '#', " ".
Si le séparateur décimal est '.' , remplacer ',' par '.' et vice versa.
L'utilisateur tape du texte dans une TextBox nommée entree.
Eliminer '*', '#', " ".
Si le séparateur décimal est '.' , remplacer ',' par '.' et vice versa.
|
VIII-F. Créer ses propres contrôles
Contrôle étendu
On peut utiliser un contrôle et étendre ses possibilités, on peut aussi créer son propre contrôle.
On va créer un contrôle étendu nommé 'TextBoxNumerique' qui est une TextBox qui n'accepte que les chiffres de 0 à 9 et permet l'effacement.
On va créer une classe.
Menu 'Projet' puis 'Ajouter une classe'.
Menu 'Projet' puis 'Ajouter une classe'.
Notre classe va hériter de TextBox :
|
On va surcharger la méthode OnKeyDown
(qui est exécutée quand l'évènement KeyDown va se produire) :
(qui est exécutée quand l'évènement KeyDown va se produire) :
|
On y teste la touche appuyée, si elle n'est pas dans le tableau des touches valides (0 à 9 et Back), on annule la touche.
Voici le code complet :
Voici le code complet :
|
Dans le constructeur on indique l'InputScope qui est 'TelephoneLocalNumber' ce qui ouvre le clavier téléphone pour l'utilisateur.
On peut maintenant ajouter le contrôle dans l'UI.
Menu 'Build' puis 'Générer la solution' et on retrouve le contrôle dans la boîte à outils en haut.
Il faut inclure l'espace de noms (ici avec un alias nommé 'local') puis mettre le customcontrol 'TextBoxNumerique' dans le code XAML.
Menu 'Build' puis 'Générer la solution' et on retrouve le contrôle dans la boîte à outils en haut.
Il faut inclure l'espace de noms (ici avec un alias nommé 'local') puis mettre le customcontrol 'TextBoxNumerique' dans le code XAML.
|
On peut utiliser les champs et méthodes hérités de TextBox dans le code C# ( MonTB.Text, par exemple).
![]() |
Le Custom Control hérite d'un contrôle ; il hérite aussi des propriétés et méthodes de ce contrôle. On peut surcharger les méthodes pour modifier le comportement ou ajouter des champs et de nouvelles méthodes. |
UserControl : contrôle utilisateur.
Là on va créer un UserControl qui est un contrôle composite contenant plusieurs contrôles et réutilisable.
Il dérive de la classe UserControl ; il a une propriété 'Content' où on mettra les contrôles.
Il dérive de la classe UserControl ; il a une propriété 'Content' où on mettra les contrôles.
On va créer un UserControl contenant deux TextBox permettant de saisir un nom, un mot de passe, un bouton 'ok' qui déterminera si le mot de passe est valide.
Créons le UserControl : menu 'Projet' puis 'Ajouter un nouvel élément'.

Choisir 'Contrôle utilisateur Windows Phone' puis en bas donner le nom 'MyControl', puis cliquer sur ajouter.
Il s'ouvre un onglet nommé 'MyControl.xaml' ; dans le concepteur il n'y a même pas de bord.
À l'aide de la boîte à outils ajouter les contrôles nécessaires :

Cela donne le code XAML correspondant suivant :
|
Il y a un TextBox nommé '_Nom', un autre nommé '_MotDePasse' et un bouton 'Bouton'.
Maintenant on va créer le code propre au UserControl, dans les fonctions privées du UserControl.
Le code contenu dans les propriétés et méthodes privées va 'piloter' le ou les contrôles internes. Ce code fournit un comportement propre au UserControl.
On va déclarer une variable bool nommée '_IsValid'. La fonction Bouton_Click (exécutée lorsque l'utilisateur clique sur 'Ok') contrôle la validité du nom et du mot de passe et si tout est valide cela entraîne _IsValid= true. Cela donne dans MyControl.xaml.cs.
|
Notez bien que la validation est triviale ; ce n'est pas notre propos ici.
Bien, le UserControl fonctionne mais pour le moment il n'y a pas de liaison avec l'extérieur.
Les contrôles qui sont dans le UserControl sont privés au UserControl et leurs propriétés ou méthodes ne sont pas accessibles à l'extérieur. On ne peut donc pas avoir accès à la propriété 'Text' du contrôle '_Nom' par exemple.
Il va falloir rajouter dans le UserControl des membres et des méthodes public qui seront accessibles à l'utilisateur du composant. Ces champs public (avec get et set) et ces méthodes publiques créeront une interface.
Ajoutons donc l'interface du UserControl
On va donc créer une propriété 'public' 'IsValid' pour que l'utilisateur du contrôle puisse savoir si 'nom/mot de passe' sont valides, une propriété public 'Nom' cela peut être utile.
Enfin une méthode Clear 'public' pour réinitialiser le UserControl :
|
Le UserControl est terminé, un coup de menu 'Build' puis 'Générer' ; maintenant on va pouvoir utiliser le UserControl.
Utilisons le UserControl 'MyControl'.
Dans la page MainPage, j'ouvre la boîte à outils ; le UserControl 'MyControl' est là, on peut j'ajouter à la page :

Cela donne le code XAML suivant :
|
On note que cela a ajouté la ligne 'xmlns:my="clr-namespace:test"' qui ajoute le namespace 'test' (l'application), ce qui permet ensuite d'utiliser 'my:Mycontrol'.
Dans le code C# de MainPage on peut accéder à la méthode Clear et aux propriétés IsValid et Nom du contrôle 'mycontrole1
|
Affiche true si la saisie Nom/Mot de passe est valide.
VIII-G. Gérer le BackButton

On peut simuler l'appui du bouton 'back' par code :
|
Si un texte a été tapé dans le TextBox 'MonTexte', demander confirmation avant de quitter la page si l'utilisateur appuie sur le bouton 'Back'.
Pour cela, on surcharge OnBackKeyPress
|
On remarque qu'on peut annuler l'effet de la touche 'Back' par e.Cancel = true.
Quand on veut forcer un 'back' par code, on peut tester avant si c'est possible :
|
Enfin, on peut interdire l'action de la touche 'Back'.
|
VIII-H. Saisie tactile, gesture
Rappel des differents gestures (dessin de Microsoft) :

Un événement Tap a lieu lorsqu'un doigt touche l'écran et le quitte avant 1,1 secondes sans se déplacer beaucoup. Si deux événements Tap se succèdent rapidement, le deuxième est traité comme un événement DoubleTap. Un événement Hold (tenir) a lieu lorsqu'un doigt appuie sur l'écran et reste au même endroit pendant environ 1,1 secondes. L'événement Hold est généré à la fin de cet intervalle de temps sans attendre que le doigt se soulève.
Note : l'émulateur ne supporte pas le multi-touche.
Note : l'émulateur ne supporte pas le multi-touche.
VIII-H-1. Evènements souris
On utilise habituellement les évènements souris.
Un doigt qui touche un bouton déclenche un évènement Click.
Soit un bouton en Xaml :
Un doigt qui touche un bouton déclenche un évènement Click.
Soit un bouton en Xaml :
|
Le Click exécute :
|
Un doigt qui touche un objet visuel (UIElement) est converti en un évènement de souris ; évènement MouseLeftButtonDown lorsque vous placez votre doigt, évènement MouseLeftButtonUp lorsque vous levez votre doigt, MouseMove lorsque vous faites glisser votre doigt.
Il y a aussi MouseLeave (sortie de la zone) MouseEnter (entrée dans la zone).
Les arguments de ces évènements sont : Sender l'objet d'où vient l'évènement et e de type MouseButtonEventArgs.
Exemple, gestion de l'évènement MouseLeftButtonUp sur un rectangle :
|
Noter que pour que cela fonctionne, il faut remplir le rectangle ; ici on met une couleur transparente grâce à Fill.
La méthode suivante sera exécutée lors du 'levé' du doigt sur le rectangle.
La méthode suivante sera exécutée lors du 'levé' du doigt sur le rectangle.
|
VIII-H-2. Evenements de bas niveau
La classe System.Windows.Input.Touch fournit un service au niveau de l'application qui traite l'entrée tactile et déclenche l'événement FrameReported.
L'argument TouchFrameEventArgs de l'évènement a la méthode GetPrimaryTouchPoint qui retourne le point tactile (TouchPoint) actuel par rapport à l'élément spécifié (null pour l'écran).
TouchPoint.Action obtient la dernière action qui s'est produite à cet emplacement. TouchPOint.TouchDevice obtient le périphérique tactile qui a généré ce TouchPoint.
L'argument TouchFrameEventArgs de l'évènement a la méthode GetPrimaryTouchPoint qui retourne le point tactile (TouchPoint) actuel par rapport à l'élément spécifié (null pour l'écran).
TouchPoint.Action obtient la dernière action qui s'est produite à cet emplacement. TouchPOint.TouchDevice obtient le périphérique tactile qui a généré ce TouchPoint.
Voici l'exemple d'un tap sur un TextBlock nommé 'txBlock' :
|
VIII-H-3. Evènements de haut niveau
Ces évènements de haut niveau sont exécutés sur les objets dérivés de UIElement ; il y a les évènements de gesture : Tap, DoubleTap, Hold.
Exemple avec Tap.
|
|
On peut utiliser l'appuie prolongé avec 'Hold'.
|
On peut aussi utiliser les évènements de manipulation :
ManipulationStarted
intervient quand la manipulation démarre.
ManipulationCompleted
intervient quand la manipulation s'arrête.
ManipulationDelta
intervient quand le doigt change de position et survient de multiples fois au cours de la manipulation.
Par exemple, pour effectuer une action si l'utilisateur pose le doigt sur un contrôle comme une ellipse.
|
|
Le second paramètre est de type ManipulationStartedEventArgs.
L'évènement ManipulationDelta permet de 'lire' les mouvements de 'Translation' et de 'Scale' (pas de rotation en WP).
Ici un glissé horizontal du doigt permet d'élargir ou de réduire l'ellipse.
Ici un glissé horizontal du doigt permet d'élargir ou de réduire l'ellipse.
|
Pour une évènement ManipulationDelta le second paramètre est de type ManipulationDeltaEventArgs.
La propriété DeltaManipulation contient les modifications qui se sont produites depuis le précédent événement ManipulationDelta.
La propriété DeltaManipulation contient les modifications qui se sont produites depuis le précédent événement ManipulationDelta.
|
Dans le code C# on peut surcharger la méthode OnManipulationStarted (et les autres évènements de manipulation) de la page :
Si l'utilisateur pose le doigt sur l'écran.
Si l'utilisateur pose le doigt sur l'écran.
|
VIII-H-4. Gestures du toolkit
Le Toolkit fournit des fonctionnalités très puissantes.
Il y a dans le Toolkit la classe GestuleService qui permet d'attacher un GestureListener à un élément.
Cela permet de gérer les Tap, DoubleTap, Hold, PinchStarted, PinchDelta, PinchCompleted, Flick, DragStarted, DragDelta, DragCompleted, GestureBegin, GestureCompleted.
Il y a dans le Toolkit la classe GestuleService qui permet d'attacher un GestureListener à un élément.
Cela permet de gérer les Tap, DoubleTap, Hold, PinchStarted, PinchDelta, PinchCompleted, Flick, DragStarted, DragDelta, DragCompleted, GestureBegin, GestureCompleted.
Il faut installer le Toolkit, ajouter dans les références 'Microsoft.Phone.Controls.Toolkit.dll'.
Dans le code XAML, dans la balise d'ouverture de la page, il faut taper :
Dans le code XAML, dans la balise d'ouverture de la page, il faut taper :
|
Maintenant on peut utiliser les gestures du toolkit : on retrouve Tap DoubleTap et Hold.
Exemple simple avec Tap ; on va appliquer un GestureService.GestureListener à la grille principale 'ContentPanel' et on va 'écouter' l'évènement Tap.
Exemple simple avec Tap ; on va appliquer un GestureService.GestureListener à la grille principale 'ContentPanel' et on va 'écouter' l'évènement Tap.
|
|
Un Tap exécute OnGestureService qui ici ouvre une simple MessageBox.
Noter que le Tap fonctionne sur les ellipses et le bouton, pas sur le fond autour.
GetPosition retourne un Point ici par rapport à ellipse2 (qui a été donné en argument), l'origine étant le coin supérieur gauche d'un rectangle contenant l'ellipse. Pour que Tap soit actif même sur le fond, il faut un Background sur la grille.
Noter que le Tap fonctionne sur les ellipses et le bouton, pas sur le fond autour.
GetPosition retourne un Point ici par rapport à ellipse2 (qui a été donné en argument), l'origine étant le coin supérieur gauche d'un rectangle contenant l'ellipse. Pour que Tap soit actif même sur le fond, il faut un Background sur la grille.
|
On peut écrire cela en C# :
Ici on a un rectangle, quand on clique dessus, il devient blanc.
Ici on a un rectangle, quand on clique dessus, il devient blanc.
|
Passons rapidement sur GestureBegin et GestureCompleted qui permettent de voir l'objet qui a déclenché la gesture (OriginalSource) et les coordonnés (GetPosition).
|
|
Une séquence Drag (traîner) est constituée d'un événement DragStarted, de zéro ou plusieurs évènements DragDelta et d'un événement DragCompleted (lorsqu'un doigt touche l'écran, se déplace, puis quitte l'écran).
DragStarted permet, outre l'objet et les coordonnées, de voir la direction de départ (retourne une 'Orientation' qui est une enum ayant deux valeurs : Horizontal et vertical).
|
|
DragDelta, outre les informations précédentes, permet de voir le déplacement horizontal et vertical (positif si le déplacement se fait à droite et en bas).
|
|
DragCompleted présente les mêmes informations (sur quel objet on lache) mais avec en plus HorizontalVelocity et VerticalVelocity.
L'événement Flick a lieu lorsqu'un doigt quitte l'écran alors qu'il se déplace encore, ce qui suggère que l'utilisateur souhaite obtenir une inertie ; je le fais lorsque j'enlève vers le haut l'écran de démarrage. Les arguments comprennent une valeur Angle (de 0 à 360 °, mesuré dans le sens des aiguilles d'une montre à partir de l'axe des X positifs horizontal à droite), ainsi que des valeurs HorizontalVelocity et VerticalVelocity (mesurées en pixels par seconde).
On va l'appliquer à une ellipse.
On va l'appliquer à une ellipse.
|
|
La séquence Pinch (pincement) a lieu lorsque deux doigts touchent l'écran ; elle est généralement interprétée pour développer ou réduire un objet.
Pinch correspond aux deux doigts qui s'écartent ou se rapprochent.
La position actuelle d'un doigt (le doigt principal) est toujours disponible avec la méthode GetPosition.
La position actuelle d'un doigt (le doigt principal) est toujours disponible avec la méthode GetPosition.
Il y a PinchStarted.
|
|
Il y a aussi PinchDelta.
|
On peut voir le 'DistanceRatio' rapport de la distance actuelle entre les deux doigts et la distance de départ. Il y a aussi le 'TotalAngleDelta' différence de l'angle actuel entre les deux doigts et l'angle de départ.
|
Il existe aussi PinchCompleted qui n'apporte rien de plus.
VIII-I. Perdre du temps
Parfois on a besoin de perdre du temps, suspendre l'exécution durant 1/2 s par exemple.
Il faut inclure l'espace de nom System.Threading puis utiliser la méthode Sleep du Thread (avec en paramètre 500 ms).
Il faut inclure l'espace de nom System.Threading puis utiliser la méthode Sleep du Thread (avec en paramètre 500 ms).
|
VIII-J. Sortir de l'application
Logiquement, le fait d'utiliser le bouton 'Back' quand on est sur la première page de l'application permet de sortir de l'application.
Si on quitte l'application avec le bouton central, elle se met à l'état dormant et se fermera automatiquement si on s'y revient pas.
Il n'y a donc pas besoin de méthode pour quitter l'application.
Si on quitte l'application avec le bouton central, elle se met à l'état dormant et se fermera automatiquement si on s'y revient pas.
Il n'y a donc pas besoin de méthode pour quitter l'application.
Si on veut vraiment, Application.Exit() n'existant pas, il faut déclencher une exception non gérée ! Ce n'est pas élégant !
|
VIII-K. Application démonstration ou payée
On peut distribuer une application gratuite en démonstration ; elle pourra ensuite être achetée et ainsi donner accès à des niveaux ou fonctions supplémentaires.
La Méthode IsTrial de LicenceInformation indique si on est en mode démo.
La Méthode IsTrial de LicenceInformation indique si on est en mode démo.
|
Code non testé.
VIII-L. Mes trucs
Sans prétention !
Attention au nom de l'application !
Si je crée une application se nommant 'calcul' puis une variable 'calcul' et si je me fais aider pour l'écriture (IntelliSense), je peux avoir des confusions entre espace de noms 'calcul' et variable 'calcul' :

De même si le nom de l'application a le nom d'une classe.
L'enfer des accolades.
Dans le code C#, quand on a plusieurs classes dans un espace de noms ou si on a des if imbriqués, il y a plein d'accolades ouvrantes et fermantes.
C'est l'horreur pour savoir où ajouter une fonction ou une classe ou un else ; si on se trompe et qu'on met une fonction une accolade trop haut, les messages d'erreur ne sont pas toujours clairs.
Le plus simple pour s'y retrouver est de cliquer sur une accolade ouvrante cela surligne l'accolade fermante correspondante.
C'est l'horreur pour savoir où ajouter une fonction ou une classe ou un else ; si on se trompe et qu'on met une fonction une accolade trop haut, les messages d'erreur ne sont pas toujours clairs.
Le plus simple pour s'y retrouver est de cliquer sur une accolade ouvrante cela surligne l'accolade fermante correspondante.

Groupe de contrôles
Avant l'univers '.NET', en VB6 par exemple, on pouvait créer des groupe de contrôles, les contrôles d'un groupe avaient les mêmes fonctions évènements et pour un clic sur différents boutons on exécutait la même fonction.
Pour simuler les 'groupes de contrôles' qui n'existent pas en WP on a un moyen simple : en XAML, pour que plusieurs boutons exécutent la même fonction, on peut indiquer Click="MyButtonClick" pour plusieurs boutons.
Pour simuler les 'groupes de contrôles' qui n'existent pas en WP on a un moyen simple : en XAML, pour que plusieurs boutons exécutent la même fonction, on peut indiquer Click="MyButtonClick" pour plusieurs boutons.
|
Ensuite dans la fonction MyButtonClick il suffit de regarder le 'sender' pour voir quel bouton a été cliqué (il faut le caster en bouton avant de tester son nom).
On peut aussi utiliser un StackPanel 'parent' pour gérer l'évènement Click de tous les boutons enfants dans le StackPanel (comme il n'y a pas de 'Click=' dans les boutons, l'évènement Click remonte dans le StackPanel) :
|
IX. Compilation, test, distribution
IX-A. Compilation
La compilation c'est transformer un code source (le code XAML et le code C# que vous avez tapé), en code exécutable et distribuable.
En haut on peut choisir Windows Phone Emulator ou Windows Phone Device pour lancer l'application sur l'émulateur ou le portable connecté (si on est enregistré) :

Puis on peut choisir 'Debug' (permettant le débogage) ou 'Release' (pour la distribution).
Si on clique sur le bouton d'exécution (ou F5) on lance le débogage.
Par le menu 'Build' puis 'Générer la solution' ou F6, on compile l'application.
Cela crée un répertoire 'Bin' avec un sous répertoire 'Debug' ou 'Release' contenant un fichier .xap (archive compressée contenant l'exécutable, les DLL, les ressources, images…).
Le fichier .xap est en fait un fichier .zip (vous pouvez renommer ce fichier en .zip et ensuite aller voir ce qu'il y a dedans).
Le fichier .xap est en fait un fichier .zip (vous pouvez renommer ce fichier en .zip et ensuite aller voir ce qu'il y a dedans).
Pour tester le .xap passer par le menu 'Build' puis 'Déployer' ; il s'exécutera dans l'émulateur.
On se souvient où se trouvent les sources des applications.
Pour mon application qui se nomme 'CalculTout' voir dans 'C:\Users\Philippe\Documents\Visual Studio 2010\Projects\CalculTout'.
Il y a les fichiers 'CalculTout.sln' et 'CalculTout.suo'.
Pour mon application qui se nomme 'CalculTout' voir dans 'C:\Users\Philippe\Documents\Visual Studio 2010\Projects\CalculTout'.
Il y a les fichiers 'CalculTout.sln' et 'CalculTout.suo'.

Il y a dessous un répertoire nommé aussi 'CalculTout' qui contient les fichiers '.xaml' et .xaml.cs' et les répertoires 'Bin' et 'Obj' qui contiennent chacun les répertoires 'Debug' et 'Release'.
Quand on compile il y a création des fichiers '.g.cs' et '.g.i.cs' en C# pour chaque page XAML. On n'a théoriquement pas besoin de s'en occuper sauf quand il y a un bogue dans le code XAML et que VS s'arrête sur une instruction de ces fichiers ; lire l'erreur donne une indication sur la correction nécessaire dans le code XAML.
IX-B. Test sur un Windows Phone
Il est possible de voir tourner votre application dans l'émulateur.
Impossible de charger simplement sur votre Windows Phone une application que vous venez de développer.
Impossible donc de tester une application sur votre portable ou de faire une application uniquement pour les membres de votre entreprise.
La solution : enregistrez-vous comme développeur chez Microsoft (99 $) et là vous aurez la possibilité de charger sur votre portable une application pour la tester.
Impossible de charger simplement sur votre Windows Phone une application que vous venez de développer.
Impossible donc de tester une application sur votre portable ou de faire une application uniquement pour les membres de votre entreprise.
La solution : enregistrez-vous comme développeur chez Microsoft (99 $) et là vous aurez la possibilité de charger sur votre portable une application pour la tester.
Pour déboguer, il faut choisir l'émulateur en haut au milieu :

Si on clique sur le bouton d'exécution (ou F5) on compile l'application, on charge l'émulateur WP7 et on exécute l'application dans l'émulateur.

La souris permet de simuler le doigt sur l'écran.
À sa gauche il y a une barre d'outils qui apparaît quand le curseur de la souris s'approche.
Les boutons de haut en bas :
- fermer l'émulateur ;
- réduire l'émulateur ;
- faire pivoter l'émulateur pour passer en mode paysage ;
- faire pivoter mais dans l'autre sens.
- ajuster l'émulateur à la taille de l'écran ;
- définir le zoom de l'émulateur ;
- autres.
- accéléromètre ;
- localisation ;
- copie d'écran.
Sur la droite de l'écran, il y a des compteurs :

En détails :

De haut en bas ils indiquent
- Thread de composition (Render Thread).
3 chiffres. En nombre de frames par seconde (maximum : 120)
Bonne valeur = 60.
Mauvaise valeur si inférieur à 30 (devient rouge).
- Thread UI (User Interface Thread).
3 chiffres. En nombre de frames par seconde (si la valeur est faible, la réaction de l'UI est moins bonne).
Bonne valeur si supérieur à 15.
Devient rouge si inférieur à 15.
- Textures (mémoire utilisée par les textures)
6 chiffres.
- Compteur de surfaces
Nombre de surfaces passées au chip graphique.
- Compteur IRT (Intermediate Texture Count).
- Screen Fill rate (nombre d'écrans dessinés par frame).
Un écran représente 480 x 800 pixels.
si> 3 mauvaises performances.
si inférieur à 2, bonnes performances.
- Thread de composition (Render Thread).
3 chiffres. En nombre de frames par seconde (maximum : 120)
Bonne valeur = 60.
Mauvaise valeur si inférieur à 30 (devient rouge).
- Thread UI (User Interface Thread).
3 chiffres. En nombre de frames par seconde (si la valeur est faible, la réaction de l'UI est moins bonne).
Bonne valeur si supérieur à 15.
Devient rouge si inférieur à 15.
- Textures (mémoire utilisée par les textures)
6 chiffres.
- Compteur de surfaces
Nombre de surfaces passées au chip graphique.
- Compteur IRT (Intermediate Texture Count).
- Screen Fill rate (nombre d'écrans dessinés par frame).
Un écran représente 480 x 800 pixels.
si> 3 mauvaises performances.
si inférieur à 2, bonnes performances.
Dans le constructeur de la classe App de votre application (App.xaml.cs), vous pouvez faire disparaître ces compteurs.
|
C'est bien pour faire des copies d'écran.
Un profiler dédié au projet WP7 a été ajouté, il n'est pas à l'heure actuelle dans sa version définitive, mais il permet de pouvoir cibler certains problèmes de frame rate et d'utilisation de thread sur la CPU/GPU.
Passez par le menu 'déboguer' puis 'Démarrer l'analyse des performances de Windows Phone'.
Passez par le menu 'déboguer' puis 'Démarrer l'analyse des performances de Windows Phone'.
IX-C. La distribution
Il faut préparer des images.
Trois images pour le MarketPlace :
Large Mobile App Tile : 173*173 px 96 DPI, fichier .PNG ;
Small Mobile App Tile : 99*99 px 96 DPI, fichier .PNG ;
Large PC App Tile : 200*200 px 96 DPI, fichier .PNG.
Une (minimum) à huit captures d'écran (Screenshots) 480*800 px 96 DPI, fichier .PNG ;
Une image en option (Background art) utilisée si l'application devient l'application du jour 1000*800 px 96 DPI, fichier .PNG.
Trois images pour le MarketPlace :
Large Mobile App Tile : 173*173 px 96 DPI, fichier .PNG ;
Small Mobile App Tile : 99*99 px 96 DPI, fichier .PNG ;
Large PC App Tile : 200*200 px 96 DPI, fichier .PNG.
Une (minimum) à huit captures d'écran (Screenshots) 480*800 px 96 DPI, fichier .PNG ;
Une image en option (Background art) utilisée si l'application devient l'application du jour 1000*800 px 96 DPI, fichier .PNG.
On peut charger à partir du site CodePlex un logiciel gratuit (http://wpiconmaker.codeplex.com/) permettant, très simplement, de créer les icônes à partir d'une image.
On se souvient que dans l'application il y a les 2 icônes :
Background.png, 173×173 px (utilisé sur l'écran de démarrage).
ApplicationIcon.png, 62x62 px (utilisée dans la liste des applications installées).
Background.png, 173×173 px (utilisé sur l'écran de démarrage).
ApplicationIcon.png, 62x62 px (utilisée dans la liste des applications installées).
La distribution se fait uniquement par le Marquet Place.
Merci à Tomlev pour sa relecture ses corrections et ses conseils, il m'a été d'un grand secours.
Merci à jacques jean pour sa relecture orthographique.
A suivre…
Philippe LASSERRE.
Merci à jacques jean pour sa relecture orthographique.
A suivre…
Philippe LASSERRE.