Windows Phone 7.
Développez pour Windows Phone 7 en C# et Xaml. Cours complet
Publié le 19 octobre 2012
IV. XAML et interface utilisateur
IV-A. Définition du XAML
IV-B. Balisage
IV-C. Casse, espace, tabulation, commentaire
IV-D. Objet, attribut, propriété
IV-E. Élément racine
IV-F. Code-behind, évènements
IV-G. Extension de balisage
IV-H. Espace de noms
IV-I. Remarque importante
V. Silverlight pour WP
V-A. La classe 'Control'
V-A-1. Ajouter un contrôle
V-A-2. Particularités des contrôles
V-A-3. Évènements
V-A-4. Saisie tactile
V-A-5. Modèle de contenu
V-B. Les applications et pages
V-C. Conteneur, position, dimensions des contrôles
V-C-1. Hiérarchie des contrôles, arbre
V-C-2. Nom, position et dimensions d'un contrôle
V-C-3. Plan
V-D. Aspect des contrôles
V-D-1. Propriétés des contrôles
V-D-2. Contrôle contenant des contrôles
V-D-3. Aspect visuel des contrôles: template visuel, style
V-D-4. Transformation
V-D-5. Font
V-E. Couleur, remplissage de surface
V-E-1. Couleur
V-E-2. SolidColorBrush
V-E-3. LinearGradientBrush
V-E-4. RadialGradientBrush
V-E-5. ImageBrush
V-E-6. Masque d'opacité
V-E-7. Nombre de couleurs et dégradés
V-F. Ressources
V-F-1. Les dictionnaires de ressources
V-F-1-a. Ressources 'simples'
V-F-1-b. Les styles
V-F-1-c. Les modèles de contrôle : ControlTemplate
V-F-1-d. Les modèles de données : Data Template
V-F-2. Les fichiers de ressources
V-F-3. Ressources Windows Phone
V-G. Les liaisons de données ou Binding
V-G-1. Principes du Binding
V-G-2. Liaison entre contrôles
V-G-3. Liaison Collection-ListBox
V-G-4. Liaison collection d'objets, ListBox
V-G-5. Convertisseur
V-G-6. Binding avec tri, filtrage, image
V-G-7. Générateur de liaison
V-G-8. Erreur dans le binding
IV. XAML et interface utilisateur

