Bien démarrer avec XAML
Dans une application .NET Multi-platform App UI (.NET MAUI), XAML est principalement utilisé pour définir le contenu visuel d’une page et fonctionne avec un fichier code-behind C#. Le fichier code-behind fournit la prise en charge du code pour le balisage. Ensemble, ces deux fichiers contribuent à une nouvelle définition de classe qui inclut des vues enfants et l’initialisation des propriétés. Dans le fichier XAML, les classes et les propriétés sont référencées avec des éléments et des attributs XML, et les liens entre le balisage et le code sont établis.
Anatomie d’un fichier XAML
Une nouvelle application .NET MAUI contient trois fichiers XAML et les fichiers code-behind associés :
La première paire de fichiers est App.xaml, un fichier XAML, et App.xaml.cs, un fichier code-behind C# associé au fichier XAML. App.xaml et App.xaml.cs contribuent à une classe nommée App
qui dérive de Application
. La deuxième paire de fichiers est AppShell.xaml et AppShell.xaml.cs, qui contribuent à une classe nommée AppShell
dérivant de Shell. La plupart des autres classes des fichiers XAML contribuent à une classe qui dérive de ContentPage, et définissent l’interface utilisateur d’une page. Cela s’applique aux fichiers MainPage.xaml et MainPage.xaml.cs.
Le fichier MainPage.xaml a la structure suivante :
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyMauiApp.MainPage">
...
</ContentPage>
Les deux déclarations d’espace de noms XML (xmlns
) font référence à des URI sur microsoft.com. Toutefois, ces URI n’ont pas de contenu et fonctionnent essentiellement en tant qu’identificateurs de version.
La première déclaration d’espace de noms XML signifie que les balises définies sans préfixe dans le fichier XAML font référence à des classes dans .NET MAUI, par exemple ContentPage. La seconde déclaration d’espace de noms utilise le préfixe x
. Il est utilisé pour plusieurs éléments et attributs intrinsèques au code XAML lui-même et pris en charge par d’autres implémentations de XAML. Toutefois, ces éléments et attributs sont légèrement différents selon l’année incorporée dans l’URI. .NET MAUI prend en charge la spécification XAML 2009.
À la fin de la première balise, le préfixe x
est utilisé pour un attribut nommé Class
. Étant donné que l’utilisation de ce préfixe x
est pratiquement universelle pour l’espace de noms XAML, les attributs XAML tels que Class
sont presque toujours appelés x:Class
. L’attribut x:Class
spécifie un nom de classe .NET complet : la classe MainPage
dans l’espace de noms MyMauiApp
. Cela signifie que ce fichier XAML définit une nouvelle classe nommée MainPage
dans l’espace de noms MyMauiApp
qui dérive de ContentPage (balise dans laquelle l’attribut x:Class
apparaît).
L’attribut x:Class
ne peut apparaître que dans l’élément racine d’un fichier XAML pour définir une classe C# dérivée. Il s’agit de la seule nouvelle classe définie dans le fichier XAML. Tous les autres éléments apparaissant dans un fichier XAML sont simplement instanciés à partir de classes existantes et initialisés.
Le fichier MainPage.xaml.cs ressemble à ceci :
namespace MyMauiApp;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
La classe MainPage
dérive de ContentPage, et elle est une définition de classe partielle.
Lorsque Visual Studio crée le projet, un générateur de code source génère un nouveau code source C# qui contient la définition de la méthode InitializeComponent
appelée depuis le constructeur MainPage
et l’ajoute à l’objet de compilation.
Au moment du runtime, le code de la classe MauiProgram
démarre l’application et exécute le constructeur de classe App
, qui instancie AppShell
. La classe AppShell
instancie la première page de l’application à afficher, c’est-à-dire MainPage
. Le constructeur MainPage
appelle InitializeComponent
, qui initialise tous les objets définis dans le XAML, les connecte tous ensemble dans les relations parent-enfant, attache des gestionnaires d’événements définis dans le code aux événements définis dans le fichier XAML et définit l’arborescence résultante des objets comme contenu de la page.
Remarque
La classe AppShell
utilise l’interpréteur de commandes .NET MAUI pour définir la première page de l’application à afficher. Toutefois, l’interpréteur de commandes n’entre pas dans le cadre de cette introduction au code XAML. Pour plus d’informations, consultez Interpréteur de commandes .NET MAUI.
Définir le contenu de la page
Un ContentPage doit contenir un enfant unique, qui peut être une vue ou une disposition avec des vues enfants. L’enfant de la ContentPage est automatiquement défini comme valeur de la propriété ContentPage.Content
.
L’exemple suivant montre une ContentPage contenant un Label :
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.HelloXamlPage"
Title="Hello XAML Page">
<Label Text="Hello, XAML!"
VerticalOptions="Center"
HorizontalTextAlignment="Center"
Rotation="-15"
FontSize="18"
FontAttributes="Bold"
TextColor="Blue" />
</ContentPage>
Dans l’exemple ci-dessus, la relation entre les classes, les propriétés et XML doit être claire. Une classe .NET MAUI (telle que ContentPage ou Label) apparaît dans le fichier XAML en tant qu’élément XML. Les propriétés de cette classe, y compris Title
sur ContentPage et sept propriétés de Label, apparaissent généralement en tant qu’attributs XML.
De nombreux raccourcis existent pour définir les valeurs de ces propriétés. Certaines propriétés sont des types de données de base. Par exemple, les propriétés Title
et Text
sont de type string
et Rotation
est de type double
. La propriété HorizontalTextAlignment
est de type TextAlignment, qui est une énumération. Pour une propriété de type énumération, il vous suffit de fournir un nom de membre.
Toutefois, avec les propriétés de types plus complexes, des convertisseurs sont utilisés pour analyser le code XAML. Il s’agit de classes dans .NET MAUI qui dérivent de TypeConverter
. Pour l’exemple ci-dessus, plusieurs convertisseurs .NET MAUI sont automatiquement appliqués pour convertir des valeurs de chaîne vers leur type correct :
LayoutOptionsConverter
pour la propriétéVerticalOptions
. Ce convertisseur convertit les noms des champs statiques publics de la structureLayoutOptions
en valeurs de typeLayoutOptions
.ColorTypeConverter
pour la propriétéTextColor
. Ce convertisseur convertit les noms des champs statiques publics des valeurs RVB hexadécimales ou de la classe Colors, avec ou sans canal alpha.
Navigation dans les pages
Lorsque vous exécutez une application .NET MAUI, c’est la MainPage
qui s’affiche généralement. Pour afficher une autre page, vous pouvez définir cette page en tant que nouvelle page de démarrage dans le fichier AppShell.xaml ou accéder à la nouvelle page à partir de MainPage
.
Pour implémenter la navigation, dans le constructeur MainPage.xaml.cs, vous pouvez créer un Button simple et utiliser le gestionnaire d’événements pour accéder à HelloXamlPage
:
public MainPage()
{
InitializeComponent();
Button button = new Button
{
Text = "Navigate!",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
button.Clicked += async (sender, args) =>
{
await Navigation.PushAsync(new HelloXamlPage());
};
Content = button;
}
Lorsque vous compilez et déployez la nouvelle version de cette application, un bouton s’affiche à l’écran. La sélection de ce bouton permet d’accéder à HelloXamlPage
:
Vous pouvez revenir à MainPage
à l’aide de la barre de navigation qui s’affiche sur chaque plateforme.
Remarque
Une alternative à ce modèle de navigation consiste à utiliser l’interpréteur de commandes .NET MAUI. Pour plus d’informations, consultez Vue d’ensemble de l’interpréteur de commandes .NET MAUI.
Interactions entre XAML et le code
L’enfant de la plupart des dérivés de ContentPage est une disposition, telle qu’une StackLayout ou une Grid, et la disposition peut contenir plusieurs enfants. Dans le XAML, ces relations parent-enfant sont établies avec une hiérarchie XML normale :
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.XamlPlusCodePage"
Title="XAML + Code Page">
<StackLayout>
<Slider VerticalOptions="Center" />
<Label Text="A simple Label"
FontSize="18"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Button Text="Click Me!"
HorizontalOptions="Center"
VerticalOptions="Center" />
</StackLayout>
</ContentPage>
La syntaxe de ce fichier XAML est complète et produit l’interface utilisateur suivante :
Toutefois, même si vous pouvez interagir avec le Slider et le Button, l’interface utilisateur n’est pas mise à jour. Le Slider doit permettre au Label d’afficher la valeur actuelle et le Button doit avoir une fonction.
L’affichage d’une valeur Slider à l’aide d’un Label peut se faire entièrement dans le XAML avec une liaison de données. Toutefois, il est utile de voir d’abord la solution de code. La gestion du clic sur le Button nécessite de toute façon du code. Cela signifie que le fichier code-behind pour XamlPlusCodePage
doit contenir des gestionnaires pour l’événement ValueChanged
du Slider et l’événement Clicked
du Button :
namespace XamlSamples
{
public partial class XamlPlusCodePage
{
public XamlPlusCodePage()
{
InitializeComponent();
}
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
valueLabel.Text = args.NewValue.ToString("F3");
}
async void OnButtonClicked(object sender, EventArgs args)
{
Button button = (Button)sender;
await DisplayAlert("Clicked!", "The button labeled '" + button.Text + "' has been clicked", "OK");
}
}
}
De retour dans le fichier XAML, les balises Slider et Button doivent inclure des attributs pour les événements ValueChanged
et Clicked
qui font référence à ces gestionnaires :
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.XamlPlusCodePage"
Title="XAML + Code Page">
<StackLayout>
<Slider VerticalOptions="Center"
ValueChanged="OnSliderValueChanged" />
<Label x:Name="valueLabel"
Text="A simple Label"
FontSize="18"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Button Text="Click Me!"
HorizontalOptions="Center"
VerticalOptions="Center"
Clicked="OnButtonClicked" />
</StackLayout>
</ContentPage>
Notez que l’affectation d’un gestionnaire à un événement a la même syntaxe que l’affectation d’une valeur à une propriété. De plus, pour que le gestionnaire d’événements ValueChanged
du Slider utilise le Label pour afficher la valeur actuelle, le gestionnaire doit référencer cet objet à partir du code. Par conséquent, le Label doit avoir un nom, spécifié dans l’attribut x:Name
. Le préfixe x
de l’attribut x:Name
indique que cet attribut est intrinsèque au code XAML. Le nom que vous donnez à l’attribut x:Name
répond aux mêmes règles que les noms de variables C#. Par exemple, il doit commencer par une lettre ou un trait de soulignement et ne contenir aucun espace incorporé.
Le gestionnaire d’événements ValueChanged
peut maintenant définir le Label pour afficher la nouvelle valeur Slider, disponible à partir des arguments d’événement :
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
valueLabel.Text = args.NewValue.ToString("F3");
}
Le gestionnaire peut également obtenir l’objet Slider qui génère cet événement à partir de l’argument sender
et obtenir la propriété Value
à partir de là :
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
valueLabel.Text = ((Slider)sender).Value.ToString("F3");
}
Le résultat est que toute manipulation du Slider entraîne l’affichage de sa valeur dans le Label :
Dans l’exemple ci-dessus, le Button simule une réponse à un événement Clicked
en affichant une alerte avec le Text
du bouton. Par conséquent, le gestionnaire d’événements peut convertir l’argument sender
en un Button, puis accéder à ses propriétés :
async void OnButtonClicked(object sender, EventArgs args)
{
Button button = (Button)sender;
await DisplayAlert("Clicked!", "The button labeled '" + button.Text + "' has been clicked", "OK");
}
La méthode OnButtonClicked
est définie en tant que async
, car la méthode DisplayAlert est asynchrone et doit être précédée de l’opérateur await
, qui revient une fois la méthode terminée. Étant donné qu’avec cette méthode, le Button déclenche l’événement à partir de l’argument sender
, le même gestionnaire peut être utilisé pour plusieurs boutons.
Étapes suivantes
XAML est principalement conçu pour instancier et initialiser des objets. Cependant, les propriétés doivent souvent être définies sur des objets complexes qui ne peuvent pas facilement être représentés en tant que chaînes XML, et parfois les propriétés définies par une classe doivent être définies sur une classe enfant. Dans ces deux cas, les fonctionnalités de syntaxe XAML essentielle sont nécessaires pour les éléments de propriété et les propriétés jointes.