• Facile

Ce cours est visible gratuitement en ligne.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 29/04/2014

Ajouter du style

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Nous avons vu qu’on pouvait modifier les couleurs, la taille de l’écriture… grâce à la fenêtre des propriétés d’un contrôle. Cela modifie les propriétés des contrôles et affecte leur rendu. C’est très bien. Mais imaginons que nous voulions changer les couleurs et l'écriture de plusieurs contrôles, il va falloir reproduire ceci sur tous les contrôles, ce qui d’un coup est plutôt moins bien ! :(
C’est là qu’intervient le style. Il correspond à l’identification de plusieurs propriétés par un nom, que l’on peut appliquer facilement à plusieurs contrôles.

Afficher des images

Pour commencer, nous allons reparler du contrôle Image. Ce n’est pas vraiment un style à proprement parler, mais il va être très utile pour rendre nos pages un peu plus jolies. Nous l’avons rapidement utilisé en montrant qu’il était très simple d’afficher une image présente sur internet simplement en indiquant l’URL de celle-ci.
Il est également très facile d’afficher des images à nous, embarquées dans l’application. Pour cela, j’utilise une petite image toute bête, représentant un cercle rouge (voir la figure suivante).

Un cercle rouge sur fond blanc
Un cercle rouge sur fond blanc

Pour suivre cet exemple avec moi, je vous conseille de télécharger cette image, en cliquant ici.
Ajoutons donc cette image à la solution. Pour cela, je vais commencer par créer un nouveau répertoire Images sous le répertoire Assets qui a été ajouté lors de la création de la solution. Ensuite, nous allons ajouter un élément existant en faisant un clic droit sur le projet. Je sélectionne l’image qui s’ajoute automatiquement à la solution.

Ici, il faut faire attention à ce que dans les propriétés de l’image, l’action de génération soit à Contenu, ce qui est le paramètre par défaut pour les projets ciblant Windows Phone 8, mais pas Windows Phone 7 où c’est l’action de génération Resource qui est le paramètre par défaut. Contenu permet d’indiquer que l’image sera un fichier à part, non intégrée à l’assembly, nous y reviendrons à la fin de la partie (voir la figure suivante).

L'image doit avoir son action de génération à Contenu
L'image doit avoir son action de génération à Contenu

Nous pourrons alors très simplement afficher l’image en nous basant sur l’URL relative de l’image dans la solution :

<Image x:Name="MonImage" Source="/Assets/Images/rond.png" Width="60" Height="60" />

À noter que cela peut aussi se faire grâce au code behind. Pour cela, supprimons la propriété Source du XAML :

<Image x:Name="MonImage" Width="60" Height="60" />

Et chargeons l’image dans le code de cette façon :

MonImage.Source = new BitmapImage(new Uri("/Assets/Images/rond.png", UriKind.Relative));

Remarque : pour utiliser la classe BitmapImage, il faut ajouter le using suivant :

using System.Windows.Media.Imaging;

Cela semble moins pratique, mais je vous l’ai présenté car nous utiliserons cette méthode un petit peu plus loin.
D’une manière générale, il sera toujours plus pertinent de passer par le XAML que par le code !

Les ressources

Les ressources sont un mécanisme de XAML qui permet de réutiliser facilement des objets ou des valeurs. Chaque classe qui dérive de FrameworkElement dispose d’une propriété Resources, qui est en fait un dictionnaire de ressources. Chaque contrôle peut donc avoir son propre dictionnaire de ressources mais en général, on définit les ressources soit au niveau de la page, soit au niveau de l’application.
Par exemple, pour définir une ressource au niveau de la page, nous utiliserons la syntaxe suivante :

<phone:PhoneApplicationPage 
    x:Class="HelloWorld.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    [… plein de choses …]
    shell:SystemTray.IsVisible="True">

    <phone:PhoneApplicationPage.Resources>
        <SolidColorBrush x:Key="BrushRouge" Color="Red"/>
    </phone:PhoneApplicationPage.Resources>

    <[… plein de choses dans la page …]>
</phone:PhoneApplicationPage>

Ici, j’ai créé un objet SolidColorBrush, qui sert à peindre une zone d’une couleur unie, dont la couleur est Rouge dans les ressources de ma page. Il est obligatoire qu’une ressource possède un nom, ici je l’ai nommé BrushRouge.
Je vais désormais pouvoir utiliser cet objet avec des contrôles, ce qui donne :

<StackPanel>
    <TextBlock Text="Bonjour ma ressource" Foreground="{StaticResource BrushRouge}" />
    <Button Content="Cliquez-moi, je suis rouge" Foreground="{StaticResource BrushRouge}" />
</StackPanel>

Et nous aurons la figure suivante.

Utilisation d'une ressource de type pinceau rouge
Utilisation d'une ressource de type pinceau rouge