IV-A. Définition du XAML
Windows Phone 7 utilise pour décrire l'interface une version spécifique de Silverlight.
Le code source de silverlight est en XAML= "eXtensible Application Markup Language". Prononcez "Zammel". Il s'agit d'un langage XML permettant de définir des interfaces d'applications
(WPF, silverlight). En d'autres termes, quand vous dessinez une interface utilisateur
en silverlight, elle est enregistrée en XAML.
Le code XAML respecte la syntaxe XML ; il est enregistré dans un fichier ayant l'extension
.xaml.
IV-B. Balisage
XAML est un langage 'balisé'.
Qu'est ce qu'une balise ? 'Élément Sémantique de base' des langages de balisage. En XML une balise est
un mot clé, un élément. Elle est comprise entre crochets et possède un nom et parfois des attributs. En
XAML l'élément est le nom d'un objet visuel (Buttom, TextBlock…)d'une propriété de cet objet visuel
(Background,Content…), ou de tout élément intervenant dans l'UI (une Brush, un ListItem…) .
Toutes les balises doivent être ouvertes puis refermées . On retrouvera donc toujours une balise de début et une balise de fin. La balise de fin porte le même nom que la balise de début à l'exception du signe / qui le précède.
Exemple :
|
On peut combiner balise de début et de fin :
|
Cela suffit à afficher un bouton.
Les balises peuvent être intriquées :
|
La dernière balise ouverte doit être la première fermée. Ici on a mis un bouton dans une grille.
IV-C. Casse, espace, tabulation, commentaire
XAML est sensible à la casse : majuscules et minuscules ne sont pas équivalentes. Les espaces et tabulations
sont ignorés.
Attention donc quand on tape du code XAML : 'grid' ou 'click' ne sont pas acceptés, il faut taper 'Grid'
et 'Click'. Le nom des types et attributs commence par une majuscule.
Les commentaires sont ignorés. Voici un commentaire en XAML :
|
IV-D. Objet, attribut, propriété
On a vu que pour créer un objet, il suffit d'écrire :
|
Un objet visuel a des propriétés : la couleur de fond, les dimensions d'un bouton, le texte dans un TextBlock
sont les propriétés. Il y a différentes manières d'indiquer les valeurs
d'une propriété d'un objet en XAML.
1- Les propriétés des objets visuels peuvent s'écrire sous forme d' attributs. Un attribut est le nom
d'une propriété de la balise souvent associé à une valeur, il est mis dans la balise d'ouverture
après le nom de la balise :
|
Ici dans un bouton, on a utilisé les attributs Background, Foreground Content, pour indiquer la couleur
du fond, du texte et le texte à afficher dans le bouton. À un attribut on affecte une valeur qui est entre guillemets et est un simple texte. On remarque que la syntaxe
est simple mais on ne peut mettre que des valeurs simples. Les attributs sont séparés par un espace.
2- Les propriétés des objets visuels peuvent aussi s'écrire sous forme d'objet balisé dans un format
alternatif appelé "Property element syntax" (syntaxe d'élément propriété), qui étend la syntaxe
de XML. Une propriété a aussi une balise de début et de fin, la syntaxe est celle de l'XML c'est
à dire de la forme :
|
Voyons, par exemple, la propriété Background d'un bouton :
|
L'intérêt de cette syntaxe est qu'entre les deux balises, on peut mettre d'autres balises ou un élément complexe (comme une Brush, par exemple).
Voici l'exemple de notre bouton :
|
3- Propriété par défaut.
Pour le texte affiché dans un bouton, on a vu qu'on pouvait l'écrire avec l'attribut content.
|
Et aussi sous forme d'objet.
|
Mais comme Content est la propriété par défaut des boutons, on peut l'écrire aussi comme cela :
|
De même la propriété 'Text' d'un TextBlock peut s'écrire ainsi :
|
On parle ici d'élément de contenu.
Remarque : on a accès dans un objet aux propriétés qui sont héritées de la classe de base. Par exemple,
dans un bouton, on a accès à la propriété BackGround qui est une propriété héritée de 'controls'.
4- Propriété attachée.
On peut utiliser dans un objet une propriété 'attachée' appartenant au parent :
|
Dans le bouton on utilise DockPanel.Dock qui n'est pas une propriété des boutons mais une propriété du DockPanel, le parent.
Le bouton est collé sur le bord gauche du DockPanel grâce à la propriété 'attachée' Dock qui prend la valeur 'Left' de l'énumération Dock.
Le bouton est collé sur le bord gauche du DockPanel grâce à la propriété 'attachée' Dock qui prend la valeur 'Left' de l'énumération Dock.
5- Propriété de liste.
Beaucoup de contrôles conteneurs peuvent contenir des contrôles enfants. Exemple avec un StackPanel (conteneur permettant d' empiler des contrôles) dans lequel on met plusieurs boutons ; on devrait normalement utiliser la balise 'StackPannel.Child'.
Beaucoup de contrôles conteneurs peuvent contenir des contrôles enfants. Exemple avec un StackPanel (conteneur permettant d' empiler des contrôles) dans lequel on met plusieurs boutons ; on devrait normalement utiliser la balise 'StackPannel.Child'.
|
En fait, comme c'est une liste, on peut omettre cette balise 'StackPanel.Child' car silverlight sait que dans un StackPanel il y a une collection de contrôles :
|
IV-E. Élément racine
Il doit y avoir un élément racine (root) et un seul dans un fichier XAML, il contient tous les autres.
En WP c'est une grille.
|
IV-F. Code-behind, évènements
L'interface est en XAML. Le code (dit code-behind) est en C#. Le code XAML
et le code-behind sont identifiés en spécifiant
un espace de noms et une classe.
Soit un logiciel nommé 'CalculeTout', par exemple.
Soit un logiciel nommé 'CalculeTout', par exemple.
En haut du fichier XAML qui décrit l'interface (fichier .xaml) :
|
La classe se nomme "CalculeTout.MainPage" (cela correspond à 'EspacedeNom.NomPage').
On remarque que WP a pris, pour le nom de l'espace de noms, le nom de l'application. Et la page de démarrage se nomme par défaut 'MainPage'.
On remarque que WP a pris, pour le nom de l'espace de noms, le nom de l'application. Et la page de démarrage se nomme par défaut 'MainPage'.
En haut du fichier C# contenant le code (fichier .xaml.cs) :
|
On a bien l'espace de noms qui est le même que celui de la page XAML (nom de l'application par défaut) et la page qui est en fait une classe dont le nom est 'MainPage'. C'est une classe partielle (partial), l'autre partie de la classe étant dans le code XAML.
Si dans la page on ajoute un Bouton et si on double-clique sur ce bouton, on se retrouve dans le code-behind en C# qui a été crée automatiquement dans le fichier .cs :
|
Il y a eu création d'une fonction 'button1_Click' qui contient le code lié à l'évènement. Elle sera exécutée quand l'utilisateur cliquera sur le bouton.
On aurait pu créer soi-même la gestion des évènements en nommant la fonction liée au 'Click' du bouton dans le code XAML :
|
Il faut dans ce cas ensuite créer une fonction MyButtonClick en C#.
|
sender est l'objet qui a déclenché l'évènement (le bouton ici).
e est de type RoutedEventArgs et contient les arguments de l'évènement.
On remarque que pour pallier la disparition des 'groupes de contrôles' et pour que le clic,
sur plusieurs boutons, exécute la même fonction, on peut indiquer Click="MyButtonClick" pour plusieurs
boutons.
|
IV-G. Extension de balisage
On a vu qu'un attribut avait une valeur, mais il peut aussi avoir comme valeur une
extension.
Les principales extensions sont les Binding et les ressources.
Les caractères { et } indiquent une extension de balisage (markup extension).
Exemple d'une extension : dans un 'Border', on utilise comme Style une ressource (staticResource) nommée PageBackground.
|
Exemple d'une extension avec ici une liaison de données (Binding). Ici le texte du TextBlock prendra la valeur de Title.
|
x:Key.
Définit une clé unique (un 'nom' unique ) pour chaque ressource dans un ResourceDictionnary ; pour utiliser cette ressource, on l'appellera par son nom.
Créons une ressource pour une grille, c'est un LinearGradientBrush (un dégradé) que l'on 'nomme' "FunkyBrush" (c'est son nom, une clé unique).
Créons une ressource pour une grille, c'est un LinearGradientBrush (un dégradé) que l'on 'nomme' "FunkyBrush" (c'est son nom, une clé unique).
|
Ensuite on peut l'utiliser dans la grid :
|
Code complet :
|
La dernière ligne peut aussi être écrite sans extension de balisage, sous la forme :
|
On ajoute que :
x:Name.
Identifie de manière unique les éléments définis en XAML comme les contrôles.
x:Class.
Définit l'espace de noms et le nom d'une classe.
IV-H. Espace de noms
Chapitre difficile ! À lire plus tard et plusieurs fois.
On a vu qu'au début du fichier XAML, on pouvait inclure un espace de noms grâce à 'xmlns:' (XML Name Space) et ainsi donner accès à des objets extérieurs.
La syntaxe est :
|
alias est maintenant le nom local de l'espace de noms 'namespace identifier'.
Pour utiliser un objet de l'espace de noms.
|
Voyons les espaces de noms qui sont déjà présents.
Déclarations des espaces de noms silverlight et XAML
Ce sont les deux premières lignes du code XAML. Elle indiquent une adresse Web.
Déclarations des espaces de noms silverlight et XAML
Ce sont les deux premières lignes du code XAML. Elle indiquent une adresse Web.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
C'est l'espace de noms XAML.
:x est là pour créer l'alias x (remarquer le ':').
La ligne indique l'espace de noms 'xaml', dessous il se nommera 'x:',
on le retrouve dans x:Key, x:Name…
:x est là pour créer l'alias x (remarquer le ':').
La ligne indique l'espace de noms 'xaml', dessous il se nommera 'x:',
on le retrouve dans x:Key, x:Name…
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
C'est l'espace de noms silverlight (à noter que cet espace de noms contient les classes des objets visuels. Il contient les classes Button, ListBox…)
On remarque que la ligne commence par xmlns= sans ':' il n'y a donc pas d'alias et les classes de cet espace de noms peuvent être utilisées sans préfixe.
C'est l'espace de noms silverlight (à noter que cet espace de noms contient les classes des objets visuels. Il contient les classes Button, ListBox…)
On remarque que la ligne commence par xmlns= sans ':' il n'y a donc pas d'alias et les classes de cet espace de noms peuvent être utilisées sans préfixe.
On pourra instancier un objet dont la classe est dans cet espace de noms :
|
On remarque qu'on utilise 'Name' car c'est l'espace de noms par défaut.
On va maintenant voir comment inclure d'autres espaces de noms dans le code XAML.
Il faudra utiliser 'clr-namespace' : espace de noms CLR (Common Language Runtime) déclaré dans l'assembly qui contient les types publics. On déclarera l'espace de noms et si nécessaire l'assembly (nom de la DLL) ; ici on n'utilise plus l'URL.
Il faudra utiliser 'clr-namespace' : espace de noms CLR (Common Language Runtime) déclaré dans l'assembly qui contient les types publics. On déclarera l'espace de noms et si nécessaire l'assembly (nom de la DLL) ; ici on n'utilise plus l'URL.
Exemple : espace de noms: 'MyNameSpace' contenant une classe 'SuperButton'.
|
Remarquons qu'on a donné un nom, un alias (Mns) à l'espace de noms 'MyNameSpace' grâce à 'xmlns:Mns'.
On utilise les ':'. Maintenant quand on utilise 'Mns' on utilise en fait 'MyNameSpace'.
L'assembly peut être omis si l'espace de noms référencé est défini dans le même assembly que l"application.
On utilise les ':'. Maintenant quand on utilise 'Mns' on utilise en fait 'MyNameSpace'.
L'assembly peut être omis si l'espace de noms référencé est défini dans le même assembly que l"application.
Ensuite, toujours en XAML on peut utiliser un objet de cet espace de noms :
|
Remarquons qu'on utilisera la syntaxe 'Espacedenom:Objet' avec 'Mnp:MyObjet'.
On utilise 'x:Name' car l'instance appartient à un autre espace de noms que celui par défaut.
Cela permettra d'utiliser le nom dans le code-behind.
On utilise 'x:Name' car l'instance appartient à un autre espace de noms que celui par défaut.
Cela permettra d'utiliser le nom dans le code-behind.
Si l'espace de noms fait partie d'un autre assembly (d'une autre ddl), il faudra ajouter le nom de l'assembly.
Par exemple, on a un espace de noms 'CustomClasses' qui est dans un assembly nommé 'Custom' (la DLL custom.dll) ; on veut utiliser la classe 'MyControle' de cet espace de noms, on doit écrire :
|
On remarque après 'assembly' il y a '='.
Puis pour utiliser 'MyControle'.
Puis pour utiliser 'MyControle'.
|
Exemples : comment utiliser dans le code XAML une classe créée dans le code C#.
Je crée une classe 'MyButton' (qui hérite de Button) dans l'espace de noms 'MyControle'.
Voyons le code C# (il est dans le code C# de l'application) :
|
Pour utiliser MyButton dans le code XAML :
|
L'interface a un comportement bizarre. Il faut compiler le projet ce qui compile le code correspondant à la classe ensuite pas de problème.
Autre exemple : si je veux utiliser des string dans un dictionnaire de ressources, il faut que j'importe l'espace de noms 'system' de mscorelib.dll :
|
Ne pas oublier que :
x:Class NameSpace.PageName, qui est la première ligne de la page XAML, permet d'indiquer l'espace de noms et le nom de la classe de la page et de faire ainsi le lien entre la classe XAML et la classe partielle de même nom contenant le code en C#.
x:Class NameSpace.PageName, qui est la première ligne de la page XAML, permet d'indiquer l'espace de noms et le nom de la classe de la page et de faire ainsi le lien entre la classe XAML et la classe partielle de même nom contenant le code en C#.
x:Name identifie de manière unique des éléments objets afin d'accéder à l'objet instancié à partir du code-behind ou du code général.
x:Key est lui, utilisé dans les ressources.
IV-I. Remarque importante
Il est important de comprendre que tout le code écrit en XAML peut aussi être écrit en C#.
|
Ce code, dans la fenêtre XAML crée un bouton ; on peut aussi créer ce bouton dans le code C# :
|
Ici on déclare un bouton, on donne ses dimensions et le texte, enfin on l'ajoute au StackPanel nommé ContentPanel.
V. Silverlight pour WP

Windows Phone 7.1 utilise silverlight 4 avec certaines particularités pour Windows Phone:
Il y a en plus dans WP 7.1 les éléments relatifs aux opérations de touché de l'écran.
Il y a en plus dans WP 7.1 les éléments relatifs aux opérations de touché de l'écran.
On peut charger la Documentation silverlight 4 Offline (fichier .CHM) en français,
Documentation silverlight 4 Attention c'est silverlight et pas silverlight pour Windows Phone, mais c'est une bonne doc !
Documentation silverlight 4 Attention c'est silverlight et pas silverlight pour Windows Phone, mais c'est une bonne doc !
V-A. La classe 'Control'
Les contrôles permettent de créer une interface utilisateur.
Les contrôles silverlight dérivent de la classe Control qui fait partie de l'espace de noms System.Windows.Controls.
Voici les classes dont dérive Control :
System.Object
System.Windows.DependencyObject
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control.
Voici les classes dont dérive Control :
System.Object
System.Windows.DependencyObject
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Control.
C'est la classe UIElement qui donne le pouvoir d'apparaître comme objet visuel et de recevoir des entrées.
La classe Control hérite des propriétés des classes parentes.
Aussi tous les contrôles ont des propriétés communes :
Les propriétés de dépendances.
Les propriétés de positionnement : Height, Width, Margin, HorizontalAlignment…
Les évènement de vie : Load, Unload, DataContext.
Le style.
Les ControlTemplate.
Les polices de caractères utilisées : FontFamily, FontSize…
La classe Control hérite des propriétés des classes parentes.
Aussi tous les contrôles ont des propriétés communes :
Les propriétés de dépendances.
Les propriétés de positionnement : Height, Width, Margin, HorizontalAlignment…
Les évènement de vie : Load, Unload, DataContext.
Le style.
Les ControlTemplate.
Les polices de caractères utilisées : FontFamily, FontSize…
V-A-1. Ajouter un contrôle
Pour mettre un contrôle dans une page, un bouton par exemple, il y a quatre manières :
- en mode 'Design', aller le chercher dans la boîte à outils et le déposer sur la page (drag and drop) ;

-l'ajouter à l'aide de code XAML ;
Il faut taper dans la fenêtre XAML :
|
Cela ajoute à la page un bouton sur lequel est affiché 'Ok'.
-l'ajouter dans le code C# :
|
On note qu'après avoir déclaré le bouton, on l'a ajouté aux enfants d'un conteneur nommé ContentPanel.
- utiliser 'Expression Blend' l'application graphique.
Il est possible ensuite de modifier ses propriétés.
Modifions la couleur de l'arrière plan du bouton, par exemple.
- En mode 'Design', dans la fenêtre de propriété en bas à droite.

-à l'aide de code XAML (ajout d'attribut 'simple') :
|
ou de manière plus complexe par ajout d'une Brush sur le fond :
|
-A l'aide de code C# :
|
On crée une nouvelle instance de SolidColorBrush de couleur bleue.
V-A-2. Particularités des contrôles
Propriétés de dépendance :
Les propriétés des contrôles et leur valeur ne sont pas 'figées' (comme dans les Windows Forms où elles ont
une valeur donnée) mais elles peuvent 'dépendre' d'autres choses. Les propriétés de dépendance
permettent de calculer la valeur d'une propriété en fonction de la valeur d'autres entrées. Ces autres
entrées peuvent être des propriétés système (des thèmes et des préférences utilisateur), des valeurs
déterminées au dernier moment (liaison de données, animations), des ressources et des styles ou
des valeurs issues de relations parent-enfant d'autres éléments.
Propriétés attachées :
Les propriétés attachées permettent à des éléments enfants de spécifier des valeurs pour une propriété
définie dans un élément parent. Cela permet de faire en sorte que les éléments enfants informent
l'élément parent sur la manière dont ils doivent être présentés dans l'interface.
La propriété DockPanel.Dock en est un exemple. Dans un Panel, il y a plusieurs enfants, plusieurs boutons,
par exemple. La propriété DockPanel.Dock de chaque bouton (enfant) permet au Panel (le parent) de positionner les boutons
dans le Panel.
Particularités des contrôles Silverlight:
Les contrôles qui ont une propriété 'Content' (les boutons, par exemple) peuvent contenir un Objet (du texte oui mais aussi une Grid, une Image, un StackPanel…), c'est extrêmement puissant.
V-A-3. Évènements
Créons un bouton avec le code XAML suivant :
|
Si je double-clique sur ce bouton dans le designer, je me retrouve dans le code-behind en C# qui a créé automatiquement la fonction évènement suivante :
|
Quand l'utilisateur du logiciel clique sur le bouton, c'est cette fonction qui sera exécutée.
De plus il y a eu un ajout dans le code XAML du bouton :
|
Click="Button_Click indique que lorsque l'évènement Click survient sur le bouton la fonction Button_Click est exécutée.
On aurait pu ajouter l'attribut Click="OnClick" en le tapant au clavier, cela aurait donné le code XAML suivant.
|
Dans ce cas, en double-cliquant sur le bouton, la routine suivante aurait été créée :
|
Il est aussi possible de taper 'Click="bouton_click"', puis de mettre le curseur sur bouton_click et de faire un clic droit. Cela ouvre un menu, cliquez sur 'Naviguer vers le gestionnaire d'évènements'.

Cela crée dans le code-behind la fonction évènement :
|
sender est l'objet qui a déclenché l'évènement, je dis bien 'Object' (il faudra le convertir en Button pour utiliser la propriété Name par exemple).
e contient les arguments de l'évènement, remarquons que e est de type RoutedEventArgs (et pas EventArgs comme dans les Windows Forms).
Sur un Windows Phone l'utilisateur tape avec son doigt sur l'écran.
Quel évènement utiliser ? Bien sûr pour un bouton c'est Click. Sur une ListBox il y a les évènements KeyDown, KeyUp, MouseLeftButtonDown, SelectionChanged, MouseLeftButtonUp ; ce dernier semble bien fonctionner pour intercepter la 'tape' du doigt.
Quel évènement utiliser ? Bien sûr pour un bouton c'est Click. Sur une ListBox il y a les évènements KeyDown, KeyUp, MouseLeftButtonDown, SelectionChanged, MouseLeftButtonUp ; ce dernier semble bien fonctionner pour intercepter la 'tape' du doigt.
Évènement routé :
Quand survient un évènement sur un contrôle, un clic sur un bouton, par exemple, si cet évènement n'est pas traité au niveau du bouton, un parent comme le StackPanel qui contient
le bouton peut traiter l'évènement. Cela est possible car l'évènement 'remonte' de parent en parent.
On peut ainsi dans le StackPanel 'parent' gérer l'évènement Click de tous les boutons enfants :
|
Dans le code C# on peut créer un contrôle et le gestionnaire d'évènements routé correspondant :
|
myButton.Click += new RoutedEventHandler(button1_Click) permet de créer un RoutedEventHandler qui indique d'exécuter la fonction 'Button1_Click' quand l'utilisateur clique sur le button1.
On peut écrire plus simplement :
|
V-A-4. Saisie tactile
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) et 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.
|
Il existe aussi des évènements de bas niveau, des évènements de haut niveau sur le UIElement (Tap, DoubleTap …) et des évènements de gesture dans le toolkit (voir chapitre sur les gestures).
V-A-5. Modèle de contenu
Pour être complet, il y a quatre modèles de contenu :
- ContentControl :
sa propriété Content contient un objet. Exemple : Button ;
- HeaderContentControl :
sa propriété Content contient un objet. Sa propriété Header fournit un titre au contrôle. Exemples : GroupBox, TabItem ;
- ItemsControl :
sa propriété Items contient une collection d'objets de même type. Exemple : ListBox contient des ListBoxItem, il y a les objets
conteneurs 'Panel' (comme les Grid, StackPanel…) qui contiennent une collection d'objets (Children) ;
- HeaderItemsControl :
sa propriété Header fournit un titre au contrôle. Sa propriété Items contient une collection d'objets.

V-B. Les applications et pages
Une application Windows Phone contient une Frame dans laquelle se trouve des Pages.
Chaque page est dans un fichier .xaml.
La page correspond au contenu d'un écran. Un appareil Windows Phone 7 possède un écran de 480 × 800 pixels.
Chaque page est dans un fichier .xaml.
La page correspond au contenu d'un écran. Un appareil Windows Phone 7 possède un écran de 480 × 800 pixels.
Quand on crée un nouveau projet nommé MyProjet, Visual Studio crée une page nommé MainPage.xaml (la page de démarrage) qui contient :
|
Dans la balise PhoneApplicationPage :
x:Class="MyProjet.MainPage indique l'espace de noms (le nom du projet par défaut) et la classe de la page.
En effet une page se présente comme une classe (dans le code XAML) plus le code C# correspondant qui se trouve dans une classe partielle.
On a ensuite la déclaration des espaces de noms (xml name space) utilisés dans la page :
L'espace de nom silverlight :
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
L'espace de nom XAML :
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
L'espace de noms contenant les contrôles :
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
Et d'autres :
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
On remarque que la première ligne commence par xmlns= sans ':', il n'y a donc pas d'alias et les classes de cet espace de noms peuvent être utilisées sans préfixe. Dans les autres lignes il y a un alias (:x par exemple) ce qui oblige à utiliser l'alias ( x:Name par exemple).
Le "d" (de "designer") et le "mc" (de "markup compatibility") dans la déclaration des espaces de noms sont utilisés par les programmes comme Expression Blend et le designer de Visual Studio. DesignerWidth et DesignerHeight sont ignorés durant la compilation.
Puis on indique la police à utiliser dans la page, sa taille et le Foreground (couleur des caractères) :
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
On indique aussi l'orientation supportée et l'orientation en cours :
SupportedOrientations="Portrait" Orientation="Portrait".
shell:SystemTray.IsVisible="True" indique d'afficher la barre système.
On a ensuite une grille qui est l'élément racine.
Cette grille contient des StackPanel affichant le titre de la page puis le contenu de l'application.
x:Class="MyProjet.MainPage indique l'espace de noms (le nom du projet par défaut) et la classe de la page.
En effet une page se présente comme une classe (dans le code XAML) plus le code C# correspondant qui se trouve dans une classe partielle.
On a ensuite la déclaration des espaces de noms (xml name space) utilisés dans la page :
L'espace de nom silverlight :
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
L'espace de nom XAML :
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
L'espace de noms contenant les contrôles :
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
Et d'autres :
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
On remarque que la première ligne commence par xmlns= sans ':', il n'y a donc pas d'alias et les classes de cet espace de noms peuvent être utilisées sans préfixe. Dans les autres lignes il y a un alias (:x par exemple) ce qui oblige à utiliser l'alias ( x:Name par exemple).
Le "d" (de "designer") et le "mc" (de "markup compatibility") dans la déclaration des espaces de noms sont utilisés par les programmes comme Expression Blend et le designer de Visual Studio. DesignerWidth et DesignerHeight sont ignorés durant la compilation.
Puis on indique la police à utiliser dans la page, sa taille et le Foreground (couleur des caractères) :
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
On indique aussi l'orientation supportée et l'orientation en cours :
SupportedOrientations="Portrait" Orientation="Portrait".
shell:SystemTray.IsVisible="True" indique d'afficher la barre système.
On a ensuite une grille qui est l'élément racine.
Cette grille contient des StackPanel affichant le titre de la page puis le contenu de l'application.
Il doit y avoir un élément racine (root) et un seul dans un fichier XAML, il contient tous les autres : c'est la grille 'LayoutRoot'.
Il y a aussi création d'un fichier MainPage.xaml.cs qui contient le code en C#.
|
L'espace de noms est celui du projet (MyProjet). Il y a une 'partial class' nommée MainPage.
La page est donc composée d'une classe en XAML complétée d'une partie C# : une classe partielle.
L'interface graphique écrite en XAML sera générée à la compilation et fusionnera avec le reste de la classe partielle définie dans le code-behind. Nous avons donc une seule et même classe définie dans deux fichiers différents (le fichier généré à partir du XAML étant caché de l'utilisateur et se nommant MainPage.Xaml.g.i.cs).
La page est donc composée d'une classe en XAML complétée d'une partie C# : une classe partielle.
L'interface graphique écrite en XAML sera générée à la compilation et fusionnera avec le reste de la classe partielle définie dans le code-behind. Nous avons donc une seule et même classe définie dans deux fichiers différents (le fichier généré à partir du XAML étant caché de l'utilisateur et se nommant MainPage.Xaml.g.i.cs).
L'explorateur de solution en haut à droite permet de voir de quoi se compose le projet 'MyProjet'.

Properties donne accès aux propriétés du projet.
Références indique les DLL chargées dans le projet.
On voit aussi :
le code XAML de l'application : App.xaml et en developpant, App.xaml.cs ;
les icônes et images du projet : ApplicationIcon.png, Background.png, SplashScreenImage.jpg ;
la page (MainPage ici) composée de l'interface (MainPage.xaml) et du code C# (MainPage.xaml.cs).
le code XAML de l'application : App.xaml et en developpant, App.xaml.cs ;
les icônes et images du projet : ApplicationIcon.png, Background.png, SplashScreenImage.jpg ;
la page (MainPage ici) composée de l'interface (MainPage.xaml) et du code C# (MainPage.xaml.cs).
Voyons le détail du fichier App.xaml, le fichier 'Application' dans lequel on peut mettre les ressources de l'application (balise Application.resources).
|
Voyons le détail du fichier App.xaml.cs (pour le voir, cliquer sur le petit triangle à droite de 'App.xaml'), le fichier comporte, par défaut, des commentaires qui expliquent bien la fonction de chaque ligne.
|
![]() | En résumé : une page est donc une classe, elle est composée d'une partie XAML et d'une partie C#, tout cela est dans l'espace de noms ayant le nom de l'application. |
Comment ouvrir une page nommée 'PageConvert.xaml' dans le code C# ?
|
V-C. Conteneur, position, dimensions des contrôles
Le positionnement des contrôles est fondamental, il faut bien le comprendre.
Comparaisons avec les WindowsForms.
En Windows Forms on pouvait mettre autant de contrôles que l'on voulait dans une fenêtre et on
utilisait simplement les coordonnées du coin supérieur gauche d'un contrôle pour définir sa position.
En Windows Forms,
en cas de changement d'écran ou de modification des dimensions d'une fenêtre, si on voulait un réagencement,
il faudrait tout gérer soit même.
En silverlight il faut utiliser la notion de conteneur et de position dans ces conteneurs. Le positionnement est relatif. Il y a capacité d'adaptation
aux modifications d'affichage et de disposition des fenêtres. Silverlight gère la négociation entre les
contrôles pour déterminer la disposition. Un contrôle informe son parent de l'emplacement et de
la taille dont il a besoin ; deuxièmement, le parent informe le contrôle de l'espace dont il peut
disposer. Cette disposition dynamique fait qu'un contrôle est positionné
sur une page en fonction de son contenu, de son conteneur de disposition parent.
La disposition silverlight est basée sur les grilles (Grid), l'empilement (Stack) et l'ancrage des contrôles.
V-C-1. Hiérarchie des contrôles, arbre
Contrôles conteneurs et non conteneurs.
Certains contrôles (dits 'non conteneurs') ne peuvent contenir qu'un contrôle. Essayer de mettre deux TextBlock
dans un bouton avec le designer ou une image et un texte dans un bouton : impossible !
Certains contrôles (dits 'conteneurs') peuvent contenir plusieurs contrôles. Une Grid, par exemple, qui peut
contenir un élément dans chacune de ses cellules ; un StackPanel peut contenir en empilement de contrôles.
Pour un bouton par exemple, en C# :
|
affiche le texte 'Ok' dans le bouton.
En XAML :
|
Content.
Dans un contrôle non conteneur, la propriété 'Content' ne peut contenir qu'un objet et un seul.
Pour un bouton par exemple, on a deux manières d'écrire le texte du bouton :
Pour un bouton par exemple, on a deux manières d'écrire le texte du bouton :
|
ou :
|
car Content est la propriété par défaut.
Content peut contenir un texte mais pas seulement ; en fait il peut contenir un
Objet (un seul) : du texte mais aussi un objet conteneur comme une
Grid, un Canvas, un StackPanel… qui lui peut contenir plusieurs contrôles. Cela
revient à mettre autant de contrôles que l'on veut dans un contrôle.
Les conteneurs comme une Grid par exemple, ont une propriété nommé Children qui permet d'ajouter plusieurs
contrôles.
|
À titre d'exemple, on peut mettre une Grid dans un bouton et mettre dans les cellules de cette Grid deux
textes, une image, une vidéo…
Voyons maintenant un exemple en XAML d'un conteneur, un StackPanel contenant un TextBlock et trois boutons :
|
Pour être complet certains contrôles ont un contenu spécifique : un TextBlock par exemple, qui ne peut afficher que du texte, a une propriété 'text' permettant d'inclure du texte (et uniquement du texte).
Graphes d'objets.
Ainsi il y a des objets dans d'autres et donc une hiérarchie des contrôles qui peut être représentée
par un graphe.
Cela a son importance car on a vu qu'un évènement (un clic, par exemple) qui survient sur un contrôle (l'image en bas à droite) peut être routé, remonter et être exploité plus haut (au niveau de la grille, par exemple).
La classe VisualTreeHelper permet de trouver le parent ou les enfants d'un contrôle :
|
À noter que GetChild retourne parfois des choses bizarres ! bogue ?
V-C-2. Nom, position et dimensions d'un contrôle
Ajoutons un bouton à la page, déplaçons le à la souris :

