Traduction

Cet article est la traduction la plus fidèle possible de l'article original de Josh Smith, A Guided Tour of WPF - Part 1 (XAML).

I. Introduction

Télécharger le code source

Télécharger l'application de démonstration

image

Cet article est le premier d'une série qui passe en revue certaines fonctionnalités majeures de la technologie Windows Presentation Foundation (WPF) de Microsoft. Cette série effleure à peine la surface du vaste domaine qu'est WPF et ne rentre pas trop dans les détails d'un sujet en particulier. Le but de cette série est de familiariser le lecteur avec les bases du modèle de programmation de WPF, au point où il sera suffisamment à l'aise pour comprendre entièrement l'application - un peu idiote - WPF Horse Race (disponible en téléchargement via les liens ci-dessus).

Le sujet de cet article est présenté dans le contexte d'une application totalement inutile de course de chevaux, que vous pouvez voir dans la capture d'écran ci-dessus. Cette application a été conçue pour être utilisée comme trame de cette série. J'ai essayé de trouver un juste équilibre entre rendre cette démo assez simple pour être comprise par quelqu'un qui découvre WPF, et suffisamment complexe pour faire quelque chose d'intéressant (ou du moins assez amusant).

II. Prérequis

Pour exécuter une application WPF, il vous faut le .NET Framework 3.0 ou une version plus récente. Windows Vista a le .NET Framework 3.0 installé par défaut, vous n'avez donc besoin de l'installer que si vous êtes sous Windows XP SP2.

Pour développer une application WPF, vous devez avoir Visual Studio 2005 avec les extensions Orcas, ou une version plus récente de Visual Studio, ainsi que le Windows SDK. Consultez la section Liens Externes à la fin de l'article pour des liens vers les ressources concernées.

III. Qu'est-ce que XAML ?

XAML signifie eXtensible Application Markup Language. C'est un langage multi-usage basé sur XML, utilisé pour déclarer des graphes d'objets qui sont instanciés à l'exécution. XAML est utilisé par les développeurs WPF pour déclarer la structure d'une interface utilisateur (IHM), ainsi que les ressources utilisées dans cette IHM.

Il n'est pas du tout obligatoire d'utiliser XAML pour programmer en WPF. Tout ce qui peut être fait en XAML peut aussi être fait en code. Utiliser XAML rend plus faciles et plus rapides de nombreux scénarios de développement, comme créer la structure de l'IHM et configurer les styles, modèles (templates) et autres entités spécifiques à WPF qui seront présentées plus tard dans cette série.

IV. Impact sur les performances

Quand vous compilez une application WPF dans Visual Studio, vos fichiers XAML sont compilés en une représentation compressée appelée Binary Application Markup Language (BAML). Ce BAML est ensuite sauvegardé comme une ressource dans l'assembly produit. Quand cet assembly est chargé et que la ressource est demandée, le BAML est lu et très rapidement transformé pour produire le graphe d'objet décrit par le XAML d'origine.

Ce processus en deux étapes permet à l'analyse du XAML d'être effectuée à la compilation, ce qui limite la dégradation de performance liée à l'instanciation d'objets à partir de texte. Cela dit, il est possible de charger du XML à partir du code à l'aide de la méthode XamlReader.Load. Le chargement dynamique de XAML peut être utile dans toutes sortes de situations, par exemple, si une partie modifiable de votre IHM doit être régulièrement téléchargée d'un serveur via un service Web XML.

V. Syntaxe élémentaire

Puisque XAML est un langage basé sur XML, il devrait être assez simple et clair pour n'importe quelle personne ayant l'habitude de XML. Il y a deux utilisations différentes des éléments XML en XAML : les éléments qui représentent des objets, et ceux qui représentent des propriétés des objets. Un attribut XML représente toujours une propriété ou un évènement d'un objet. C'est tout ; c'est aussi simple que ça. Il y a quelques autres concepts qui s'ajoutent à ces règles fondamentales, mais le XAML ne devient jamais compliqué.

Par exemple :

 
Sélectionnez
<Button Content="Click Me" Click="OnButtonClick">
  <Button.Background>
    <LinearGradientBrush>
      <GradientStop Color="Yellow" Offset="0" />
      <GradientStop Color="Green" Offset="1" />
    </LinearGradientBrush>
  </Button.Background>
</Button>


Le code XAML ci-dessus produit un petit bouton sympa, dont le rendu ressemble à ça :

image

