Freigeben über


Erste Schritte mit XAML

Beispiel durchsuchen.Durchsuchen Sie das Beispiel

In einer .NET Multi-Platform App UI (.NET MAUI) wird XAML meist dazu verwendet, den visuellen Inhalt einer Seite zu definieren und arbeitet mit einer C#-CodeBehind-Datei zusammen. Die CodeBehind-Datei bietet Code-Unterstützung für das Markup. Zusammen ergeben diese beiden Dateien eine neue Klassendefinition, die untergeordnete Elemente und die Initialisierung von Eigenschaften enthält. Innerhalb der XAML-Datei werden Klassen und Eigenschaften mit XML-Elementen und -Attributen referenziert, und es werden Verknüpfungen zwischen dem Markup und dem Code hergestellt.

Aufbau einer XAML-Datei

Eine neue .NET MAUI-App enthält drei XAML-Dateien und die zugehörigen CodeBehind-Dateien:

Screenshot der Struktur einer neuen .NET MAUI-App.

Das erste Dateipaar ist App.xaml, eine XAML-Datei, und App.xaml.cs, eine C#- CodeBehind-Datei, die mit der XAML-Datei verknüpft ist. Sowohl App.xaml als auch App.xaml.cs tragen zu einer Klasse namens App bei, die sich von Application ableitet. Das zweite Dateipaar ist AppShell.xaml und AppShell.xaml.cs, die zu einer Klasse namens AppShell beitragen, die von Shell abgeleitet ist. Die meisten anderen Klassen mit XAML-Dateien tragen zu einer Klasse bei, die von ContentPage abgeleitet ist, und definieren die Benutzeroberfläche einer Seite. Dies gilt für die Dateien MainPage.xaml und MainPage.xaml.cs.

Die Datei MainPage.xaml hat die folgende Struktur:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyMauiApp.MainPage">
    ...
</ContentPage>

Die beiden XML-Namespace-Deklarationen (xmlns) verweisen auf URIs auf microsoft.com. Diese URIs haben jedoch keinen Inhalt und dienen im Wesentlichen als Versionsbezeichner.

Die erste XML-Namespace-Deklaration bedeutet, dass in der XAML-Datei definierte Tags ohne Präfix auf Klassen in .NET MAUI verweisen, z. B. ContentPage. Die zweite Namespace-Deklaration definiert ein Präfix von x. Dies wird für mehrere Elemente und Attribute verwendet, die XAML-spezifisch sind und die von anderen Implementierungen von XAML unterstützt werden. Diese Elemente und Attribute unterscheiden sich jedoch geringfügig, je nachdem, welches Jahr in den URI eingebettet ist. .NET MAUI unterstützt die 2009 XAML-Spezifikation.

Am Ende des ersten Tags wird das Präfix x für ein Attribut namens Class verwendet. Da die Verwendung dieses Präfixes x für den XAML-Namespace praktisch universell ist, werden XAML-Attribute wie Class fast immer als x:Class bezeichnet. Das x:Class-Attribut spezifiziert einen voll qualifizierten .NET-Klassennamen: die MainPage-Klasse im MyMauiApp-Namespace. Das bedeutet, dass diese XAML-Datei eine neue Klasse mit dem Namen MainPage im Namespace MyMauiApp definiert, die von ContentPage (dem Tag, in dem das Attribut x:Class erscheint) abgeleitet ist.

Das x:Class-Attribut kann nur im Root-Element einer XAML-Datei erscheinen, um eine abgeleitete C#-Klasse zu definieren. Dies ist die einzige neue Klasse, die in der XAML-Datei definiert ist. Alles andere, was in einer XAML-Datei erscheint, wird stattdessen einfach aus vorhandenen Klassen erstellt und initialisiert.

Die Datei MainPage.xaml.cs sieht ähnlich aus wie diese:

namespace MyMauiApp;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }
}

Die Klasse MainPage leitet sich von ContentPage ab und ist eine partielle Klassendefinition.

Wenn Visual Studio das Projekt erstellt, erzeugt ein Quellcodegenerator neuen C#-Quellcode, der die Definition der InitializeComponent-Methode enthält, die vom MainPage-Konstruktor aufgerufen wird, und fügt sie dem Kompilierungsobjekt hinzu.