Cela affiche le code XAML suivant :
|
Name indique le nom du contrôle.
Content indique le texte affiché dans le bouton.
Height et Width indiquent les dimensions du bouton.
Margin indique les marges autour du bouton.
HorizontalAlignment indique sur quoi est ancré le bouton.
Content indique le texte affiché dans le bouton.
Height et Width indiquent les dimensions du bouton.
Margin indique les marges autour du bouton.
HorizontalAlignment indique sur quoi est ancré le bouton.
Voyons cela en détails :
Dimensions d'un contrôle.
Les dimensions sont, par défaut, en pixels (px) ou "device independente unit".
Noter que les valeurs des dimensions et coordonnées sont des 'Double' (nombre réel en virgule flottante double précision).
|
En C# :
|
On peut utiliser une unité différente :
px (valeur par défaut) représente les device-independente units ou pixels (1/96th inch per unit ;)
in est l'abréviation du mot anglais « inches » (pouces) ; 1 in = 96 px ;
cm correspond à centimètres ; 1 cm = (96/2,54) px ;
pt correspond à points ; 1 pt = (96/72) px.
px (valeur par défaut) représente les device-independente units ou pixels (1/96th inch per unit ;)
in est l'abréviation du mot anglais « inches » (pouces) ; 1 in = 96 px ;
cm correspond à centimètres ; 1 cm = (96/2,54) px ;
pt correspond à points ; 1 pt = (96/72) px.
Exemple :
|
Largeur et hauteur du bouton en centimètres.
|
Hauteur de la police : 36 pixels soit 36x72/96 = 24 points.
Width et Height peuvent aussi prendre la valeur Auto. L'élément remplit alors la largeur ou la hauteur disponible dans le conteneur (cela semble fonctionner uniquement s'il n'y a pas de HorizontalAlignment ou de VerticalAlignment ni de Margin).
On peut spécifier :
MinWidth et MaxWidth (0 et infinity par défaut),
MinHeight et MaxHeigth.
MinWidth et MinHeight servent à indiquer des dimensions minimales afin qu'un texte, par exemple, ne soit pas tronqué.
MinWidth et MaxWidth (0 et infinity par défaut),
MinHeight et MaxHeigth.
MinWidth et MinHeight servent à indiquer des dimensions minimales afin qu'un texte, par exemple, ne soit pas tronqué.
Enfin ActualWidth et ActualHeigth indiquent les dimensions actuelles réelles, si des contraintes (relation avec les autres contrôles, disposition…) imposent des dimensions différentes de celles qu'on désirait. La disposition peut parfois rejeter les dimensions proposées.
Alignement :
VerticalAlignement et HorizontalAlignment définissent sur quoi est aligné le contrôle. Le contrôle y sera 'ancré', si on modifie les dimensions du conteneur, le contrôle suivra.
Cela remplace la propriété 'Anchor' des Windows Forms.
Rappelons que si on modifie la taille du conteneur, le contrôle reste à égale distance du bord sur lequel il est aligné (ancré).
Valeur possible pour VerticalAlignement : Top, Bottom, Center, Stretch (étire le contrôle et le remplit verticalement).
Valeur possible pour HorizontalAlignment : Left, Right, Center, Stretch (étire le contrôle et le remplit horizontalement).
Attention, si on renseigne Width et Height Stretch ne fonctionne pas !
Margin définit les distances au conteneur, les marges.
Margin="30,64,128,0" indique les marges gauche, supérieure, droite, inférieure.
Margin="30" indique que toutes les marges sont à 30.
Dans la fenêtre des propriétés d'un contrôle, la flèche à droite de la propriété 'Margin' ouvre l'éditeur de marges :

