Partie 1. Bien démarrer avec XAML
Dans une Xamarin.Forms application, 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.
Création de la solution
Pour commencer à modifier votre premier fichier XAML, utilisez Visual Studio ou Visual Studio pour Mac pour créer une Xamarin.Forms solution. (Sélectionnez l’onglet ci-dessous correspondant à votre environnement.)
Dans Windows, lancez Visual Studio 2019 et, dans la fenêtre de démarrage, cliquez sur Créer un projet pour créer un projet :
Dans la fenêtre Créer un projet, sélectionnez Mobile dans la liste déroulante Type de projet, sélectionnez le modèle Application mobile (Xamarin.Forms) et cliquez sur le bouton Suivant :
Dans la fenêtre Configurer votre nouveau projet, définissez le nom du projet sur XamlSamples (ou selon vos préférences), puis cliquez sur le bouton Créer.
Dans la boîte de dialogue Nouvelle application multiplateforme, cliquez sur Vide, puis sur le bouton OK :
Quatre projets sont créés dans la solution : la bibliothèque XamlSamples .NET Standard, XamlSamples.Android, XamlSamples.iOS et la solution plateforme Windows universelle, XamlSamples.UWP.
Après avoir créé la solution XamlSamples , vous pouvez tester votre environnement de développement en sélectionnant les différents projets de plateforme en tant que projet de démarrage de solution, et en créant et en déployant l’application simple créée par le modèle de projet sur des émulateurs téléphoniques ou des appareils réels.
Sauf si vous devez écrire du code spécifique à la plateforme, le projet de bibliothèque XamlSamples .NET Standard partagé est l’endroit où vous passerez pratiquement tout votre temps de programmation. Ces articles ne s’aventureront pas en dehors de ce projet.
Anatomie d’un fichier XAML
Dans la bibliothèque XamlSamples .NET Standard, vous trouverez une paire de fichiers portant les noms suivants :
- App.xaml, le fichier XAML et
- App.xaml.cs, un fichier code-behind C# associé au fichier XAML.
Vous devez cliquer sur la flèche en regard d’App.xaml pour afficher le fichier code-behind.
App.xaml et App.xaml.cs contribuent à une classe nommée App
qui dérive de Application
. La plupart des autres classes avec des fichiers XAML contribuent à une classe qui dérive de ContentPage
; ces fichiers utilisent XAML pour définir le contenu visuel d’une page entière. Cela est vrai pour les deux autres fichiers du projet XamlSamples :
- MainPage.xaml, le fichier XAML et
- MainPage.xaml.cs, le fichier code-behind C#.
Le fichier MainPage.xaml ressemble à ceci (bien que la mise en forme puisse être un peu différente) :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
x:Class="XamlSamples.MainPage">
<StackLayout>
<!-- Place new controls here -->
<Label Text="Welcome to Xamarin Forms!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
Les deux déclarations d’espace de nomsxmlns
XML () font référence aux URI, la première apparemment sur le site web de Xamarin et la seconde sur Microsoft. Ne vous dérangez pas à vérifier ce à quoi pointent ces URI. Il n’y a rien. Ils sont simplement des URI appartenant à Xamarin et Microsoft, et ils fonctionnent essentiellement en tant qu’identificateurs de version.
La première déclaration d’espace de noms XML signifie que les balises définies dans le fichier XAML sans préfixe font référence aux classes dans Xamarin.Forms, 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. Xamarin.Forms prend en charge la spécification XAML 2009, mais pas toutes.
La local
déclaration d’espace de noms vous permet d’accéder à d’autres classes à partir du projet de bibliothèque .NET Standard.
À la fin de cette première balise, le x
préfixe 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 XamlSamples
. Cela signifie que ce fichier XAML définit une nouvelle classe nommée MainPage
dans l’espace XamlSamples
de noms qui dérive de ContentPage
la 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. Tout le reste qui apparaît dans le fichier XAML est simplement instancié à partir de classes existantes et initialisé.
Le fichier MainPage.xaml.cs ressemble à ceci (à part les directives inutilisées using
) :
using Xamarin.Forms;
namespace XamlSamples
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
}
La MainPage
classe dérive de ContentPage
, mais notez la définition de partial
classe. Cela suggère qu’il doit y avoir une autre définition de classe partielle pour MainPage
, mais où est-ce ? Et quelle est cette InitializeComponent
méthode ?
Lorsque Visual Studio génère le projet, il analyse le fichier XAML pour générer un fichier de code C#. Si vous recherchez dans le répertoire XamlSamples\XamlSamples\obj\Debug , vous trouverez un fichier nommé XamlSamples.MainPage.xaml.g.cs. Le « g » signifie « g » généré. Il s’agit de l’autre définition partielle de classe qui MainPage
contient la définition de la InitializeComponent
méthode appelée à partir du MainPage
constructeur. Ces deux définitions de classes partielles MainPage
peuvent ensuite être compilées ensemble. Selon que le code XAML est compilé ou non, le fichier XAML ou une forme binaire du fichier XAML est incorporé dans l’exécutable.
Au moment de l’exécution, le code dans le projet de plateforme particulier appelle une LoadApplication
méthode, en lui transmettant une nouvelle instance de la App
classe dans la bibliothèque .NET Standard. Le App
constructeur de classe instancie MainPage
. Constructeur de cette classe appelle InitializeComponent
ensuite la LoadFromXaml
méthode qui extrait le fichier XAML (ou son fichier binaire compilé) à partir de la bibliothèque .NET Standard. LoadFromXaml
initialise tous les objets définis dans le fichier 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.
Bien que vous n’ayez normalement pas besoin de consacrer beaucoup de temps aux fichiers de code générés, des exceptions d’exécution sont parfois déclenchées sur le code dans les fichiers générés. Vous devez donc être familiarisé avec eux.
Lorsque vous compilez et exécutez ce programme, l’élément Label
apparaît au centre de la page, comme le suggère le code XAML :
Pour des visuels plus intéressants, tout ce dont vous avez besoin est plus intéressant EN XAML.
Ajout de nouvelles pages XAML
Pour ajouter d’autres classes XAML ContentPage
à votre projet, sélectionnez le projet de bibliothèque XamlSamples .NET Standard, cliquez avec le bouton droit et sélectionnez Ajouter > un nouvel élément.... Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Visual C# Items >Xamarin.Forms> Content Page (et non Content Page (C#), qui crée une page de code uniquement ou un mode Contenu, qui n’est pas une page. Donnez un nom à la page, par exemple HelloXamlPage :
Deux fichiers sont ajoutés au projet, HelloXamlPage.xaml et le fichier code-behind HelloXamlPage.xaml.cs.
Définition du contenu de la page
Modifiez le fichier HelloXamlPage.xaml afin que les seules balises soient celles pour ContentPage
et ContentPage.Content
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.HelloXamlPage">
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
Les ContentPage.Content
balises font partie de la syntaxe unique du code XAML. Au début, ils semblent être xml non valides, mais ils sont légaux. La période n’est pas un caractère spécial en XML.
Les ContentPage.Content
balises sont appelées balises d’élément de propriété. Content
est une propriété de ContentPage
, et est généralement définie sur une vue unique ou une disposition avec des vues enfants. Normalement, les propriétés deviennent des attributs en XAML, mais il serait difficile de définir un Content
attribut sur un objet complexe. Pour cette raison, la propriété est exprimée en tant qu’élément XML composé du nom de classe et du nom de propriété séparés par un point. À présent, la Content
propriété peut être définie entre les ContentPage.Content
balises, comme suit :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.HelloXamlPage"
Title="Hello XAML Page">
<ContentPage.Content>
<Label Text="Hello, XAML!"
VerticalOptions="Center"
HorizontalTextAlignment="Center"
Rotation="-15"
IsVisible="true"
FontSize="Large"
FontAttributes="Bold"
TextColor="Blue" />
</ContentPage.Content>
</ContentPage>
Notez également qu’un Title
attribut a été défini sur la balise racine.
À ce stade, la relation entre les classes, propriétés et XML doit être évidente : une Xamarin.Forms classe (par exemple ContentPage
) 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, apparaissent généralement sous forme d’attributs Label
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 Title
Text
propriétés sont de type , Rotation
est de type Double
String
, et IsVisible
(qui est true
par défaut et est défini ici uniquement pour l’illustration) est de type Boolean
.
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 qui Xamarin.Forms dérivent de TypeConverter
. Beaucoup sont des classes publiques, mais certains ne le sont pas. Pour ce fichier XAML particulier, plusieurs de ces classes jouent un rôle en arrière-plan :
LayoutOptionsConverter
pour laVerticalOptions
propriétéFontSizeConverter
pour laFontSize
propriétéColorTypeConverter
pour laTextColor
propriété
Ces convertisseurs régissent la syntaxe autorisée des paramètres de propriété.
Le ThicknessTypeConverter
peut gérer un, deux ou quatre nombres séparés par des virgules. Si un nombre est fourni, il s’applique aux quatre côtés. Avec deux nombres, le premier est de gauche et de droite, et le second est supérieur et inférieur. Quatre nombres sont dans l’ordre de gauche, de haut, de droite et de bas.
Il LayoutOptionsConverter
peut convertir les noms des champs statiques publics de la LayoutOptions
structure en valeurs de type LayoutOptions
.
Il FontSizeConverter
peut gérer un NamedSize
membre ou une taille de police numérique.
Accepte ColorTypeConverter
les noms des champs statiques publics de la Color
structure ou des valeurs RVB hexadécimales, avec ou sans canal alpha, précédés d’un signe numérique (#). Voici la syntaxe sans canal alpha :
TextColor="#rrggbb"
Chacune des petites lettres est un chiffre hexadécimal. Voici comment un canal alpha est inclus :
TextColor="#aarrggbb">
Pour le canal alpha, gardez à l’esprit que FF est entièrement opaque et 00 est entièrement transparent.
Deux autres formats vous permettent de spécifier un seul chiffre hexadécimal pour chaque canal :
TextColor="#rgb"
TextColor="#argb"
Dans ces cas, le chiffre est répété pour former la valeur. Par exemple, #CF3 est la couleur RVB CC-FF-33.
Navigation dans les pages
Lorsque vous exécutez le programme XamlSamples , celui-ci MainPage
s’affiche. Pour voir le nouveau HelloXamlPage
que vous pouvez définir comme nouvelle page de démarrage dans le fichier App.xaml.cs , ou accédez à la nouvelle page à partir de MainPage
.
Pour implémenter la navigation, commencez par modifier le code dans le constructeur App.xaml.cs afin qu’un NavigationPage
objet soit créé :
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
Dans le constructeur MainPage.xaml.cs , vous pouvez créer un gestionnaire d’événements simple Button
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;
}
La définition de la Content
propriété de la page remplace le paramètre de la Content
propriété dans le fichier XAML. Lorsque vous compilez et déployez la nouvelle version de ce programme, un bouton s’affiche à l’écran. Appuyez dessus pour accéder à HelloXamlPage
. Voici la page résultante sur iPhone, Android et UWP :
Vous pouvez revenir à MainPage
l’aide du < bouton Précédent sur iOS, en utilisant la flèche gauche en haut de la page ou en bas du téléphone sur Android, ou en utilisant la flèche gauche en haut de la page sur Windows 10.
N’hésitez pas à tester le code XAML de différentes façons d’afficher le Label
fichier . Si vous devez incorporer des caractères Unicode dans le texte, vous pouvez utiliser la syntaxe XML standard. Par exemple, pour placer le message d’accueil entre guillemets intelligents, utilisez :
<Label Text="“Hello, XAML!”" … />
Voici à quoi elle ressemble :
Interactions xaml et de code
L’exemple HelloXamlPage ne contient qu’un seul élément Label
de la page, mais c’est très inhabituel. La plupart des ContentPage
dérivés définissent la Content
propriété sur une disposition d’une certaine sorte, par exemple un StackLayout
. La Children
propriété du type StackLayout
est définie comme étant de type IList<View>
, mais il s’agit en fait d’un objet de type ElementCollection<View>
, et cette collection peut être remplie avec plusieurs vues ou autres dispositions. En XAML, ces relations parent-enfant sont établies avec une hiérarchie XML normale. Voici un fichier XAML pour une nouvelle page nommée XamlPlusCodePage :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.XamlPlusCodePage"
Title="XAML + Code Page">
<StackLayout>
<Slider VerticalOptions="CenterAndExpand" />
<Label Text="A simple Label"
Font="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Click Me!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Ce fichier XAML est syntactiquement complet, et voici ce à quoi il ressemble :
Toutefois, vous êtes susceptible de considérer ce programme comme étant fonctionnellement défectueux. Peut-être est-il Slider
censé faire Label
apparaître la valeur actuelle, et il Button
est probablement destiné à faire quelque chose au sein du programme.
Comme vous le verrez dans la partie 4. Principes de base de la liaison de données, le travail d’affichage d’une Slider
valeur à l’aide d’une Label
valeur peut être entièrement géré en XAML avec une liaison de données. Mais 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
lequel doit contenir des gestionnaires pour l’événement ValueChanged
de l’événement Slider
et l’événement Clicked
du Button
. Ajoutons-les :
namespace XamlSamples
{
public partial class XamlPlusCodePage
{
public XamlPlusCodePage()
{
InitializeComponent();
}
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
}
void OnButtonClicked(object sender, EventArgs args)
{
}
}
}
Ces gestionnaires d’événements n’ont pas besoin d’être publics.
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://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.XamlPlusCodePage"
Title="XAML + Code Page">
<StackLayout>
<Slider VerticalOptions="CenterAndExpand"
ValueChanged="OnSliderValueChanged" />
<Label Text="A simple Label"
Font="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Click Me!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
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é.
Si le gestionnaire de l’événement de l’événement ValueChanged
Slider
utilise la Label
valeur actuelle pour afficher la valeur actuelle, le gestionnaire doit référencer cet objet à partir du code. Le Label
nom doit être spécifié avec l’attribut x:Name
.
<Label x:Name="valueLabel"
Text="A simple Label"
Font="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
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é.
À présent, le ValueChanged
gestionnaire d’événements peut définir la Label
valeur pour afficher la nouvelle Slider
valeur. La nouvelle valeur est disponible à partir des arguments d’événement :
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
valueLabel.Text = args.NewValue.ToString("F3");
}
Ou bien, le gestionnaire peut obtenir l’objet Slider
qui génère cet événement à partir de l’argument sender
et obtenir la Value
propriété à partir de ceci :
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
valueLabel.Text = ((Slider)sender).Value.ToString("F3");
}
Lorsque vous exécutez le programme pour la première fois, la Label
valeur n’affiche pas la Slider
valeur, car l’événement ValueChanged
n’a pas encore été déclenché. Toutefois, toute manipulation des causes de l’affichage de Slider
la valeur :
Maintenant pour le Button
. Nous allons simuler une réponse à un Clicked
événement en affichant une alerte avec le Text
bouton. Le gestionnaire d’événements peut convertir l’argument sender
en toute sécurité 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 est définie comme async
étant parce que la DisplayAlert
méthode est asynchrone et doit être précédée de l’opérateur await
, qui retourne 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.
Vous avez vu qu’un objet défini en XAML peut déclencher un événement géré dans le fichier code-behind et que le fichier code-behind peut accéder à un objet défini en XAML à l’aide du nom affecté à celui-ci avec l’attribut x:Name
. Il s’agit des deux méthodes fondamentales que le code et XAML interagissent.
Des informations supplémentaires sur le fonctionnement du code XAML peuvent être recueillies en examinant le fichier XamlPlusCode.xaml.g.cs nouvellement généré, qui inclut désormais tout nom affecté à n’importe quel x:Name
attribut en tant que champ privé. Voici une version simplifiée de ce fichier :
public partial class XamlPlusCodePage : ContentPage {
private Label valueLabel;
private void InitializeComponent() {
this.LoadFromXaml(typeof(XamlPlusCodePage));
valueLabel = this.FindByName<Label>("valueLabel");
}
}
La déclaration de ce champ permet à la variable d’être utilisée librement n’importe où dans le XamlPlusCodePage
fichier de classe partielle sous votre juridiction. Au moment de l’exécution, le champ est affecté une fois que le code XAML a été analysé. Cela signifie que le valueLabel
champ est null
lorsque le XamlPlusCodePage
constructeur commence mais valide après InitializeComponent
l’appel.
Après InitializeComponent
avoir retourné le contrôle au constructeur, les visuels de la page ont été construits comme s’ils avaient été instanciés et initialisés dans le code. Le fichier XAML ne joue plus de rôle dans la classe. Vous pouvez manipuler ces objets sur la page de quelque manière que ce soit, par exemple, en ajoutant des vues à la StackLayout
page ou en définissant entièrement la Content
propriété de la page sur un autre élément. Vous pouvez « parcourir l’arborescence » en examinant la Content
propriété de la page et les éléments des Children
collections de dispositions. Vous pouvez définir des propriétés sur les vues consultées de cette façon ou leur attribuer dynamiquement des gestionnaires d’événements.
N’hésitez pas. Il s’agit de votre page, et XAML n’est qu’un outil pour générer son contenu.
Résumé
Avec cette introduction, vous avez vu comment un fichier XAML et un fichier de code contribuent à une définition de classe et comment les fichiers XAML et de code interagissent. Mais XAML a également ses propres fonctionnalités syntactiques uniques qui lui permettent d’être utilisé de manière très flexible. Vous pouvez commencer à les explorer dans la partie 2. Syntaxe XAML essentielle.