Zur Laufzeit startet der Code in der Klasse MauiProgram die Anwendung und führt den App-Klassenkonstruktor aus, der AppShell instanziiert. Die Klasse AppShell erstellt die erste Seite der anzuzeigenden App, die MainPage ist. Der MainPage-Konstruktor ruft InitializeComponent auf, der alle in der XAML-Datei definierten Objekte initialisiert, sie alle in übergeordneten und untergeordneten Beziehungen miteinander verbindet, im Code definierte Ereignishandler an die in der XAML-Datei festgelegten Ereignisse anhängt und der daraus resultierenden Baumstruktur von Objekten als Inhalt der Seite festlegt.

Hinweis

Die Klasse AppShell verwendet die .NET MAUI Shell, um die erste anzuzeigende Seite der App festzulegen. Shell würde jedoch den Rahmen dieser Einführung in XAML sprengen. Weitere Informationen finden Sie unter .NET MAUI Shell.

Seiteninhalt festlegen

Eine ContentPage sollte ein einzelnes untergeordnetes Element enthalten, das eine Ansicht oder ein Layout mit untergeordneten Ansichten sein kann. Das untergeordnete Element der ContentPage wird automatisch als Wert der Eigenschaft ContentPage.Content festgelegt.

Das folgende Beispiel zeigt eine ContentPage, die ein Label enthält:

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

Aus dem obigen Beispiel sollte die Beziehung zwischen Klassen, Eigenschaften und XML ersichtlich sein. Eine .NET MAUI-Klasse (wie ContentPage oder Label) erscheint in der XAML-Datei als XML-Element. Eigenschaften dieser Klasse – einschließlich Title auf ContentPage und sieben Eigenschaften von Label – erscheinen normalerweise als XML-Attribute.

Es gibt viele Tastenkombinationen, um die Werte dieser Eigenschaften festzulegen. Einige Eigenschaften sind grundlegende Datentypen. Zum Beispiel sind die Eigenschaften Title und Text vom Typ string, und Rotation ist vom Typ double. Die Eigenschaft HorizontalTextAlignment ist vom Typ TextAlignment, bei dem es sich um eine Enumeration handelt. Für eine Eigenschaft eines Enumerationstyps ist nur die Angabe eines Mitgliedsnamens erforderlich.

Für Eigenschaften komplexerer Typen werden jedoch Konverter zur Analyse von XAML verwendet. Es handelt sich dabei um Klassen in .NET MAUI, die von TypeConverter abgeleitet sind. Für das obige Beispiel werden automatisch mehrere .NET MAUI-Konverter angewendet, um die Zeichenfolgenwerte in den richtigen Typ umzuwandeln:

  • LayoutOptionsConverter für die Eigenschaft VerticalOptions. Dieser Konverter wandelt die Namen von öffentlichen statischen Feldern der LayoutOptions-Struktur in Werte des Typs LayoutOptions um.
  • ColorTypeConverter für die Eigenschaft TextColor. Dieser Konverter wandelt die Namen von öffentlichen statischen Feldern der Colors-Klasse in hexadezimale RGB-Werte mit oder ohne Alphakanal um.

Wenn Sie eine .NET MAUI-App ausführen, wird in der Regel die MainPage angezeigt. Wenn Sie eine andere Seite sehen möchten, können Sie diese entweder in der Datei AppShell.xaml als neue Startseite festlegen oder von MainPage aus zur neuen Seite navigieren.

Um die Navigation zu implementieren, können Sie im Konstruktor MainPage.xaml.cs eine einfache Button erstellen und den Ereignishandler verwenden, um zu HelloXamlPage zu navigieren:

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;
}

Wenn Sie die neue Version dieser App kompilieren und bereitstellen, erscheint eine Schaltfläche auf dem Bildschirm. Durch Drücken dieser Schaltfläche gelangen Sie zu HelloXamlPage:

Screenshot des gedrehten Beschriftungstexts.

Über die Navigationsleiste, die auf jeder Plattform erscheint, gelangen Sie zurück zur MainPage.

Hinweis

Eine Alternative zu diesem Navigationsmodell ist die Verwendung der .NET MAUI Shell. Weitere Informationen finden Sie unter Übersicht über .NET MAUI Shell.

Interaktionen zwischen XAML und Code