Paddding définit l'épaisseur d'une marge dans le contrôle. (valable dans certains contrôles seulement).
![]() | En pratique on positionne et on dimensionne le contrôle à la souris ce qui modifie en conséquence les propriétés Width, Height et Margin. |
En résumé :
Silverlight commence par regarder la propriété "Width". Si elle est définie, c'est cette valeur qui est utilisée pour la largeur du composant, même si "HorizontalAlignment=Strech". Si aucune valeur n'est spécifiée ou qu'elle vaut "Auto", Silverlight regarde la valeur de "HorizontalAlignment". Si la valeur est "Strech", la largeur sera tout l'espace disponible. Sinon, la propriété "Width" étant sur "Auto", la largeur s'adaptera au contenu.
Silverlight commence par regarder la propriété "Width". Si elle est définie, c'est cette valeur qui est utilisée pour la largeur du composant, même si "HorizontalAlignment=Strech". Si aucune valeur n'est spécifiée ou qu'elle vaut "Auto", Silverlight regarde la valeur de "HorizontalAlignment". Si la valeur est "Strech", la largeur sera tout l'espace disponible. Sinon, la propriété "Width" étant sur "Auto", la largeur s'adaptera au contenu.
![]() | Bien comprendre qu'on ne travaille plus en coordonnées absolues de position du contrôle (Left, Top c'est fini…) mais plutôt en accrochant les contrôles (avec une marge autour) dans un conteneur (Grid, StackPanel). |
Dans ce chapitre, on voit le positionnement d'un contrôle dans un conteneur, pour être complet, il faut aussi voir le chapitre sur les conteneurs et les règles de positionnement dynamique. Dans une grille par exemple, dans chaque cellule on pourra positionner un contrôle comme indiqué ici avec une 'margin' autour.
Exemple de création de contrôle entièrement en C# :
On peut avoir besoin au cours du déroulement de l'application de créer de toute pièce un bouton.
Ici on a mis le code dans le constructeur de la page.
On peut avoir besoin au cours du déroulement de l'application de créer de toute pièce un bouton.
Ici on a mis le code dans le constructeur de la page.
|
On remarque que si on crée un contrôle dans le code C#, il est nécessaire d'ajouter ce contrôle à un conteneur déjà présent sinon le contrôle n'apparaît pas.
On voit aussi que Margin (comme Padding) accepte un objet Thickness (épaisseur). On en crée un avant de l'affecter à la propriété Margin.
On voit aussi que Margin (comme Padding) accepte un objet Thickness (épaisseur). On en crée un avant de l'affecter à la propriété Margin.
V-C-3. Plan
Les objets peuvent être au premier plan ou au second plan : l'objet de premier plan apparaîtra au dessus des autres et les cachera s'il n'est pas transparent.
Dans le designer, cliquer sur un objet visuel, clic droit puis 'Ordre' puis 'Mettre au premier plan'.

En fait, il n'y a pas de propriété indiquant le plan, silverlight affiche les objets qui se trouvent dans un conteneur dans l'ordre du code XAML ; le fait de mettre un objet au premier plan met le code XAML de l'objet à la fin du conteneur :
|
Ici l'image nommée 'Image' sera au premier plan.
V-D. Aspect des contrôles
Quand on dépose un bouton dans un formulaire, il a un aspect 'standard', on a souvent besoin de modifier sa couleur ou sa forme, son aspect visuel ; c'est ce que nous allons voir.
Dans ce chapitre on travaille sur UN contrôle. Dans le chapitre sur les ressources, on verra comment créer des modèles de contrôles (avec les Styles et les Templates) pour les appliquer à un, plusieurs ou tous les contrôles.
V-D-1. Propriétés des contrôles
Ici on garde l'aspect général du contôle, on modifie simplement ses propriétés (Couleur, texte, font…).
On veut avoir ce beau bouton (bof !), ci-dessous l'exemple :
Avec le designer, on prend un bouton dans la boîte à outils, on le pose dans un conteneur (une grid, par exemple).
Pour définir les dimensions, la couleur et le texte dans le bouton, on va modifier les propriétés dans la fenêtre de propriétés en bas à droite :

- Height et Width permettent de modifier les dimensions ;
- Foreground et Background donnent la couleur du texte et du fond ;
- BorderBrush et BorderThickness indique la couleur et l'épaisseur des bords ;
- FontFamily indique le nom de la police de caractères ;
- FontSize indique la hauteur de la police ;
- FontStyle permet de choisir entre Normal, Italic, Oblique ;
- FontWeight permet de choisir entre Normal, Bold, Heavy… ;
- Name donne le nom du bouton en haut de la fenêtre ;
- Content indique le texte à afficher.
En bas de l'écran dans la fenêtre XAML, apparaît le code XAML correspondant au bouton.
|
Dans une fenêtre vide, on aurait pu coller le code XAML entre les balises Grid et voir apparaître le bouton.
On aurait pu créer le bouton avec du code C# :
|
On a à notre disposition une classe Colors qui contient les couleurs :
On ne peut pas affecter directement une couleur à une propriété définissant une couleur : myButton.Background = Colors.Red; ne fonctionne pas.
Il faut instancier et utiliser une SolidColorBrush :
|
Il en est de même avec FontFamily, FontStyle, FontWeight et Thickness (épaisseur). Il faut instancier une FontFamily, un FontStyle, un FontWeight ou un Thickness pour donner une valeur à la propriété correspondante.
L'énumération Brushes que l'on peut utiliser en WPF ne fonctionne pas ici :
|
Au lieu de mettre une couleur unie dans le fond d'un contrôle, on peut y mettre une 'LinearGradientBrush' ce qui produit un bel aspect de Background dégradé.
Cela donne :

En XAML :
|
Un contrôle peut être visible ou non :
(Visible ou Collapsed qui correspond à une taille de zéro et n'occupe pas d'espace dans le layout.)
|
En C# :
|
On peut ajouter l'attribut Opacity dont la valeur va de 0 à 1.
|
Avec la valeur 0.5 l'image est semi-transparente.
On peut aussi modifier les propriétés d'un contrôle ou d'un type de contrôle (tous les boutons de l'application) à l'aide des Ressources des Styles ; voir le chapitre 'Ressources'. Enfin on peut utiliser les data templates et contrôles templates (voir plus bas).
V-D-2. Contrôle contenant des contrôles
On a vu que la propriété Content d'un bouton pouvait contenir un objet mais un seul. On peut y mettre du texte, mais comment mettre un texte et une image dans un bouton ?
Il faut mettre un StackPanel (ou une Grid) dans le bouton (puisque celui-ci ne peut contenir qu'un seul objet), dans ce StackPanel (qui lui est un conteneur qui peut contenir x contrôles empilés) mettre un TextBlock et une Image. Dans le designer c'est difficile de mettre un StackPanel dans un Button, il se met dessus et pas dedans (c'est galère !), donc tapez ou collez le code XAML du StackPanel dans le bouton. De plus l'image doit être dans les ressources : passer par le menu 'Projet' puis 'Ajouter un élément existant', indiqué 'resources' dans les 'options de génération' en bas. Voir le chapitre sur les ressources.
|
Cela donne :

On se rend compte de la puissance de silverlight : on peut mettre autant de contrôles que l'on veut dans un contrôle en utilisant des conteneurs. Dans notre bouton on aurait pu mettre deux images, deux textes…
V-D-3. Aspect visuel des contrôles: template visuel, style
Ici on modifie l'aspect profond des contrôles.
Chaque contrôle possède un template visuel ou Control Template qui permet de définir l'aspect visuel du contrôle, le template indique comment il sera dessiné (forme, arrière plan, bords, coins, contenu…).
Ce template est entre les balises 'Button.Template' pour un bouton. On peut bien sûr modifier ce template, ce qui modifie l'aspect du bouton. On peut ainsi obtenir des boutons ronds, elliptiques…

Dans le template du bouton, ici, on va définir la forme qui est un rectangle mais aussi la forme des coins (radius).
On va donc faire un bouton Cyan avec des coins ronds (grâce à Rectangle RadiusX="39" RadiusY="39").
|
Cela donne :

On voit qu'à partir du moment ou on utilise le ControlTemplate, il faut tout refaire, la forme du contrôle (Rectangle), mais aussi l'aspect du contenu ce qui explique l'usage du ContentPresenteur qui permet de gérer le contenu. On aurait pu ajouter l'aspect du bouton s'il est 'Enabled', 'Focused' ou 'cliqué' (voir le détail d'un template dans le chapitre sur les ressources).
Pour les listes on a un ItemsPresenter.
Pour les listes on a un ItemsPresenter.
Si au lieu de mettre 'Rectangle Radius…' on met 'Ellipse', le bouton est en forme d'ellipse.
|

Cette exemple fonctionne mais est incomplet car comme dans le template, on n'a pas défini l'aspect du bouton en cas de clic ou quand il a le focus, le bouton ne change donc jamais d'aspect même quand on clique dessus !
On pourrait créer un Style pour un bouton. En fait c'est beaucoup plus simple d'utiliser une propriété (les Styles sont plutôt utilisés dans les ressources).
Dans ce chapitre, on a modifié UN contrôle directement, il est possible de modifier un contrôle avec un style ou plusieurs contrôles de même type. Voir le chapitre sur les ressources qui parle des modèles de contrôles et donne un exemple complet.
Enfin, pour être complet, il est possible de modifier l'aspect des données dans un contrôle grâce aux Data Template (modèle de données).
V-D-4. Transformation
Pour effectuer une transformation 2D sur un UIElement, on utilise la propriété RenderTransform.
On peut modifier l'échelle, la rotation, l'oblicité, le déplacement.
On peut modifier l'échelle, la rotation, l'oblicité, le déplacement.
Échelle :
on peut effectuer une transformation horizontale ou verticale grâce à un ScaleTransform.
Pour cela on définit ScaleX et ScaleY.
on peut effectuer une transformation horizontale ou verticale grâce à un ScaleTransform.
Pour cela on définit ScaleX et ScaleY.
Dans un bouton, on dessine une loupe (avec un Path), puis on va l'agrandir grâce à RenderTransform.
ScaleX="3" ScaleY="3" indiquent d'agrandir de trois fois.
ScaleX="3" ScaleY="3" indiquent d'agrandir de trois fois.
|

Si ScaleX ou ScaleY sont négatifs, il y a inversion de l'élément.
Attention pour que l'élément reste au même endroit, il faut modifier l'origine de la transformation dans l'élément (origine est par défaut sur le coin supérieur gauche ce qui déplacerait l'élément en haut à gauche).
Exemple avec un bouton.
Attention pour que l'élément reste au même endroit, il faut modifier l'origine de la transformation dans l'élément (origine est par défaut sur le coin supérieur gauche ce qui déplacerait l'élément en haut à gauche).
Exemple avec un bouton.
|

Rotation :
On peut effectuer une rotation grâce à un RotateTransform.
Pour cela on définit Angle et si nécessaire CenterX et CenterY.
Exemple : texte vertical.
On peut effectuer une rotation grâce à un RotateTransform.
Pour cela on définit Angle et si nécessaire CenterX et CenterY.
Exemple : texte vertical.
|

Inclinaison :
On peut effectuer une inclinaison grâce à un SkewTransform.
Pour cela on définit AngleX AngleY et si nécessaire CenterX et CenterY.
Exemple : texte penché.
On peut effectuer une inclinaison grâce à un SkewTransform.
Pour cela on définit AngleX AngleY et si nécessaire CenterX et CenterY.
Exemple : texte penché.
|

Déplacement :
TranslateTransform permet de déplacer un élément ; on renseigne ici X et Y qui indiquent le déplacement en pixels.
Ici on va déplacer le texte quand on pose le doigt dessus ; il revient à sa place quand on lève le doigt.
TranslateTransform permet de déplacer un élément ; on renseigne ici X et Y qui indiquent le déplacement en pixels.
Ici on va déplacer le texte quand on pose le doigt dessus ; il revient à sa place quand on lève le doigt.
|
|
On peut aussi créer des effets visuels.
|

V-D-5. Font
Les 'fonts' correspondent aux polices de caractères.
Quand on crée une page, les polices standards (ressources Windows Phone) sont utilisées pour la page :
|
PhoneFontFamilyNormal correspond à la police Métro 'Segoe WP'.
PhoneFontSizeNormal correspond à 20 pixels.
Pour un contrôle comme un TextBlock, on peut modifier la police.
|

