XAML-Markuperweiterungen

Abgeschlossen

Ein Großteil Ihrer XAML-Definition wird zur Kompilierzeit geklärt sein. Häufig wissen Sie, wo Elemente positioniert werden sollten, welche Farben und Schriftarten verwendet werden und welchen Literal werten Eigenschaften zugewiesen werden sollten.

Mitunter müssen Sie einen Eigenschaftswert auf einen Wert festlegen, der zur Kompilierzeit nicht bestimmt werden kann. Diese Werte werden erst bekannt, wenn das Programm ausgeführt wird. In diesen Situationen können Sie ein Objekt erstellen, das zur Laufzeit einen Wert für XAML bereitstellt. XAML unterstützt zu diesem Zweck Markuperweiterungen.

In dieser Lerneinheit erfahren Sie, wie Sie Markuperweiterungen erstellen und verwenden.

Was ist eine Markuperweiterung?

Eine Markuperweiterung ist eine Klasse, die Sie in XAML für den Zugriff auf Laufzeitwerte benötigen. Angenommen, Sie haben in der XAML-Benutzeroberfläche viele Bezeichnungen definiert und möchten die Eigenschaft FontSize in der gesamten App auf ein und denselben Wert festlegen, um sicherzustellen, dass der Stil aller Bezeichnungen konsistent ist. Sie können die Eigenschaft FontSize mithilfe von XAML festlegen, wie im folgenden Beispiel gezeigt:

<Label Text="Hello, World!"
            Grid.Row="0"
            SemanticProperties.HeadingLevel="Level1"
            FontSize="28"
            HorizontalOptions="CenterAndExpand"/>

Sie können diese Einstellung für jede Bezeichnung wiederholen, aber was ist, wenn Sie diesen Wert später ändern möchten? Sie müssen nach jeder Instanz dieser Eigenschaft suchen und die Änderung vornehmen. Angenommen, Sie wissen nicht, welchen Wert Sie verwenden sollten. Möglicherweise wird er zur Laufzeit auf der Grundlage von Geräteausrichtung, Bildschirmauflösung oder anderen Faktoren berechnet. In diesen Fällen benötigen Sie etwas Anspruchsvolleres als ein hartcodiertes Literal. Hier ist eine Markuperweiterung nützlich. Markuperweiterungen ermöglichen Flexibilität, wie Sie einen Wert abrufen, der in XAML verwendet wird.

Erstellen einer Markuperweiterung

Eine Markuperweiterung ist eine Klasse, die die Schnittstelle Microsoft.Maui.Controls.Xaml.IMarkupExtension implementiert. Diese Schnittstelle definiert eine Methode namens ProvideValue mit der folgenden Signatur:

public object ProvideValue(IServiceProvider serviceProvider)
{
    ...
}

Zweck dieser Methode ist die Bereitstellung eines Werts für das XAML-Markup. Beachten Sie, dass der Rückgabetyp objectlautet. Der Wert kann also einen beliebigen Typ aufweisen, solange er für die Umgebung geeignet ist, in der er verwendet wird. Beispielsweise sollte der Rückgabetyp in einer Markuperweiterung, die einen Schriftgrad berechnet und zurückgibt, double lauten.

Der Parameter serviceProvider enthält Kontextinformationen dazu, an welchen Stellen im XAML-Code die Markuperweiterung verwendet wird. Er gibt unter anderem das Steuerelement an, auf das die Erweiterung angewendet wird.

Sie können die Markuperweiterung für die Eigenschaft FontSize einfach halten. Im folgenden Beispiel macht die Klasse MainPage ein double-Feld mit dem Namen MyFontSize verfügbar. Die Klasse GlobalFontSizeExtension implementiert die Schnittstelle IMarkupExtension, und die Methode ProvideValue gibt den Wert der Variable MyFontSize zurück:

namespace MyMauiApp;

public partial class MainPage : ContentPage
{
    public const double MyFontSize = 28;

    public MainPage()
    {
        InitializeComponent();
        ...
    }
    ...
}

public class GlobalFontSizeExtension : IMarkupExtension
{
    public object ProvideValue(IServiceProvider serviceProvider)
    {
        return MainPage.MyFontSize;
    }
}