Disséquons ce XAML pour voir comment il fonctionne. L'élément <Button> déclare qu'une instance de la classe Button sera créée. L'objet Button aura pour valeur de la propriété Content la chaîne « Click Me ». L'évènement Click du bouton sera géré par une méthode appelée OnButtonClick dans le fichier de code-behind (nous parlerons du code-behind d'ici peu).

L'élément suivant <Button.Background> utilise la syntaxe appelée « élément de propriété » (propertyelementsyntax). Cet élément XML représente la propriété Background du bouton qu'on est en train de configurer. L'élément enfant de cet élément de propriété est la valeur qu'on affecte à la propriété. Dans le cas présent, on affecte à la propriété Background un objet LinearGradientBrush (pinceau de dégradé linéaire).

Ce pinceau a deux éléments enfants <GradientStop>, qui peuvent sembler déroutants au début. Que font ces objets GradientStop ici ? À quoi sont-ils affectés ou ajoutés ? La réponse réside dans le fait que XAML intègre des « raccourcis » qui permettent de spécifier qu'une propriété d'une classe est considérée comme son « contenu ». Il n'est pas nécessaire d'utiliser la syntaxe d'élément de propriété pour affecter une valeur à la propriété de contenu. Puisque la propriété de contenu de LinearGradientBrush est la propriété GradientStops, le code XAML suivant est équivalent à celui ci-dessus :

 
Sélectionnez
<Button Content="Click Me" Click="OnButtonClick">
  <Button.Background>
    <LinearGradientBrush>
      <LinearGradientBrush.GradientStops>
        <GradientStop Color="Yellow" Offset="0" />
        <GradientStop Color="Green" Offset="1" />
      <LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
  </Button.Background>
</Button>

VI. La version C#

Si vous êtes curieux de savoir à quoi ressemblerait ce XAML s'il était écrit en C#, voilà la traduction :

other
Sélectionnez
Button b = new Button();
b.Content = "Click Me";
b.Click += this.OnButtonClick;
LinearGradientBrush lgb = new LinearGradientBrush();
lgb.GradientStops.Add( new GradientStop( Colors.Yellow, 0 ) );
lgb.GradientStops.Add( new GradientStop( Colors.Green, 1 ) );
b.Background = lgb;

VII. Markup extensions

Le parseur XAML sait aussi travailler avec des éléments de syntaxe spéciaux appelés « markup extensions ». Les markup extensions permettent, de façon compacte, de configurer des objets ou de référencer d'autres objets définis ailleurs dans l'application. Elles sont utilisées pour affecter une valeur à un objet, soit via un attribut XML, soit avec la syntaxe d'élément de propriété. Les markup extensions sont utilisées, par exemple, pour spécifier une valeur nulle, déclarer un tableau, référencer un objet défini dans un dictionnaire de ressources, lier une propriété à une autre, et bien d'autres cas encore.

Le code XAML suivant est à peu près équivalent à l'exemple précédent (avec des changements mineurs) :

 
Sélectionnez
<Grid>
  <Grid.Resources>
    <LinearGradientBrush x:Key="FunkyBrush">
      <GradientStop Color="Yellow" Offset="0" />
      <GradientStop Color="Green" Offset="1" />
    </LinearGradientBrush>
  </Grid.Resources>
  <Button Background="{StaticResource FunkyBrush}">Click Me</Button>
</Grid>

Remarquez que la propriété Background du bouton est définie, via un attribute XML, à la valeur {StaticResourceFunkyBrush}. Quand un attribut est défini avec une valeur qui commence par {et se termine par }, il s'agit d'une markup extension.

Dans le cas présent la classe StaticResourceExtension est utilisée pour référencer la LinearGradientBrush définie dans le dictionnaire de ressources de la Grid. (Remarque : Grid est un panneau de disposition des éléments en WPF, et non un contrôle de présentation de données sous forme de tableau comme on pourrait s'y attendre).

VIII. Fichiers de code-behind

Le code XAML est compilé en une classe. Si vous ne spécifiez pas le nom de classe qu'il doit utiliser, le compilateur générera un nom pour vous. Cependant, si vous appliquez l'attribut x:Class à l'élément XML racine du fichier XAML, vous pouvez créer une classe partielle en C# ou VB.NET qui sera fusionnée avec la classe partielle XAML. C'est comme cela que vous pouvez associer un comportement à la structure et aux éléments visuels déclarés en XAML.

Par exemple, dans la démonstration ci-dessus, on a créé un bouton en XAML et on lui a affecté une méthode pour gérer l'évènement Click. La méthode OnButtonClick serait définie dans le fichier de code-behind qui contient l'autre partie de la classe partielle générée par le XAML.

Supposons que le bouton dont on parlait est dans une fenêtre appelée MyWindow dérivée de la classe Window. Voilà ce que contiendrait le fichier de code-behind (MyWindow.xaml.cs) :

 
Sélectionnez
public partial class MyWindow : Window
{
 public MyWindow()
 {
  InitializeComponent();
 }
 void OnButtonClick( object sender, RoutedEventArgs e )
 {
  MessageBox.Show( "Click me again.  That felt good." );
 }
}

IX. Comment l'application WPF Horse Race utilise XAML

L'application WPF Horse Race est presque entièrement écrite en XAML. L'application utilise trois fichiers C# : le code-behind pour la fenêtre principale, un fichier pour la classe HorseRace, et un autre qui contient des convertisseurs de valeur (on en reparlera dans l'article sur le binding). Tout le reste de l'application est en XAML.

Je vous encourage à explorer le code source de l'application WPF Horse Race et à regarder à quoi ressemble le XAML quand il est utilisé pour créer un vrai programme (par opposition à la simple démonstration vue jusqu'ici). Le reste des articles de la série examinera comment fonctionne l'application complète, mais rien ne remplace le fait de creuser le code source et de voir vous-même comment il fonctionne.

X. Liens externes

Remerciements

Je tiens ici à remercier Josh Smith pour son aimable autorisation de traduire l'article, ainsi que Karzoff pour la relecture orthographique.