Quand on tape FontFamilly=" la liste des polices disponibles s'affiche.

Pour ajouter une autre police : charger une police gratuite et redistribuable (fichier .ttf), la mettre dans un répertoire /fonts du projet. L'ajouter au projet et dans les propriétés de la police mettre 'Option de génération' à 'contenu' et 'Copier dans le répertoire de sortie' à 'Copier si plus récent'.
Il semble que si on la met avec 'Option de génération' à Resources, on la voit dans la liste des polices (à vérifier).
Pour l'utiliser :
Il semble que si on la met avec 'Option de génération' à Resources, on la voit dans la liste des polices (à vérifier).
Pour l'utiliser :
|
Avant # il y a le nom du fichier '.ttf'.
Après # il y a le nom de la police (ouvrir le fichier .ttf en cliquant dessus, il peut y avoir plusieurs polices dedans, voir le nom en haut).
Après # il y a le nom de la police (ouvrir le fichier .ttf en cliquant dessus, il peut y avoir plusieurs polices dedans, voir le nom en haut).
Il faut trouver des polices redistribuables (licence GNU par exemple) et pas des polices pour usage personnel :
voir ici http://www.dafont.com/fr/top.php?l[]=10.
voir ici http://www.dafont.com/fr/top.php?l[]=10.
On peut spécifier la hauteur de la police avec FontSize (en pixels) :
|
En fait, la hauteur occupée est de 33 % supérieur à la hauteur indiquée par FontSize car il y a quelques pixels blancs au dessus et au dessous.
Comme Point=3/4 *Pixels, une FontSize de 36 correspond à 24 Points.
Comme Point=3/4 *Pixels, une FontSize de 36 correspond à 24 Points.
V-E. Couleur, remplissage de surface
V-E-1. Couleur
Dans le code XAML, les couleurs sont désignées directement :
|
En fait il y a une conversion implicite du texte "Red" en System.Windows.Media.Brushes.Red.
On aurait pu écrire :
|
ou en donnant le code couleur du rouge en hexadécimal :
|

Les couleurs sont codées sur 32 bits : composante alpha (transparence) sur 8 bits et R (rouge), B (bleu), G (vert) chacun sur 8 bits.
Quand dans le code XAML on tape Color=" une liste des couleurs s'ouvre ; il suffit de choisir une couleur. Là il y a une multitude de couleurs.
Voici les couleurs disponibles et leur valeur hexadécimale :
Voici les couleurs disponibles et leur valeur hexadécimale :

Bien sûr on peut agir sur la composante alpha pour rendre une couleur plus ou moins transparente, il y a aussi une couleur transparente :
|
En C#
On peut utiliser l'énumération Color de System.Windows.Media pour déclarer une variable qui contient une couleur.
La classe Colors permet d'avoir la valeur de 15 couleurs différentes :
On peut utiliser l'énumération Color de System.Windows.Media pour déclarer une variable qui contient une couleur.
La classe Colors permet d'avoir la valeur de 15 couleurs différentes :
|
Les couleurs sont codées sur 32 bits : composante alpha (transparence) et RBG.
On peut utiliser FromArgb pour indiquer les paramètres alpha, R, B, G.
On peut utiliser FromArgb pour indiquer les paramètres alpha, R, B, G.
|
Il y a 15 couleurs dans la classe 'Colors', aussi pour utiliser dans le code C# les autres couleurs de la palette ci dessus, il faut utiliser la valeur hexadécimale et la découper.
Pour obtenir la couleur 'Silver' de code hexadécimal #FFC0C0C0.
Pour obtenir la couleur 'Silver' de code hexadécimal #FFC0C0C0.
|
L'outil pinceau
Dans la fenêtre 'Propriétés', pour donner une couleur à la propriété (Background, par exemple) d'un contrôle on peut taper le nom de la couleur, on peut aussi ouvrir l'outil pinceau en cliquant sur la flèche à droite :