Alors, qu’y-a-t-il derrière ces ressources ?

La première chose que l’on peut voir c’est la syntaxe particulière à l’intérieur de la propriété ForeGround :

Foreground="{StaticResource BrushRouge}"

Des accolades avec le mot-clé StaticResource… Cela signifie qu’à l’exécution de l’application, le moteur va aller chercher la ressource associée au nom BrushRouge et il va la mettre dans la propriété Foreground de notre contrôle.

Ce moteur commence par chercher la ressource dans les ressources de la page et s’il ne la trouve pas, il ira chercher dans le dictionnaire de ressources de l’application. Nous avons positionné notre ressource dans la page, c’est donc celle-ci qu’il utilise en premier.

Remarquez que le dictionnaire de ressources, c’est simplement une collection d’objets associés à un nom. S’il est défini dans la page, alors il sera accessible pour tous les contrôles de la page. S’il est défini au niveau de l’application, alors il sera utilisable partout dans l’application.
Vous aurez pu constater qu’ici, notre principal intérêt d’utiliser une ressource est de pouvoir changer la couleur de tous les contrôles en une seule fois.

Nous pouvons mettre n’importe quel objet dans les ressources. Nous y avons mis un SolidColorBrush afin que cela se voit, mais il est possible d’y mettre un peu tout et n’importe quoi. Pour illustrer ce point, nous allons utiliser le dictionnaire de ressource de l’application et y stocker une chaine de caractère. Ouvrez donc le fichier App.xaml où se trouve le dictionnaire de ressources. Nous pouvons ajouter notre chaine de caractères dans la section <Application.Resources> déjà existante pour avoir :

<Application.Resources>
    <system:String x:Key="TitreApplication">Hello World</system:String>
</Application.Resources>

Vous serez obligés de rajouter l’espace de nom suivant en haut du fichier App.xaml :

xmlns:system="clr-namespace:System;assembly=mscorlib"

dans les propriétés de l’application de manière à avoir :

<Application 
    x:Class="HelloWorld.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:system="clr-namespace:System;assembly=mscorlib">

Pourquoi ? Parce que la classe String n’est pas connue de l’application. Il faut lui indiquer où elle se trouve, en indiquant son espace de nom, un peu comme un using C#.
Pour cela on utilise la syntaxe précédente pour dire que l’espace de nom que j’ai nommé « system » correspondra à l’espace de nom System de l’assembly mscorlib.
Pour utiliser ma classe String, il faudra que je la préfixe de « system: ».

Bref, revenons à notre ressource de type String. Je vais pouvoir l’utiliser depuis n’importe quelle page vu qu’elle est définie dans le dictionnaire de ressources de l’application, par exemple dans ma page principale :

<TextBlock Text="{StaticResource TitreApplication}" Foreground="{StaticResource BrushRouge}" />

Et nous aurons donc la figure suivante.

Utilisation d'une ressource de type chaîne de caractère
Utilisation d'une ressource de type chaîne de caractère

Les styles

Le style correspond à l’identification de plusieurs propriétés par un nom, que l’on peut appliquer facilement à plusieurs contrôles.
Un style trouve donc tout à fait naturellement sa place dans les dictionnaires de ressources que nous avons déjà vus. Un style est, comme une ressource, caractérisé par un nom et cible un type de contrôle. Par exemple, observons le style suivant :

<phone:PhoneApplicationPage.Resources>
    <Style x:Key="StyleTexte" TargetType="TextBlock">
        <Setter Property="Foreground" Value="Green" />
        <Setter Property="FontSize" Value="35" />
        <Setter Property="FontFamily" Value="Comic Sans MS" />
        <Setter Property="Margin" Value="0 20 0 20" />
        <Setter Property="HorizontalAlignment" Value="Center" />
    </Style>
</phone:PhoneApplicationPage.Resources>

On remarque l’élément important TargetType="TextBlock" qui me permet d’indiquer que le style s’applique aux contrôles TextBlock. La lecture du style nous renseigne sur ce qu’il fait. Nous pouvons remarquer que la propriété Foreground aura la valeur Green, que la propriété FontSize aura la valeur 35, etc.
Pour que notre contrôle bénéficie de ce style, nous pourrons utiliser encore la syntaxe suivante :

<TextBlock Text="{StaticResource TitreApplication}" Style="{StaticResource StyleTexte}"/>

Ce qui nous donnera la figure suivante.

Le style appliqué au TextBlock
Le style appliqué au TextBlock

Ah, mais ça me rappelle quelque chose, on n‘a pas déjà vu des styles ?
Et si, lorsque nous créons une nouvelle application, Visual Studio nous créé le squelette d’une page dans le fichier MainPage.xaml et nous avons notamment le titre de la page défini de cette façon :

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
    <TextBlock Text="MON APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
    <TextBlock Text="Hello World" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

