Erste Schritte mit XAML
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:
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 EigenschaftVerticalOptions
. Dieser Konverter wandelt die Namen von öffentlichen statischen Feldern derLayoutOptions
-Struktur in Werte des TypsLayoutOptions
um.ColorTypeConverter
für die EigenschaftTextColor
. Dieser Konverter wandelt die Namen von öffentlichen statischen Feldern der Colors-Klasse in hexadezimale RGB-Werte mit oder ohne Alphakanal um.
Seitennavigation
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
:
Ü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:
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:
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.