On peut choisir en haut une des icônes : null, couleur unie, dégradé, image.
Les curseurs permettent de doser la composante R, G, B et la composante alpha.
La valeur de la couleur est retournée en hexadécimal : #DF6C5F4D par exemple.
Les curseurs permettent de doser la composante R, G, B et la composante alpha.
La valeur de la couleur est retournée en hexadécimal : #DF6C5F4D par exemple.
On peut aussi utiliser les couleurs Windows Phone standards (couleurs styles ou Brush) qui sont dans les ressources. Leurs noms commencent par 'Phone' :
|
Ces ressources utilisent le thème en cours (couleur de fond et couleur d'accentuation) que l'utilisateur à sélectionné dans les paramètres (fond clair ou foncé).
Voir chapitre sur les thèmes.
Voir chapitre sur les thèmes.
Sélecteur de ressource
Dans la fenêtre 'Propriétés', pour donner une valeur ressource à la propriété (Background par exemple) d'un contrôle on peut ouvrir la fenêtre du sélecteur de ressource en cliquant sur le carré à côté du nom de la propriété :
Dans la fenêtre 'Propriétés', pour donner une valeur ressource à la propriété (Background par exemple) d'un contrôle on peut ouvrir la fenêtre du sélecteur de ressource en cliquant sur le carré à côté du nom de la propriété :

Dans le menu, choisir 'Appliquer la ressource'.

Double cliquer sur la ressource désirée.
Pour remplir une surface d'une forme (Rectangle, par exemple) avec une couleur on utilise Fill.
|
En C#
|
Pour indiquer une couleur d'avant ou d'arrière plan pour un élément coloré on utilise Foreground, Background.
|
On a vu qu'en C# il faut impérativement (même pour une couleur unie) utiliser une Brush (une brosse !).
Voyons les Brush en détails.
V-E-2. SolidColorBrush
C'est simple, c'est une couleur unie.
On peut 'remplir' peindre un objet, le fond d'un bouton (Background), un rectangle et même du texte avec un pinceau, une brosse (Brush).
En XAML c'est simple de remplir avec une Brush de couleur unie.
|
En C# c'est plus compliqué :
|
On crée une instance de SolidColorBrush ( grâce à new) avec comme paramètre la couleur désirée.
Exemple 1 : on veut choisir la couleur du Background d'un bouton.
On peut le définir en mode design dans la fenêtre de propriétés.
En XAML :
|
ou en hexadécimal :
|
ou en C# :
|
On ne peut pas affecter directement la couleur : (myButton.Background = Colors.Red ne fonctionne pas) on est obligé d'instancier une nouvelle SolidColorBrush et de lui donner la valeur Red qui appartient à la collection Colors.
Exemple 2 : créer un rectangle rouge.
|
Remarquer qu'on a utilisé la méthode Fill pour remplir le rectangle avec la Brush.
En XAML :
|

V-E-3. LinearGradientBrush
Peinture avec dégradé linéaire.
C'est une couleur qui se transforme progressivement en une autre puis éventuellement en une autre encore.
C'est une couleur qui se transforme progressivement en une autre puis éventuellement en une autre encore.
Il y a un system de coordonnées sur la surface à remplir : (0,0) est au coin supérieur gauche, (1,1) au coin inférieur droit.
'0.5, 0.5 ' correspond au centre.
StartPoint indique les coordonnées du début du gradient, EndPoint les coordonnées de la fin du gradient, GradientStop indique la position relative de la couleur sur la ligne qui rejoint le point de début au point de la fin.
Exemple 1 : sur une Grid, on positionne trois couleurs dans la diagonale.
On ne peut pas le faire dans la fenêtre designer avec la souris, le plus simple est de coller le code XAML dans la fenêtre XAML ou de l'écrire en C#.
Pour suivre la diagonale StartPoint="0,0" EndPoint="1,1".
le rouge sera à 0 % de la diagonale, le blanc à 50 % le bleu à 100 %.
En XAML :
|

En C# :
|

La syntaxe suivante pour le GradientStop, bien que correcte n'est pas acceptée :
|
Exemple 2 : plein de couleurs dans un rectangle.
|

Exemple 3 : sur un bouton avec un dégradé de gris.
Pour que le gradient s'applique de haut en bas StartPoint="0,0" EndPoint="0,1" le blanc sera à 0 % de la verticale, le gris à 100 % de la verticale.
En XAML :
|

Remarque : on aurait pu mettre un GradientStop en dehors de la zone (à 2 par exemple pour le LightGray) ce qui permet d'estomper la couleur grise et de faire un bouton plus clair.
Exemple 4 : texte d'un bouton avec dégradé.
|

Ici on a utilisé un LinearGradientBrush pour le Foreground.
V-E-4. RadialGradientBrush
Peinture avec dégradé radial.
Ici on applique deux couleurs ou plus dans un cercle qui occupe la totalité du conteneur.
Ici on applique deux couleurs ou plus dans un cercle qui occupe la totalité du conteneur.
Visualisons ce cercle et le system de coordonnées :
Le GradientOrigin donne le centre du gradient. Ci-dessous le centre du gradient est à 0.50, 0.50 (c'est sa valeur par défaut) c'est à dire au centre du cercle. Les couleurs seront donc concentriques.
Les GradientStop indiquent la position des couleurs par rapport au centre : le blanc est à l'offset 0 : disque de blanc au centre ; le bleu est à l'offset 0.5, cela donne un cercle de bleu autour du blanc ; le vert est à l'offset 1 (100 %): le cercle vert est autour du cercle bleu.
En XAML
|
Pour l'exemple suivant le centre du gradient est à 0.50, 1 excentré en bas du cercle.
On a ajouté artificiellement, pour mieux comprendre, le cercle gris qui occupe la totalité du conteneur et le centre du gradient symbolisé par un point noir.
L'offset du blanc est 0.75 : le blanc monte haut.
En XAML
|
Ici l'offset du blanc est 0.50 : le blanc monte moins haut.
En XAML :
|
Exemple sur une Grid. Centre du gradient excentré en haut à droite (0.75, 0.25) et il y a trois couleurs.
En XAML :
|
On peut avoir une ellipse au lieu d'un cercle en définissant RadiusX et RadiusY.
|
Un exemple complet en C# :
|

Autre exemple, une Sphère : on remplit une ellipse avec un RadialGradientBrush :
|

Dernier exemple : utiliser une RadialGradientBrush comme Foreground d'un texte.
|

V-E-5. ImageBrush
On peut mettre une image dans un rectangle, par exemple.
En XAML :
|
Si je donne à la propriété Foreground le nom d'une ImageBrush, le texte va être dessiné avec cette image :
|

Il n'y a pas de VirtualBrush en WP7.
V-E-6. Masque d'opacité
Dans les UIElements, une image par exemple, on peut mettre un masque d'opacité (propriété OpacityMask), il permet de modifier la transparence d'une image en fonction d'un masque qui peut être un dégradé ou une image.
Seule la composante alpha du masque est prise en compte. L'image hérite de la transparence du masque.
Seule la composante alpha du masque est prise en compte. L'image hérite de la transparence du masque.
Ici sur l'image de cet oiseau on applique un masque qui est une RadialGradientBrush de plus en plus transparente vers l'exterieur.
|

Effet miroir :
Ici on affiche 2 fois la même image. On inverse la seconde par rapport à l'axe des Y grâce à RenderTransform et on lui applique un masque qui est un LinearGradientBrush.
Ici on affiche 2 fois la même image. On inverse la seconde par rapport à l'axe des Y grâce à RenderTransform et on lui applique un masque qui est un LinearGradientBrush.
|

V-E-7. Nombre de couleurs et dégradés
Les téléphones Windows Phone 7 ont des écrans 32 bpp (bits par pixel) ou des écrans 16 bpp (bits par pixel), l'émulateur est en 16 bpp pour aider les développeurs à concevoir des applications qui fonctionnent quel que soit le matériel.
Aussi dans l'émulateur les dégradés ne sont pas beaux et présentent des bandes colorées
(pour être sûr d'avoir un beau dégradé, certains proposent d'afficher l'image d'un dégradé qu'on aura flouté dans PaintNet ou PhotoShop).
Aussi dans l'émulateur les dégradés ne sont pas beaux et présentent des bandes colorées
(pour être sûr d'avoir un beau dégradé, certains proposent d'afficher l'image d'un dégradé qu'on aura flouté dans PaintNet ou PhotoShop).
V-F. Ressources
Les ressources sont un ensemble d'éléments :
- Couleurs, Brush, Style, ControlTemplate (aspect du contrôle), DataTemplate (affichage des données) ressources dites 'internes' ;
- Images, icônes, textes, sons (ressources contenues dans des fichiers externes).
- Couleurs, Brush, Style, ControlTemplate (aspect du contrôle), DataTemplate (affichage des données) ressources dites 'internes' ;
- Images, icônes, textes, sons (ressources contenues dans des fichiers externes).
Nous allons donc voir
1- Les ressources internes.
2- Les fichiers de ressources externes.
3- Les ressources fournies par WP.
V-F-1. Les dictionnaires de ressources
On a vu antérieurement comment modifier certaines propriétés d'UN contrôle. Mais il est possible de créer des modèles pour ensuite les appliquer à un ou plusieurs contrôles.
Ici on va voir comment créer des styles, des modèles de contrôles, des modèles de données pour les appliquer à un, plusieurs ou tous les contrôles ou données .
Ici on va voir comment créer des styles, des modèles de contrôles, des modèles de données pour les appliquer à un, plusieurs ou tous les contrôles ou données .
V-F-1-a. Ressources 'simples'
Plutôt que d'indiquer X fois quelle couleur ou Brush utiliser dans plusieurs contrôles d'une fenêtre, il est plus simple de définir une ressource contenant la couleur ou la Brush puis X fois, indiquer pour chaque contrôle quelle ressource utiliser.
Les ressources sont dans un dictionnaire de ressources. Dans les ressources de l'application, d'une page ou d'un objet, entre les balises de début et de fin de ressources.
|
Remarquez : Resources avec un 's' et non Ressources.
Ici dans ces ressources simples, la ressource est une Brush, une couleur un texte…
Chaque ressource doit avoir une clé unique. Il faut affecter la clé unique via l'attribut x:Key.
En principe, la clé est une chaîne de caractères.
|
Ici la clé unique de la SolidColorBrush est "MyBrush", c'est son 'nom', son nom d'index.
Elle est dans les ressources de la grille.
Elle est dans les ressources de la grille.
Ensuite dans le code XAML de l'UI on utilise cette ressource grâce à {StaticResource MyBrush}.
Seul le contrôle utilisant la ressource la prendra en compte !
Ici dans la grille où se trouve la ressource, on a un bouton et une ellipse. On peut donc utiliser la ressource dans le bouton et l'ellipse.
Seul le contrôle utilisant la ressource la prendra en compte !
Ici dans la grille où se trouve la ressource, on a un bouton et une ellipse. On peut donc utiliser la ressource dans le bouton et l'ellipse.
|
En C# :
|
Exemple complet
Dans une Grid, on crée une ressource de type LinearGradientBrush nommée BrushBizarre, ensuite on applique cette Brush au fond d'un bouton.
|
Où mettre les ressources ?
-Dans un objet. Dans une Grid comme dans l'exemple précédent, syntaxe : Grid.Resources ; dans ce cas la Grid mais aussi tous les objets contenus dans la Grid peuvent utiliser la ressource.
|
En C# comment utiliser la ressource ?
|
-Dans une Page, ici on crée une ressource string dans la page.
|
On remarque que pour utiliser une string comme ressource, il faut au préalable importer l'espace de noms system.
Comment l'utiliser dans la page ?
|
En C# :
|
-Dans le fichier Application.
C'est le fichier App.xaml.
|
Dans ce cas la ressource est utilisable dans toute l'application.
On peut l'utiliser dans un TextBlock :
|
Comment récupérer la brush en C# ?
|
- Dans un fichier de ressources indépendant.
Menu 'Projet', puis 'Ajouter un nouvel élément' puis 'Fichier texte'. Nommer le 'Dictionnary1' puis Ok.
Y mettre une SolidColorBrush.
|
Pour que cela fonctionne, il faut ajouter dans le fichier App.xaml la référence au dictionnaire.
|
L'emplacement où est déclaré la ressource affecte l'emplacement où la ressource peut être utilisée.
![]() | Si vous déclarez la ressource dans votre fichier App.xaml avec la balise 'Application.Resources', elle pourra être utilisée n'importe où dans votre application. |
Si vous déclarez la ressource dans une Grid grâce à 'Grid.Resources', elle pourra être utilisée uniquement dans la Grid et dans les objets enfants qui sont dans cette grille.
Il n'existe pas de ressources 'Dynamiques' en WP.
V-F-1-b. Les styles
Le style est une ressource qui est applicable à un objet ou un 'Type' d'objet. On peut créer un style pour les Buttons, les List…
Il correspond à l'identification de plusieurs propriétés par un nom, que l'on peut appliquer ensuite facilement à plusieurs contrôles.
Il peut être placé dans les ressources d'un objet, d'une page ou d'une application.
Il correspond à l'identification de plusieurs propriétés par un nom, que l'on peut appliquer ensuite facilement à plusieurs contrôles.
Il peut être placé dans les ressources d'un objet, d'une page ou d'une application.
Ici on va créer un style pour les TextBlock.
TargetType="TextBlock" indique quel type cela concerne.
x:Key= , indique le nom du style.
Setter va servir à définir une Property à laquelle on va donner une Value.
Dans ce style, grâce à 'Setter Property=' on affecte des valeurs aux propriétés des TextBlock.
|
Ensuite, dans un TextBlock on peut utiliser le style.
Il faut utiliser l'attribut Style= dans le TextBlock sur lequel on veut appliquer le style.
|
Depuis WP 7.1 (Mango), si on omet x:Name dans un style, cela permet d'appliquer le style automatiquement à tous les objets correspondant au TargetType.
Si on enlève x:Name :
|
Le style sera appliqué dans le textblock qui suit et tous les textblocks.
|
On vient d'utiliser un Setter pour modifier une propriété, mais il est possible dans un style de mettre un DataTemplate (modèle de donnée), un ControlTemplate (modèle de contrôle).
Voyons un exemple avec un ControlTemplate (lire le chapitre suivant avant).
Ici on crée un style contenant un ControlTemplate donnant des boutons ronds et rouges.
Voyons un exemple avec un ControlTemplate (lire le chapitre suivant avant).
Ici on crée un style contenant un ControlTemplate donnant des boutons ronds et rouges.
|
Pour simplifier, le template n'est pas complet ; en particulier, le bouton ne change pas d'aspect quand on clique.
Et pour l'utiliser sur un bouton :
|

En C# pour appliquer le style à un contrôle :
|
On peut dans un style récupérer un style existant et l'étendre. On utilise BaseOn pour récupérer un style.
|
V-F-1-c. Les modèles de contrôle : ControlTemplate
On a vu plus haut qu'on pouvait mettre un template (modèle, gabarit) dans un contrôle :
|
Mais on peut aussi créer des Modèles de contrôle (ControlTemplate) dans les ressources permettant de modifier tous les contrôles d'un même type.
On spécifie la structure visuelle et les aspects comportementaux d'un type de contrôle. Là, on ne modifie pas une simple propriété du contrôle, mais son aspect profond.
Si on écrit un ControlTemplate, on va définir son aspect visuel (fond, forme…), il faut aussi obligatoirement redéfinir l'aspect de son contenu (ControlPresenter) et si nécessaire les modifications liées aux évènements (VisualStateManager).
Comment avoir des boutons en forme d'ellipse ?

Dans les ressources de l'application (dans App.xaml), on va créer un style pour les boutons, on va sur le template et son ControlTemplate.
- Pour la forme du bouton, on va mettre dans une grille une ellipse (la remplir avec une Brush).
- Pour le texte on ajoute un ContentPresenter.
- Pour modifier la couleur quand le bouton est 'Pressed', on utilise un VisualStateManager contenant un Storyboard qui modifie la Brush de l'ellipse. Le bouton devient blanc quand on clique dessus.
- Pour la forme du bouton, on va mettre dans une grille une ellipse (la remplir avec une Brush).
- Pour le texte on ajoute un ContentPresenter.
- Pour modifier la couleur quand le bouton est 'Pressed', on utilise un VisualStateManager contenant un Storyboard qui modifie la Brush de l'ellipse. Le bouton devient blanc quand on clique dessus.
|
Pour un contrôle liste on aurait utilisé un ItemsPresenter.
Pour appliquer le style a un bouton :
|

V-F-1-d. Les modèles de données : Data Template
Enfin pour être complet il est possible de modifier l'aspect des données affichées dans un contrôle grâce au Data Template (modèle de données) ; voir le chapitre sur les liaisons de données pour le détail.
Utilisation de Template dans une ListBox.
Grâce à l'ItemTemplate on peut afficher les items d'une ListBox comme on veut.
Ici on veut afficher dans une ListBox une collection.
Pour chaque Item on affiche une petite sphère, la propriété 'Nom' en gros et la propriété 'TextBref' dessous en plus petit.
Ici on veut afficher dans une ListBox une collection.
Pour chaque Item on affiche une petite sphère, la propriété 'Nom' en gros et la propriété 'TextBref' dessous en plus petit.
On suppose que la collection a déjà été créée (voir exemple en fin de chapitre sur les collections) et qu'on effectue une liaison (Binding) de la collection sur la ListBox, ce qui remplit automatiquement la ListBox avec la collection.
Dans l'ItemTemplate on met un StackPanel dans lequel on met une ellipse puis deux TextBlock qui sont en liaison avec les propriétés 'Titre' et 'TextBref'.
|

Comment afficher une liste d'images ?
Mesphotos étant une liste de noms d'images, la propriété 'NomImage' contient le nom de la photo ; on montre ici le principe simplement.
Mesphotos étant une liste de noms d'images, la propriété 'NomImage' contient le nom de la photo ; on montre ici le principe simplement.
|
Ici on affiche la liste des noms d'images.
Comment afficher les images elle mêmes ? en créant un DataTemplate.
Il affiche pour chaque élément une ligne contenant le nom de l'image puis l'image elle-même.
Comment afficher les images elle mêmes ? en créant un DataTemplate.
Il affiche pour chaque élément une ligne contenant le nom de l'image puis l'image elle-même.
|
Ici le Data Template est dans le contrôle, on aurait pu créer un DataTemplate dans les ressources.
V-F-2. Les fichiers de ressources
On peut ajouter dans le projet des fichiers image, son, icône…
Exemple de fichier Image.
Exemple de fichier Image.
J'ai une image nommée 'xvide.jpg', je veux la mettre dans les ressources pour la charger dans un contrôle image.
Mettre le fichier image dans le répertoire des sources (dans C:\Documents and Settings\phil\Mes documents\Visual Studio 2010\Projects\MyApplication\MyApplication).
Mettons à jour les fichiers de l'explorateur de solution en cliquant sur le bouton en haut (voir ci-dessous).
Le fichier apparaît dans l'explorateur de solution mais en grisé.
Le fichier apparaît dans l'explorateur de solution mais en grisé.

Clic droit sur le fichier puis sur 'Inclure dans le projet'.
Le fichier devient une 'resource' (voir en bas dans les propriétés, 'Action de génération=Resource').
Le fichier devient une 'resource' (voir en bas dans les propriétés, 'Action de génération=Resource').
On peut aussi passer par : Menu Projet=>Ajouter un élément existant.
Si on a créé un répertoire nommé image, pointer C:\Documents and Settings\phil\Mes documents\Visual Studio 2010\Projects\MyApplication\MyApplication\image\xvide.jpg, puis cliquer sur 'Ajouter'.
Le fichier apparaît dans l'explorateur de solution (en haut à droite).
Là aussi dans la fenêtre des propriétés du fichier 'Action de génération' prend la valeur 'Resource' par défaut.
Mettre la ressource dans l'image.
|
Notez bien : pas de chemin.
L'image xvide.jpg apparaît dans le contrôle image.
Dans le code C# :
|
Lors de la génération du projet, l'image sera dans l'exécutable.
On peut passer par les ressources de l'application.
-Charger xvide.jpg dans le projet comme ci-dessus.
-Créer une ressource nommée "someImage" dans Application.xaml
|
-Mettre la ressource dans une image
|
Bien sûr, on peut utiliser des icônes.
On peut aussi donner l'adresse Internet d'une image.
On peut aussi donner l'adresse Internet d'une image.
Revenons sur les valeurs d' 'Option de génération' dans les propriétés d'un fichier :

Si on déroule la liste, on a les valeurs :
- Aucun : Le fichier n'est pas inclus dans le groupe de sorties de projet et n'est pas compilé au cours du processus de génération. Fichier texte contenant de la documentation par exemple ;
- Compiler : Le fichier est compilé dans la sortie de projet. Cette valeur est utilisée par défaut pour les fichiers de code (.cs) ;
- Page : Le fichier est compilé dans la sortie de projet. Cette valeur est utilisée par défaut pour les fichiers .xaml ;
- ApplicationDefinition : Cette valeur est utilisée par défaut pour App.xaml ;
- Contenu : Le fichier n'est pas compilé, mais il est inclus dans le groupe de sorties Contenu. Valeur par défaut d'un fichier .htm ou d'autres types de fichier Web, par exemple ;
- Resources : Cette action de génération va incorporer le fichier dans l'assembly du projet (correspond aux ressources incorporées).
- Ressource incorporée : semble ne pas pouvoir être utilisé en silverlight.
- Aucun : Le fichier n'est pas inclus dans le groupe de sorties de projet et n'est pas compilé au cours du processus de génération. Fichier texte contenant de la documentation par exemple ;
- Compiler : Le fichier est compilé dans la sortie de projet. Cette valeur est utilisée par défaut pour les fichiers de code (.cs) ;
- Page : Le fichier est compilé dans la sortie de projet. Cette valeur est utilisée par défaut pour les fichiers .xaml ;
- ApplicationDefinition : Cette valeur est utilisée par défaut pour App.xaml ;
- Contenu : Le fichier n'est pas compilé, mais il est inclus dans le groupe de sorties Contenu. Valeur par défaut d'un fichier .htm ou d'autres types de fichier Web, par exemple ;
- Resources : Cette action de génération va incorporer le fichier dans l'assembly du projet (correspond aux ressources incorporées).
- Ressource incorporée : semble ne pas pouvoir être utilisé en silverlight.
Notez que dans l'explorateur de solutions , si on ajoute une image (menu 'Projet', 'Ajouter un elément existant' ), l'option 'Action de génération' prend la valeur 'Resource'.
On peut, quand on met une image dans le projet, en faire un 'Contenu' ou une 'Resource'.
Avec 'Contenu', le fichier image est dans le fichier d'installation XAP mais pas dans la DLL. Cela serait plus performant.
Noter la syntaxe de la valeur de 'Source':
Avec 'Contenu', le fichier image est dans le fichier d'installation XAP mais pas dans la DLL. Cela serait plus performant.
Noter la syntaxe de la valeur de 'Source':
|
Avec 'Resource', le fichier image est incorporé dans le fichier DLL qui est dans le XAP.
Noter la syntaxe de la valeur de 'Source':
Noter la syntaxe de la valeur de 'Source':
|
V-F-3. Ressources Windows Phone
WP fournit un dictionnaire de ressources dont on peut utiliser les valeurs dans une application. Ce sont des valeurs 'standards' proposées par Microsoft.
Elles sont en rapport avec le thème en cours (couleur de fond : claire ou foncée, couleur d'accentuation).
Le nom de ces ressources commence par 'Phone'.
Il y a des PhoneBrush dans ces ressources.
Par exemple pour un fond de page on va utiliser le fond de page standard : PhoneForegroundBrush.
Elles sont en rapport avec le thème en cours (couleur de fond : claire ou foncée, couleur d'accentuation).
Le nom de ces ressources commence par 'Phone'.
Il y a des PhoneBrush dans ces ressources.
Par exemple pour un fond de page on va utiliser le fond de page standard : PhoneForegroundBrush.
|
Il y a aussi des PhoneColor , PhoneFonts, les tailles pour les caractères (PhoneFontSizeMedium = 17),
mais aussi les épaisseurs pour les propriétés Thickness, Padding…
enfin les styles de texte et la visibilité ou l'opacité du thème.
Voici un exemple de l'utilisation d'un style dans un TextBox :
|
Voici où trouver toutes les ressources et leur valeur :
D'ailleurs, automatiquement, quand on crée une page, la police 'normale' est utilisée pour la page, ainsi que la couleur du fond :
|
Pour afficher le nom de l'application et le titre on utilise PhoneTextNormalStyle et PhoneTextTitle1Style :
|
C'est la ressource 'PhoneFontFamilyNormal' (correspondant à la police Métro 'Segoe WP') qui est donc utilisée pour le texte de la page.
Comment utiliser les couleurs du thème actuel ?
Dans les paramètres du Windows Phone on peut choisir :
L'arrière plan (clair ou sombre) ;
La couleur d'accentuation (11 couleurs proposées).
L'arrière plan (clair ou sombre) ;
La couleur d'accentuation (11 couleurs proposées).

Ces couleurs se retrouvent dans les ressources Windows Phones :
la couleur de fond est PhoneBackgrountColor ;
la couleur d'accentuation est PhoneAccentColor.
Il y a les Brush correspondantes :
Dans le code XAML, quand on utilise des ressources comme couleur, ce sont les 'Brush' qu'il faut utiliser et pas les couleurs.
PhoneAccentBrush : Brush d'accentuation définie par le thème.
PhoneForegroundBrush : Brush utilisée pour les éléments de premier plan tels que le texte ou les icônes.
PhoneBackgroundBrush : Brush utilisée pour les éléments d'arrière-plan.
PhoneContrastBackgroundBrush : Brush de fond utilisée pour mettre en contraste (fond des menus contextuels par exemple).
PhoneContrastForegroundBrush : Brush de premier plan utilisée pour les éléments à mettre en contraste. Par exemple les textes des menus contextuels.
PhoneDisabledBrush : Brush des éléments désactivés.
PhoneSubtleBrush : Brush partiellement transparente qui permet de mettre en retrait des éléments visuels moins importants.
PhoneBorderBrush : Brush de bordure des contrôles TextBox, CheckBox, PasswordBox, et RadioButton.
PhoneSemitransparentBrush : Brush presque transparente permettant de faire ressortir des éléments de couleurs similaires (par exemple du texte blanc sur une image claire).
On peut aussi utiliser les styles :
PhoneTextNormalStyle qui contraste avec la couleur du fond pour le rendre lisible, PhoneTextTitle1Style.
Voir le chapitre sur les thèmes.
la couleur d'accentuation est PhoneAccentColor.
Il y a les Brush correspondantes :
Dans le code XAML, quand on utilise des ressources comme couleur, ce sont les 'Brush' qu'il faut utiliser et pas les couleurs.
PhoneAccentBrush : Brush d'accentuation définie par le thème.
PhoneForegroundBrush : Brush utilisée pour les éléments de premier plan tels que le texte ou les icônes.
PhoneBackgroundBrush : Brush utilisée pour les éléments d'arrière-plan.
PhoneContrastBackgroundBrush : Brush de fond utilisée pour mettre en contraste (fond des menus contextuels par exemple).
PhoneContrastForegroundBrush : Brush de premier plan utilisée pour les éléments à mettre en contraste. Par exemple les textes des menus contextuels.
PhoneDisabledBrush : Brush des éléments désactivés.
PhoneSubtleBrush : Brush partiellement transparente qui permet de mettre en retrait des éléments visuels moins importants.
PhoneBorderBrush : Brush de bordure des contrôles TextBox, CheckBox, PasswordBox, et RadioButton.
PhoneSemitransparentBrush : Brush presque transparente permettant de faire ressortir des éléments de couleurs similaires (par exemple du texte blanc sur une image claire).
On peut aussi utiliser les styles :
PhoneTextNormalStyle qui contraste avec la couleur du fond pour le rendre lisible, PhoneTextTitle1Style.
Voir le chapitre sur les thèmes.
Sélecteur de ressource :
dans la fenêtre 'Propriétés', pour donner la valeur d'une ressource à la propriété (BackGround par exemple) d'un contrôle on peut ouvrir le sélecteur de ressource en cliquant sur le carré à coté du nom de la propriété.

Dans le menu, choisir 'Appliquer la ressource'.

Double cliquer sur la ressource désirée.
Typographie :
il est conseillé d'utiliser la typographie recommandée.

V-G. Les liaisons de données ou Binding
V-G-1. Principes du Binding
Binding veut dire liaison.
"Les liaisons de données sont des processus qui établissent une connexion entre l'interface utilisateur de l'application et la logique métier." En d'autres termes, elles permettent d'établir une connexion entre un contrôle et une sources de données. Cela permet, par exemple, d'afficher automatiquement le contenu d'une base de données, d'une collection… dans une ListBox…
Il faut donc un objet visuel, la cible (ListBox, TextBox…) ayant une propriété de dépendance et faire une liaison avec la source de liaison qui est la propriété d'un objet (collection, tableau, base de données…).
La liaison peut être unidirectionnelle (OnWay= en lecture seule de la source) ou bidirectionnelle (TwoWay), ce qui permet dans ce dernier cas de mettre à jour la source quand on fait une modification dans l'UI.
La liaison peut être unidirectionnelle (OnWay= en lecture seule de la source) ou bidirectionnelle (TwoWay), ce qui permet dans ce dernier cas de mettre à jour la source quand on fait une modification dans l'UI.

Binding entre objets :
Pour qu'une propriété d'un objet (dit 'cible') soit liée à une source, il faut lui affecter un objet Binding (Text="{Binding…) puis indiquer l'objet source avec ElementName et la propriété source avec Path :
|
Ici la propriété Text du TextBox est liée à la propriété Text d'un autre contrôle. Si on tape un texte dans le contrôle txtsource, il apparaitra dans la propriété Text de notre TextBox.
DataContext
La propriété DataSource des contrôles WindowsForms n'existe plus ; les contrôles silverlight ont un DataContext. Il peut être renseigné en XAML ou dans le code #. Le DataContext indique donc la source mais ce qui est fondamental c'est que les contrôles enfants vont hériter du DataContext :
Si un DockPanel a un DataContext, les Buttons qui sont dedans hériterons de ce DataContext, il suffira pour chaque contrôle enfant d'indiquer une partie de la source (une propriété, un champ…).
Autrement dit, si vous avez une source possédant plusieurs propriétés, la source est spécifiée en utilisant DataContext du contrôle (pratique pour un groupe d'éléments donc). Chaque propriété à afficher sera indiquée dans les éléments enfants.
Si on a dans le code C# de la page une collection d'objets ayant les propriétés Nom, Prenom, Rue, Ville, on renseigne le DataContext dans le code C# puis on peut utiliser le binding comme cela :
Si un DockPanel a un DataContext, les Buttons qui sont dedans hériterons de ce DataContext, il suffira pour chaque contrôle enfant d'indiquer une partie de la source (une propriété, un champ…).
Autrement dit, si vous avez une source possédant plusieurs propriétés, la source est spécifiée en utilisant DataContext du contrôle (pratique pour un groupe d'éléments donc). Chaque propriété à afficher sera indiquée dans les éléments enfants.
Si on a dans le code C# de la page une collection d'objets ayant les propriétés Nom, Prenom, Rue, Ville, on renseigne le DataContext dans le code C# puis on peut utiliser le binding comme cela :
|
Ici on crée une liaison du StackPanel avec une collection.
Les TextBox héritent du DataContext du StackPanel. Cela permet ensuite de lier la propriété Text de chaque TextBox à différentes propriétés des objets de la collection.
Vous pouvez indiquer le DataContext dans le code C# :
|
Dans ce cas en XAML, il faut simplement indiquer qu'il y a un Binding avec l'expression "{Binding}" :
|
Il est possible d'indiquer comme DataContext la classe elle-même.
|
![]() | On insiste sur le fait que si vous souhaitez créer une liaison avec un objet source (comme une collection, par exemple) qui a déjà été instancié dans le code C#, vous devez définir la propriété DataContext dans le code C# (et pas en XAML). |
Si on n'utilise pas le DataContext, on peut aussi utiliser la propriété Source du Binding :
|
Si on utilise un contrôle de type ItemsControl tel qu'un ListBox, ListView ou un TreeView pour afficher une collection de données, il faut utiliser ItemsSource pour indiquer la source :
|
Mode indique le mode de mise a jour (OneWay, TwoWay, OneTime).
|
UpdateSourceTrigger détermine le moment des mises à jour de la liaison.
La valeur est par défaut 'Default' et le binding se fera dans ce cas lors de la sortie du contrôle source.
L'autre valeur est 'Explicit'.
La valeur est par défaut 'Default' et le binding se fera dans ce cas lors de la sortie du contrôle source.
L'autre valeur est 'Explicit'.
V-G-2. Liaison entre contrôles
Pour qu'une propriété d'un objet (dit 'cible') soit liée à une source, il faut lui affecter un objet Binding ( Text="{Binding…) puis indiquer l'objet source avec ElementName et la propriété source avec Path.
A - Créons deux TextBox ; on va créer une liaison entre les deux propriétés Text, quand on tape un texte dans la première, il apparaît dans la seconde :
|
Dans la cible, la propriété Text= 'Binding' entre accolades permet d'indiquer qu'il y a une liaison, 'ElementName' indique la source de la liaison (la source est désignée par son nom dans le XAML). Path la propriété de la source. Il y a une ',' entre chaque élément à partir du second.
La syntaxe suivante est aussi acceptée.
|
On remarque que la mise à jour est effectuée (dans le cas d'un TextBox) quand on quitte le TextBox source. Il y a bien une propriété UpdateSourceTrigger qui détermine le moment de la mise à jour, elle peut avoir une des deux valeurs 'Default' et 'Explicit' (pas de valeur PropertyChanged).
Par défaut le Mode est égal à OneWay (la liaison se fait uniquement dans le sens source=>cible).
On peut donner la valeur TwoWay au mode, ce qui permet de faire en plus la liaison cible=>source : quand on tape dans la cible, la source est modifiée (cela est visible dans notre exemple ci-dessous quand on quitte la cible) :
|
Pour être complet il existe aussi les modes OneTime (mise à jour une seule fois au départ).
B - Créons deux ListBox ; quand on ajoute des éléments dans la première, ils apparaissent dans la seconde :
|
C - Créons maintenant un Slider (curseur) et un rectangle ; quand on bouge le curseur du Slider cela modifie la hauteur du rectangle, il faut donc comme source la propriété Value du Slider et comme cible la propriété Height du rectangle :
|

D - Créons une ListBox, on ajoute des éléments à cette ListBox avec du code C# ; quand on clique sur un item il s'affiche dans le TextBlock en bas :
|

À noter que si on met des items dans la ListBox en utilisant le code XAML ci dessous, cela ne marche pas ; le binding affiche le type (il faut ajouter des éléments à la ListBox avec du code C#).
|
E -Créons un TextBox et un TextBlock avec liaison ; comment mettre à jour quand on veut ?
UpdateSourceTrigger détermine le moment des mises à jour de la liaison.
La valeur est par défaut 'Default' et le binding se fera dans ce cas lors de la sortie du contrôle source.
L'autre valeur est 'Explicit'.
Ici la mise à jour se fait quand on la provoque explicitement.
Exemple : on a un TextBox dans lequel on va taper du texte ; on a un TextBlock dans lequel le texte va s'afficher par binding. On va indiquer une mise à jour explicite.
La valeur est par défaut 'Default' et le binding se fera dans ce cas lors de la sortie du contrôle source.
L'autre valeur est 'Explicit'.
Ici la mise à jour se fait quand on la provoque explicitement.
Exemple : on a un TextBox dans lequel on va taper du texte ; on a un TextBlock dans lequel le texte va s'afficher par binding. On va indiquer une mise à jour explicite.
|
Pour que la mise à jour intervienne lors du changement du texte dans la TextBox, il faut créer un EventHandler sur l'évènement TextChanged et dans la routine exécutée par ce dernier évènement effectuer la mise à jour du binding (propriété Update d'un BindingExpression).
|

Maintenant quand on tape du texte dans le TextBox, il s'affiche dans le TextBlock immédiatement.
En résumé : dans le Binding, ElementName indique le contrôle source. La propriété Path spécifie la propriété de l'objet.
Path peut aussi avoir une valeur comme Text.Height ou Text[1] (deuxième caractère).
V-G-3. Liaison Collection-ListBox
Pour une ListBox, c'est ItemsSource qui indique la source.
Voici le code XAML de la ListBox : ItemsSource ="{Binding}" indique que la source est une liaison mais n'indique pas la source.
|
On crée une collection nommée 'noms' de type List(Of), on la remplit avec des noms ; comment faire une liaison List() ListBox et afficher automatiquement les noms dans la ListBox ?
Voici le code C# :
|
ListBox1.DataContext = noms indique quelle est la source de la liaison.
La liaison est ici par défaut : OneWay.
La liaison est ici par défaut : OneWay.
Cela marche aussi avec un tableau.
Le problème est que si ensuite j'ajoute un nom à la liste (noms.Add("Toto");), 'Toto' n'apparaît pas dans la ListBox.
Il n'y a pas de 'mise à jour'. On verra comment résoudre cela.
Il n'y a pas de 'mise à jour'. On verra comment résoudre cela.
![]() | Si vous souhaitez créer une liaison avec un objet source (comme une collection, par exemple) qui a déjà été instancié dans le code C#, vous devez définir la propriété DataContext dans le code C#. |
Si l'utilisateur clique sur un élément de la liste, il est possible de l'utiliser dans un autre contrôle :
|
Ici dans le TextBlock, le nom qui a été sélectionné dans la ListBox sera affiché car on utilise comme Path le SelectedItem.
V-G-4. Liaison collection d'objets, ListBox
On veut une collection contenant des objets nommés 'ElementDeListe' ayant les propriétés 'Titre', 'Formule', 'Mode' et les afficher par liaison dans une liste.
On va créer une classe 'ElementDeListe' qui a trois propriétés: 'Titre', 'Formule' et 'Mode'.
On va aussi créer une collection nommée 'ListMath' qui hérite de la Classe List(Of). On y mettra des ElementDeListe.
On va aussi créer une collection nommée 'ListMath' qui hérite de la Classe List(Of). On y mettra des ElementDeListe.
Dans Class1.cs on crée une classe nommée 'ElementDeListe'.
|
Dans MainPage.xaml.cs on déclare une collection nommée 'ListMath' de type List, on y met quelques éléments.
|
En fin de code on lie la collection à la ListBox grâce à sa propriété DataContext.
Dans MainPage.xaml on crée une ListBox nommée 'listBox1', on indique que la source des items est une liaison.
|
Cela donne :

La ListBox affiche les types !
Pour afficher Titre et Formule, on va ajouter un ItemTemplate contenant un StackPanel horizontal qui contient trois TextBlocks. Le premier et le troisième sont liés aux propriétés Titre et Formule.
|

Le problème, là aussi, est que si ensuite j'ajoute un objet à la liste ( ListeMath.Add(new ElementDeListe("Ares-m2", "Ares", "C"));) ou si je modifie une propriété d'un objet de la liste, cela ne modifie pas la ListBox.
Il n'y a pas de 'mise à jour'.
Il n'y a pas de 'mise à jour'.
On peut forcer la mise à jour de deux manières :
1 -En utilisant une ObservableCollection(Of)
Il faut utiliser une ObservableCollection générique qui possède l' interface 'INotifyCollectionChanged' qui entraîne, en cas d'ajout ou de suppression d'élément de la collection, une mise à jour de la ListBox.
Remarquons que pour utiliser une ObservableCollection il faut ajouter : 'System.Collections.ObjectModel'
|
Ensuite on utilise l'ObservableCollection :
|
Maintenant cela marche : si on ajoute un élément à ListeMath, il apparaît immédiatement dans la ListBox.
C'est que l'observable collection a en natif une interface : INotifyCollectionChanged.
2 -En ajoutant des interfaces à la classe
En effet, avec une List rien n'indique à la liaison collection-listbox que la collection a changé et qu'il faut mettre à jour.
Ajout de INotifyPropertyChanged (après le nom de la classe et les ':').
Permet, lorsqu'on modifie une propriété d'un objet présent dans la List (on change un titre, par exemple), que la modification soit dans la ListBox.
|
Ajout de INotifyCollectionChanged.
Permet, si on modifie la collection (ajout d'un élément par exemple) de voir apparaitre cet élément dans la ListBox.
(Code contenant uniquement la partie INotifyCollectionchanged ; code non testé.)
(Code contenant uniquement la partie INotifyCollectionchanged ; code non testé.)
|
![]() |
On voit qu'il est bien plus simple d'utiliser une ObservableCollection pour que l'ajout ou la suppression d'élément soit pris en compte. Par contre pour la modification d'élément déjà dans la liste , il faut implémenter INotifyPropertyChanged. |
V-G-5. Convertisseur
On peut aussi utiliser un converter (en anglais "converter", en français "convertisseur") qui, entre la source et la cible va effectuer une conversion.

Ici l'exemple montre un binding avec comme cible un TextBlock, le converter enlève simplement les blancs avant et après.
|
Le converter est écrit en C#, il doit implémenter impérativement Convert et ConvertBack.
|
V-G-6. Binding avec tri, filtrage, image
Nous allons créer une page contenant une ListBox affichant une liste de personnes.
L'application se nomme 'binding avancé' et la page 'MainPage'.
Créons une classe 'Personne' avec les propriétés Prenom, Nom, Adresse, Sexe, Image et une classe 'LesMembres' contenant une liste de personnes (ce code est dans un module de classe class1.cs).
L'application se nomme 'binding avancé' et la page 'MainPage'.
Créons une classe 'Personne' avec les propriétés Prenom, Nom, Adresse, Sexe, Image et une classe 'LesMembres' contenant une liste de personnes (ce code est dans un module de classe class1.cs).
|
Dans le code-behind C# de la page, on instancie 'Membres' de type 'LesMembres' et on ajoute quatre 'Personne'.
|
Dans le code XAML de la page, dans la grille principale, on ajoute une ListBox nommée 'ListBox1'.
Dans le ListBox on indique que l'ItemSource est une liaison (dans le code c# ci dessus le DataContext crée une liaison entre cette ListBox1 et Membres).
Dans le ListBox on indique que l'ItemSource est une liaison (dans le code c# ci dessus le DataContext crée une liaison entre cette ListBox1 et Membres).
|
On note qu'on a ajouté un ItemTemplate qui hérite de la liaison et affiche les propriétés Nom et Prenom.
Cela donne :

Nous allons aller plus loin.
Nous avons cette collection de Personne. Comment trier les personnes ? Comment n'afficher dans la ListBox que certaines personnes en fonction de critères ? Comment afficher des images ?
Pour cela ajoutons en haut le MainPage (pour avoir accès à Linq) et aux méthodes d'extension :
|
Maintenant on veut trier les personnes par le nom.
Nous allons utiliser OrderBy de Linq.
OrderBy effectue un tri.
Voilà comment modifier le DataContext :
|

Maintenant on veut filtrer les personnes par le Sexe.
On ne veut mettre dans la ListBox que les personnes de sexe 'F'. Nous allons utiliser Where de Linq.
Where précise les conditions à appliquer, c'est le 'filtre'.
Il faut ajouter une fonction TestSexe qui retourne true si Sexe="F" et modifier le DataContext qui filtrera en utilisant cette fonction :
|

Petit bonus
Si l'utilisateur clique sur un élément de la liste, il est possible de voir dans un contrôle Image sous la ListBox une image correspondant à la "Personne" sélectionnée (le nom de l'image est dans la propriété 'Image') :
Si l'utilisateur clique sur un élément de la liste, il est possible de voir dans un contrôle Image sous la ListBox une image correspondant à la "Personne" sélectionnée (le nom de l'image est dans la propriété 'Image') :
|
Ici on a fait un binding sur le SelectedItem de la ListBox1. Sa propriété Image sert de 'Source', ce qui affiche l'image.
Maintenant on veut afficher une image différente suivant le sexe.
Nous allons utiliser Select de Linq.
Select précise les éléments à extraire. Il faut ajouter en haut du fichier Class1.cs et du fichier MainPage :
|
Il faut créer une classe supplémentaire dans class1.cs.
|
Il faut créer (avec Paint) deux petites images, carrerose.jpg (de couleur rose) et carrebleue.jpg (de couleur bleue) et les mettre dans le répertoire du projet ; il faut ensuite les ajouter au projet (menu 'projet' puis 'Ajouter un élément existant'. Enfin il faut, dans les propriétés des images, indiquer 'contenu' dans 'option de génération'.
Dans MainPage, il faut ajouter une fonction 'giveImage' qui reçoit en paramètre 'F' ou 'M' et qui retourne un BitmapImage contenant l'image du carré rose ou bleue en fonction du sexe donc :
|
Il faut maintenant modifier le DataContext avec la clause Select qui retourne un objet de type PersonneImage avec le nom le prénom et un BitmapImage en fonction du sexe (pour cela on appelle la fonction giveImage).
|
Enfin il faut modifier, dans le code XAML, le DataTemplate de la ListBox en ajoutant un contrôle Image dont la propriété Source sera en liaison avec la propriété Image de l'objet PersonneImage :
|

Génial !
On peut mettre plusieurs clauses :
|
V-G-7. Générateur de liaison
Dans la fenêtre 'Propriétés' d'un contrôle, pour créer une liaison avec la propriété d'un contrôle on peut ouvrir la fenêtre du générateur de liaison en cliquant sur le carré à côté du nom de la propriété :

Dans le menu, choisir 'Appliquer la liaison de données'.

Choisir l'objet de liaison désiré.
V-G-8. Erreur dans le binding
Si, dans le code Xaml, nous orthographions mal le nom d'une propriété dans l'expression du binding ('nome' au lieu de 'nom' par exemple), il n'y a pas d'erreur à la compilation mais la liaison ne se fait pas.
Heureusement, il y a un message d'erreur dans la fenêtre de sortie (Ctrl+W, O) :
Heureusement, il y a un message d'erreur dans la fenêtre de sortie (Ctrl+W, O) :