Das untergeordnete Element der meisten ContentPage-Derivate ist ein Layout, z. B. ein StackLayout oder ein Grid, und das Layout kann mehrere untergeordnete Elemente enthalten. In XAML werden die Beziehungen zwischen über- und untergeordneten Elementen über die normale XML-Hierarchie hergestellt:

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

Diese XAML-Datei ist syntaktisch vollständig und erzeugt die folgende Benutzeroberfläche:

Screenshot mehrerer Steuerelemente auf einer Seite.

Während Sie jedoch mit Slider und Button interagieren können, wird die Benutzeroberfläche nicht aktualisiert. Der Slider sollte das Label zur Anzeige des aktuellen Wertes veranlassen und die Button sollte etwas bewirken.

Die Anzeige eines Slider-Wertes mit einem Label kann vollständig in XAML mit einer Datenbindung erreicht werden. Es ist jedoch hilfreich, sich zuerst die Lösung des Codes anzusehen. Der Klick auf Button erfordert jedoch definitiv Code. Das bedeutet, dass die Code-Behind-Datei für XamlPlusCodePage Handler für das Ereignis ValueChanged von Slider und das Ereignis Clicked von Button enthalten muss:

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");
        }
    }
}

In der XAML-Datei müssen die Tags Slider und Button Attribute für die Ereignisse ValueChanged und Clicked enthalten, die auf diese Handler verweisen:

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

Beachten Sie, dass die Zuweisung eines Handlers zu einem Ereignis dieselbe Syntax hat wie die Zuweisung eines Wertes zu einer Eigenschaft. Damit der Ereignishandler ValueChanged des Ereignisses Slider das Label zur Anzeige des aktuellen Werts verwenden kann, muss der Handler dieses Objekt im Code referenzieren. Dazu benötigt das Label einen Namen, der mit dem Attribut x:Name angegeben wird. Das Präfix x des Attributs x:Name zeigt an, dass es sich bei diesem Attribut um ein XAML-eigenes Attribut handelt. Für den Namen, den Sie dem Attribut x:Name zuweisen, gelten dieselben Regeln wie für C#-Variablennamen. Es muss beispielsweise mit einem Buchstaben oder einem Unterstrich beginnen und darf keine Leerzeichen enthalten.

Der Ereignishandler ValueChanged kann nun das Label so einstellen, dass es den neuen Slider-Wert anzeigt, der in den Ereignisargumenten verfügbar ist:

void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
    valueLabel.Text = args.NewValue.ToString("F3");
}

Alternativ kann der Handler das Slider-Objekt, das dieses Ereignis erzeugt, aus dem sender-Argument abrufen und die Eigenschaft Value von diesem abrufen:

void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
    valueLabel.Text = ((Slider)sender).Value.ToString("F3");
}

Das Ergebnis ist, dass jede Manipulation des Slider dazu führt, dass sein Wert in Label angezeigt wird:

Screenshot mehrerer Steuerelemente auf einer Seite, wobei der Schiebereglerwert angezeigt wird.

Im obigen Beispiel simuliert die Button eine Reaktion auf ein Clicked-Ereignis, indem sie eine Meldung mit dem Text der Schaltfläche anzeigt. Daher kann der Ereignisbehandler das sender-Argument in eine Button umwandeln und dann auf dessen Eigenschaften zugreifen:

async void OnButtonClicked(object sender, EventArgs args)
{
    Button button = (Button)sender;
    await DisplayAlert("Clicked!", "The button labeled '" + button.Text + "' has been clicked", "OK");
}

Die OnButtonClicked-Methode ist als async definiert, weil die DisplayAlert-Methode asynchron ist und mit dem Operator await gestartet werden sollte, der zurückgibt, wann die Methode beendet ist. Da diese Methode die Button, die das Ereignis auslöst, aus dem sender-Argument bezieht, kann derselbe Handler für mehrere Schaltflächen verwendet werden.

Nächste Schritte

XAML ist hauptsächlich für die Erstellung und Initialisierung von Objekten gedacht. Oft müssen jedoch Eigenschaften für komplexe Objekte festgelegt werden, die sich nicht einfach als XML-Strings darstellen lassen, und manchmal müssen Eigenschaften, die von einer Klasse definiert wurden, für eine untergeordnete Klasse festgelegt werden. Diese beiden Anforderungen erfordern die wesentlichen XAML-Syntaxfeatures von Eigenschaftselementen und angefügten Eigenschaften.