Hinweis

Das Feld MyFontSize muss ein static-Element der Klasse MainPage sein, damit in der Methode ProvideValue entsprechend darauf verwiesen werden kann. Es hat sich bewährt, dass die Variable in diesem Fall auch eine Konstante ist. Ein const-Wert ist static.

Die Methode ProvideValue kann je nach Ausrichtung und Formfaktor des Geräts auch Anpassungen am zurückgegebenen Wert vornehmen.

Anwenden der Markuperweiterung auf ein Steuerelement in XAML

Wenn Sie die Markuperweiterung in Ihrem XAML-Code verwenden möchten, fügen Sie den Namespace, der die Klasse GlobalFontSizeExtension enthält, der Liste der Namespaces im Tag ContentPage hinzu. Im folgenden Beispiel erhält dieser Namespace den Alias mycode:

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

Sie können die Markuperweiterung verwenden, um die Eigenschaft FontSize auf diese Weise festzulegen. Beachten Sie, dass eine Markuperweiterung gemäß Konvention das Suffix Extension im Namen enthält. XAML erkennt dieses Suffix, und Sie müssen es nicht einschließen, wenn Sie die Erweiterung über Ihren XAML-Code aufrufen. Im folgenden Beispiel wird auf die Klasse GlobalFontSizeExtension einfach als GlobalFontSize verwiesen:

<Label Text="Hello, World!"
            Grid.Row="0"
            SemanticProperties.HeadingLevel="Level1"
            FontSize="{mycode:GlobalFontSize}"
            HorizontalOptions="CenterAndExpand"/>

Sie können dieselbe Markuperweiterung im gesamten XAML-Code für jedes Steuerelement anwenden, für das der Schriftgrad angegeben werden muss. Wenn Sie den Schriftgrad später ändern möchten, müssen Sie nur die Definition der Variablen MyFontSize in der Klasse MainPage ändern.

Die StaticExtension-Klasse

So nützlich die Markuperweiterung GlobalFontSize auch ist – es ist unwahrscheinlich, dass Sie jemals eine solche Erweiterung erstellen. Der Grund dafür ist einfach. .NET MAUI bietet bereits eine allgemeinere Erweiterung, mit der Sie auf beliebige statische Werte in Ihrem Code verweisen können. Diese Erweiterung heißt StaticExtension oder kurz Static. Der folgende Code zeigt die Grundstruktur dieser Erweiterungsklasse:

[ContentProperty ("Member")]
public class StaticExtension : IMarkupExtension
{
    public string Member {get; set;}
    public object ProvideValue (IServiceProvider serviceProvider)
    {
        ...
    }
}

Hinweis

Benutzerdefinierte Markuperweiterungen sind dafür konzipiert, dass Sie nicht nur einfache statische Fälle, sondern auch komplexere Situationen verarbeiten können. Ein Beispiel: Möglicherweise müssen Sie den Schriftgrad basierend auf dem Geräteformfaktor dynamisch ändern.

Wenn Sie diese Klasse in Ihrem XAML-Code verwenden, geben Sie den Namen der statischen Variablen an, auf die Sie in der Eigenschaft Member verweisen möchten. Die Methode ProvideValue gibt dann den Wert in dieser Variablen zurück. Das folgende Beispiel veranschaulicht ihre Verwendung:

<Label Text="Hello, World!"
            Grid.Row="0"
            SemanticProperties.HeadingLevel="Level1"
            FontSize="{x:Static Member=mycode:MainPage.MyFontSize}"
            HorizontalOptions="CenterAndExpand"/>

.NET MAUI stellt eine Reihe weiterer Markuperweiterungsklassen bereit, die Sie für Szenarien wie Datenbindung, das Verweisen auf dynamische Ressourcen und Stile sowie die Verarbeitung von Datenarrays verwenden können.

Überprüfung der Kenntnisse

1.

Mit welcher Markuperweiterung können Sie eine XAML-Eigenschaft auf einen statischen Wert festlegen, der in einer CodeBehind-Klasse definiert ist?

2.

Welche Schnittstelle verwenden Sie zum Erstellen einer benutzerdefinierten Markuperweiterung?