Vous pouvez désormais comprendre que ces deux TextBlock utilisent les styles PhoneTextNormalStyle et PhoneTextTitle1Style. Ce ne sont pas des styles que nous avons créés. Il s’agit de styles systèmes, présents directement dans le système d’exploitation et que nous pouvons utiliser comme bon nous semble.
Le style est un élément qui sera très souvent utilisé dans nos applications. Définir le XAML associé à ces styles est un peu rébarbatif. Heureusement, Blend peut nous aider dans la création de style…
Prenons par exemple le code XAML suivant :

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <TextBlock Text="Nom" Grid.Column="0" Grid.Row="0" />
    <TextBox Grid.Row="0" Grid.Column="1" />
    <TextBlock Text="Prénom" Grid.Column="0" Grid.Row="1" />
    <TextBox Grid.Row="1" Grid.Column="1" />
    <TextBlock Text="Age" Grid.Column="0" Grid.Row="2" />
    <TextBox Grid.Row="2" Grid.Column="1" />
</Grid>

Qui donne la figure suivante.

Aperçu d'un formulaire construit en XAML
Aperçu d'un formulaire construit en XAML

Si nous passons dans Blend, nous pouvons facilement créer un style en faisant un clic droit sur un TextBlock et en choisissant de modifier le style, puis de créer un nouveau style en choisissant de créer un élément vide (voir la figure suivante).

Modification du style dans Blend
Modification du style dans Blend

Blend nous ouvre une nouvelle fenêtre où nous pouvons créer un nouveau style (voir la figure suivante).

Fenêtre de création d'un nouveau style
Fenêtre de création d'un nouveau style

Nous devons fournir un nom au style puis nous pouvons indiquer quelle est la portée du style, soit toute l’application (ce que j’ai choisi), soit la page courante, soit un dictionnaire de ressources déjà existant.

Le style est créé dans le fichier App.xaml, comme nous l’avons déjà vu, qui est le fichier de lancement de l’application. Je peux aller modifier les propriétés du style, par exemple la couleur (voir la figure suivante).

Modification de la couleur du style
Modification de la couleur du style

Une fois le style terminé, je peux retourner dans ma page pour appliquer ce style aux autres contrôles. Pour cela, j’utilise le bouton droit sur le contrôle, Modifier le style , Appliquer la ressource, et je peux retrouver mon style tout en haut (voir la figure suivante).

Notre nouveau style fait partie de la liste des styles
Notre nouveau style fait partie de la liste des styles

On remarque au passage qu’il existe plein de styles déjà tout prêts, ce sont des styles systèmes comme ceux que nous avons vu un peu plus haut et dont nous pouvons allégrement nous servir !
De retour dans le XAML, je peux constater qu’une propriété a été rajoutée à mes TextBlock :

<TextBlock Text="Prénom" Grid.Column="0" Grid.Row="1" Style="{StaticResource TexteStyle}" />

C’est la propriété Style bien évidemment, qui va permettre d’indiquer que l’on applique le style TexteStyle. Celui-ci est défini dans le XAML du fichier App.xaml :

<Style x:Key="TexteStyle" TargetType="TextBlock">
    <Setter Property="Foreground" Value="#FF0B5EF0"/>
    <Setter Property="FontFamily" Value="Andy"/>
    <Setter Property="FontSize" Value="32"/>
</Style>

Ce qui correspond aux valeurs que j’ai modifiées. Et voilà, plutôt simple non ?
Remarquons avant de terminer que les styles peuvent hériter entre eux, ce qui permet de compléter ou de remplacer certaines valeurs. Prenons par exemple le XAML suivant :

<Style x:Key="TexteStyle" TargetType="TextBlock">
    <Setter Property="Foreground" Value="#FF0B5EF0"/>
    <Setter Property="FontFamily" Value="Andy"/>
    <Setter Property="FontSize" Value="32"/>
</Style>
<Style x:Key="TexteStyle2" TargetType="TextBlock" BasedOn="{StaticResource TexteStyle}">
    <Setter Property="FontSize" Value="45"/>
    <Setter Property="HorizontalAlignment" Value="Center" />
</Style>

Le deuxième style hérite du premier grâce à la propriété BaseOn.
Notez que les styles sont encore plus puissants que ça, nous aurons l’occasion de voir d’autres utilisations plus loin dans le cours.

Les thèmes

Si vous avez joué avec l’émulateur ou avec vos Windows Phone, vous avez pu vous rendre compte que Windows Phone disposait de plusieurs thèmes. Ouvrez votre émulateur et faites glisser l’écran sur la droite ou cliquez sur la flèche en bas de l’écran d’accueil, cliquez ensuite sur Paramètres (voir la figure suivante).

