La représentation XAML de l'exemple précédent devient alors :
<Window x:Class="WpfApplication1.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<DockPanel Name="dockPanel" LastChildFill="False">
<DockPanel.Children>
<Button Name="button1" DockPanel.Dock="Bottom">
<Button.Background>
<SolidColorBrush>AliceBlue</SolidColorBrush>
</Button.Background>
<Button.Width>100</Button.Width>
<Button.Height>50</Button.Height>
<Button.Content>Hello</Button.Content>
</Button>
<Button Name="button2" DockPanel.Dock="Top">
<Button.Background>
<SolidColorBrush>Aquamarine</SolidColorBrush>
</Button.Background>
<Button.Width>100</Button.Width>
<Button.Height>50</Button.Height>
<Button.Content>Hello</Button.Content>
</Button>
</DockPanel.Children>
</DockPanel>
</Window>
Ce modèle reflète fidèlement ce qui a pu être écrit en C# en respectant l'organisation hiérarchique. Bien entendu il est possible d'écrire la même chose en utilisant une version abrégée plus proche de ce qu'on peut connaître ailleurs (par exemple dans le monde HTML) :
<Window x:Class="WpfApplication1.Window2bis"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<DockPanel Name="dockPanel" LastChildFill="False">
<Button Name="button1" DockPanel.Dock="Bottom" Width="100" Height="50" Background="AliceBlue" Content="Hello"/>
<Button Name="button2" DockPanel.Dock="Top" Width="100" Height="50" Background="Aquamarine">
Hello
</Button>
</DockPanel>
</Window>
On notera (pour le moment) qu'un fichier XAML est un fichier XML avec les caractéristiques suivantes :
- Il ne supporte que les encodages UTF-16, UTF-8 (valeur par défaut) et ASCII.
- Les propriétés des classes sont mappées en éléments et/ou attributs XML. En effet contrairement à HTML qui est un langage orienté présentation, XAML est un langage d'instanciation des classes .Net où la transformation d'une chaine de caractères XML en objet .Net se fait soit par conversion simple (par exemple une chaine vers un entier) soit via un TypeConverter.
- Il y a généralement deux namespaces : un pour WPF (celui par défaut) et un pour XAML (x : par convention).
- Comme nous le verrons par la suite les caractères {et} servent de séquences d'échappement à XAML.
Le mapping entre les namespaces .Net et XML se fait via l'attribut
XmlnsDefinitionAttribute. Par exemple :
Dans le cas suivant :
<Button Name="button2" DockPanel.Dock="Top" Width="100" Height="50" Background="Aquamarine">
Hello
</Button>
on constate que sans préciser à quelle propriété correspond
Hello elle est automatiquement affectée à la propriété
Content du bouton. En effet une classe peut préciser une propriété par défaut grâce au mot clé
DefaultPropertyAttribute.
Par exemple, dans notre cas, la classe de base
ContentControl indique :
On remarque aussi que dans le tag
Button on peut faire appel aux propriétés du
DockPanel . Ce type de propriété dont la valeur peut être fixée au niveau d'un élément fils porte le nom d'
attached properties :
<Button Name="button1" DockPanel.Dock="Bottom">
Maintenant on peut se demander si avec un tel mécanisme la performance est au rendez-vous. Dans les faits la performance est préservée car le fichier XAML est compilé en un fichier portant l'extension
BAML (B pour binary) puis positionné en ressource de l'exécutable. Ce processus peut être facilement observé à travers les fichiers intermédiaires générés lors de la compilation :
Le code C# généré dans le fichier portant l'extension
.g.cs se contente de charger la ressource BAML:
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/WpfApplication1;component/window8.xaml", System.UriKind.Relative);
#line 1 "..\..\Window8.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
Le tout est ensuite compilé et produit un exécutable dont l'analyse avec
Reflector (étendu par le plugin
BAMLViewer) donne ceci :
Toutefois les éléments suivants ne collent pas vraiment au modèle hiérarchique du XML :
- Les ressources
- Les évènements
- Le binding
- Le multilinguisme
- ...
Nous allons voir comment ces deux premiers points sont pris en charge par XAML.