Partager via


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 les 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 :

Fenêtre Nouvelle solution

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 :

Nouvelle fenêtre projet

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 :

Boîte de dialogue Nouvelle application

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 case activée ce que ces URI pointent. 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 deuxième déclaration d’espace de noms définit un préfixe de x. Cela 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 x préfixe 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 MainPage classe dans l’espace XamlSamples de noms. Cela signifie que ce fichier XAML définit une nouvelle classe nommée MainPage dans l’espace XamlSamples de noms qui dérive de ContentPagela balise dans laquelle l’attribut x:Class apparaît.

L’attribut x:Class peut uniquement apparaître 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 InitializeComponentensuite 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 :

Affichage par défaut Xamarin.Forms

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 :

Boîte de dialogue Ajouter un nouvel élément

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 ) Labelapparaî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 LabelXML.

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 TitleText propriétés sont de type , Rotation est de type DoubleString, et IsVisible (qui est true par défaut et est défini ici uniquement pour l’illustration) est de type Boolean.

La HorizontalTextAlignment propriété est de type TextAlignment, qui est une énumération. Pour une propriété de n’importe quel type d’énumération, tout ce que vous devez fournir est un nom de membre.

Toutefois, pour les propriétés de types plus complexes, les 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 la VerticalOptions propriété
  • FontSizeConverter pour la FontSize propriété
  • ColorTypeConverter pour la TextColor 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.

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 i Téléphone, Android et UWP :

Texte de l’étiquette pivotée

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 Labelfichier . 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="&#x201C;Hello, XAML!&#x201D;" … />

Voici ce à quoi il ressemble :

Texte d’étiquette pivoté avec des caractères Unicode

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 :

Plusieurs contrôles sur une page

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. Même si, la gestion du clic nécessite certainement du Button 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 et Button les Slider balises doivent inclure des attributs pour les ValueChanged gestionnaires et Clicked événements 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 ValueChangedSlider 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 x préfixe de l’attribut x:Name indique que cet attribut est intrinsèque au code XAML.

Le nom que vous attribuez à l’attribut x:Name a les 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 :

Valeur du curseur affichée

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é que cette méthode obtient le déclenchement de l’événement Button à 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 StackLayoutpage 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.