Accès au menu de paramétrage de l'émulateur
Accès au menu de paramétrage de l'émulateur

Puis sur thème (voir la figure suivante).

Accès au paramétrage des thèmes
Accès au paramétrage des thèmes

On obtient cet écran (voir la figure suivante).

Paramétrage des thèmes
Paramétrage des thèmes

Il est possible de choisir le thème, soit sombre soit clair puis la couleur d’accentuation (voir la figure suivante).

Modification de la couleur d'accentuation
Modification de la couleur d'accentuation

Qu’est-ce que ça veut dire ? Eh bien cela veut dire qu’on ne peut pas faire n’importe quoi avec les couleurs et surtout pas n’importe comment. Par exemple, si j’écris du texte de couleur blanche, cela passera très bien avec mon thème sombre, mais cela deviendra invisible avec un thème clair.

Les contrôles de Windows Phone savent gérer ces différents thèmes sans aucun problème grâce aux styles systèmes qui savent s’adapter aux différents thèmes, comme par exemple les styles PhoneTextNormalStyle et PhoneTextTitle1Style.
Ainsi, si vous lancez votre application fraîchement créée en mode sombre, vous aurez les titres suivants (voir la figure suivante).

Le titre est blanc sur fond noir en mode sombre
Le titre est blanc sur fond noir en mode sombre

Alors qu’en mode clair, vous aurez la figure suivante.

Le titre est noir sur fond blanc en mode clair
Le titre est noir sur fond blanc en mode clair

Les couleurs sont différentes, c’est le style qui gère les différents thèmes. Il est possible de détecter le thème de l’application afin d’adapter nos designs, par exemple en changeant une image ou en changeant une couleur, etc.
Pour ce faire, on peut utiliser la technique suivante :

Visibility darkBackgroundVisibility = (Visibility)Application.Current.Resources["PhoneDarkThemeVisibility"];
if (darkBackgroundVisibility == Visibility.Visible)
{
    // le thème est sombre
}
else
{
    // le thème est clair
}

De même, on peut récupérer la couleur d’accentuation choisie afin de l’utiliser sur nos pages, par exemple :

Color couleur = (Color)Application.Current.Resources["PhoneAccentColor"];
MonTextBox.Foreground = new SolidColorBrush(couleur);

Changer l’apparence de son contrôle

Il n’y a pas que les styles qui permettent de changer l’apparence d’un contrôle. Rappelez-vous, nous avons dit que certains contrôles dérivaient de la classe ContentControl. Il s’agit de contrôles qui contiennent d’autres objets.
C’est le cas du bouton par exemple. Il est possible de modifier son apparence sans changer ses fonctionnalités. C’est une des grandes forces du XAML. Il suffit de redéfinir la propriété Content du bouton…
Jusqu’à présent, un bouton c’était ce XAML (à l’intérieur d’un StackPanel) :

<Button Content="Cliquez-moi !" />

Qui donnait la figure suivante.

Un simple bouton
Un simple bouton

Nous avons mis une chaîne de caractères dans la propriété Content. Cette propriété est de type object, il est donc possible d’y mettre n’importe quoi. En l’occurrence, on peut y mettre un TextBlock qui donnera le même résultat visuel :

<Button>
    <Button.Content>
        <TextBlock Text="Cliquez-moi" />
    </Button.Content>
</Button>

Si on peut mettre un TextBlock, on peut mettre n’importe quoi et c’est ça qui est formidable. Par exemple, on peut facilement mettre une image. Reprenons notre rond rouge du début du chapitre, puis utilisez le XAML suivant :

<Button>
    <Button.Content>
        <StackPanel>
            <Image Source="/Assets/Images/rond.png" Width="100" Height="100" />
            <TextBlock Text="Cliquez-moi !" />
        </StackPanel>
    </Button.Content>
</Button>

Nous obtenons un bouton tout à fait fonctionnel possédant une image et un texte (voir la figure suivante).

Un bouton avec une image
Un bouton avec une image

Nous n’avons rien eu d’autre à faire que de modifier l’objet Content et ce bouton continue à se comporter comme un bouton classique.
Remarquons avant de terminer qu’il est possible de pousser la personnalisation encore plus loin grâce aux modèles (en anglais template) que nous verrons plus loin.

  • Les styles sont un élément très puissant nous permettant de modifier l’apparence de nos contrôles.

  • On peut changer l’apparence des contrôles de type ContentControl pour créer un autre look tout en conservant la fonctionnalité du contrôle.

  • Il faut faire attention aux différents thèmes d’une application et toujours vérifier que ce qu’on souhaite afficher soit bien visible en fonction des thèmes et de la couleur d’accentuation.

Exemple de certificat de réussite
Exemple de certificat de réussite