Erstellen von XAML-Markup-Erweiterungen
Auf Entwicklerebene ist eine .NET Multi-Platform App UI (.NET MAUI) XAML Markup-Erweiterung eine Klasse, die die Schnittstelle IMarkupExtension oder IMarkupExtension<T> implementiert. Es ist auch möglich, eigene XAML-Markup-Erweiterungen zu definieren, indem man von IMarkupExtension oder IMarkupExtension<T> ableitet. Verwenden Sie die generische Form, wenn die Markup-Erweiterung einen Wert eines bestimmten Typs erhält. Dies ist bei mehreren der .NET MAUI Markup-Erweiterungen der Fall:
TypeExtension
wird vonIMarkupExtension<Type>
abgeleitetArrayExtension
wird vonIMarkupExtension<Array>
abgeleitetDynamicResourceExtension
wird vonIMarkupExtension<DynamicResource>
abgeleitetBindingExtension
wird vonIMarkupExtension<BindingBase>
abgeleitet
Alle Klassen, die IMarkupExtension oder IMarkupExtension<T> implementieren, müssen entweder mit RequireServiceAttribute oder AcceptEmptyServiceProviderAttribute kommentiert werden. Weitere Informationen finden Sie unter Dienstanbieter.
Die beiden IMarkupExtension-Schnittstellen definieren jeweils nur eine Methode, die ProvideValue
genannt wird:
public interface IMarkupExtension
{
object ProvideValue(IServiceProvider serviceProvider);
}
public interface IMarkupExtension<out T> : IMarkupExtension
{
new T ProvideValue(IServiceProvider serviceProvider);
}
Da IMarkupExtension<T> von IMarkupExtension abgeleitet ist und das Schlüsselwort new
auf ProvideValue
enthält, enthält sie beide ProvideValue
Methoden.
Häufig definieren XAML-Markup-Erweiterungen Eigenschaften, die zum Rückgabewert beitragen, und die Methode ProvideValue
weist ein einzelnes Argument vom Typ IServiceProvider
auf. Weitere Informationen über Dienstanbieter finden Sie unter Dienstanbieter.
Erstellen einer Markup-Erweiterung
Die folgende XAML-Markup-Erweiterung zeigt, wie Sie Ihre eigene Markup-Erweiterung erstellen können. Sie ermöglicht es Ihnen, einen Color-Wert aus den Komponenten Farbton, Sättigung und Helligkeit zu konstruieren. Sie definiert vier Eigenschaften für die vier Komponenten der Farbe, einschließlich einer Alphakomponente, die auf 1 initialisiert wird. Die Klasse leitet sich von IMarkupExtension<Color>
ab, um einen Color Rückgabewert anzugeben:
public class HslColorExtension : IMarkupExtension<Color>
{
public float H { get; set; }
public float S { get; set; }
public float L { get; set; }
public float A { get; set; } = 1.0f;
public Color ProvideValue(IServiceProvider serviceProvider)
{
return Color.FromHsla(H, S, L, A);
}
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
{
return (this as IMarkupExtension<Color>).ProvideValue(serviceProvider);
}
}
[AcceptEmptyServiceProvider]
public class HslColorExtension : IMarkupExtension<Color>
{
public float H { get; set; }
public float S { get; set; }
public float L { get; set; }
public float A { get; set; } = 1.0f;
public Color ProvideValue(IServiceProvider serviceProvider)
{
return Color.FromHsla(H, S, L, A);
}
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
{
return (this as IMarkupExtension<Color>).ProvideValue(serviceProvider);
}
}
Diese Markup-Erweiterung ist mit AcceptEmptyServiceProviderAttribute gekennzeichnet, da sie keinen Dienst des Dienstanbieters verwendet. Weitere Informationen finden Sie unter Dienstanbieter.
Da IMarkupExtension<T> von IMarkupExtension abgeleitet ist, muss die Klasse zwei ProvideValue
-Methoden enthalten, eine, die ein Color zurückgibt, und eine, die ein object
zurückgibt, aber die zweite Methode kann die erste Methode aufrufen.
Verwenden einer Markup-Erweiterung
Die folgende XAML demonstriert eine Vielzahl von Ansätzen, die verwendet werden können, um die HslColorExtension
aufzurufen, um die Farbe für ein BoxView anzugeben:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MarkupExtensions"
x:Class="MarkupExtensions.HslColorDemoPage"
Title="HSL Color Demo">
<ContentPage.Resources>
<Style TargetType="BoxView">
<Setter Property="WidthRequest" Value="80" />
<Setter Property="HeightRequest" Value="80" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
</Style>
</ContentPage.Resources>
<StackLayout>
<BoxView>
<BoxView.Color>
<local:HslColorExtension H="0" S="1" L="0.5" A="1" />
</BoxView.Color>
</BoxView>
<BoxView>
<BoxView.Color>
<local:HslColor H="0.33" S="1" L="0.5" />
</BoxView.Color>
</BoxView>
<BoxView Color="{local:HslColorExtension H=0.67, S=1, L=0.5}" />
<BoxView Color="{local:HslColor H=0, S=0, L=0.5}" />
<BoxView Color="{local:HslColor A=0.5}" />
</StackLayout>
</ContentPage>
Wenn HslColorExtension
in diesem Beispiel ein XML-Tag ist, werden die vier Eigenschaften als Attribute festgelegt, aber wenn es zwischen geschweiften Klammern steht, werden die vier Eigenschaften durch Kommas ohne Anführungszeichen getrennt. Die Standardwerte für H
, S
und L
sind 0, und der Standardwert von A
ist 1, sodass diese Eigenschaften weggelassen werden können, wenn sie auf Standardwerte gesetzt werden sollen. Das letzte Beispiel zeigt ein Beispiel, bei dem die Helligkeit 0 ist, was normalerweise Schwarz ergibt, aber der Alphakanal 0,5 ist, sodass es halb transparent ist und vor dem weißen Hintergrund der Seite grau erscheint:
Dienstanbieter
Durch die Verwendung des IServiceProvider
-Arguments für ProvideValue
können XAML-Markup-Erweiterungen Zugriff auf Daten über die XAML-Datei erhalten, in der sie verwendet werden. Mit dem Dienst IProvideValueTarget
können Sie zum Beispiel Daten über das Objekt abrufen, auf das die Markup-Erweiterung angewendet wird:
IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
Die IProvideValueTarget
-Schnittstelle definiert zwei Eigenschaften, TargetObject
und TargetProperty
. Wenn diese Information in der Klasse HslColorExtension
erhalten wird, ist TargetObject
die BoxView und TargetProperty
die Color
Eigenschaft von BoxView. Dies ist die Eigenschaft, für die die XAML-Markup-Erweiterung festgelegt wurde.
Alle Klassen, die IMarkupExtension oder IMarkupExtension<T> implementieren, müssen entweder mit RequireServiceAttribute oder AcceptEmptyServiceProviderAttribute kommentiert werden:
Für jede Verwendung von
serviceProvider.GetService(typeof(T))
in derProvideValue
-Methode sollte die Klasse mit[RequireService(typeof(T))]
kommentiert werden:[RequireService([typeof(IReferenceProvider), typeof(IProvideValueTarget)])] public class MyMarkupExtension : IMarkupExtension { public object ProvideValue(IServiceProvider serviceProvider) { ... var referenceProvider = serviceProvider.GetService<IReferenceProvider>(); var valueProvider = serviceProvider.GetService<IProvideValueTarget>() as IProvideParentValues ?? throw new ArgumentException("serviceProvider does not provide an IProvideValueTarget"); ... } }
Wenn die Markuperweiterung keinen Dienst des Dienstanbieters verwendet, sollte die Klasse mit
[AcceptEmptyServiceProvider]
kommentiert werden.
Diese Anmerkungen sind aufgrund einer XAML-Compileroptimierung erforderlich, die die Generierung von effizienterem Code ermöglicht, wodurch die App-Größe reduziert und die Laufzeitleistung verbessert wird.