Tworzenie rozszerzeń znaczników XAML
Na poziomie dewelopera rozszerzenie znaczników XAML (.NET MAUI) aplikacji wieloplatformowej platformy .NET jest klasą implementającą IMarkupExtension interfejs lub IMarkupExtension<T> . Istnieje również możliwość zdefiniowania własnych niestandardowych rozszerzeń znaczników XAML przez wyprowadzenie z lub IMarkupExtension IMarkupExtension<T>. Użyj formularza ogólnego, jeśli rozszerzenie znaczników uzyskuje wartość określonego typu. Jest to przypadek z kilkoma rozszerzeniami znaczników MAUI platformy .NET:
TypeExtension
pochodzi zIMarkupExtension<Type>
ArrayExtension
pochodzi zIMarkupExtension<Array>
DynamicResourceExtension
pochodzi zIMarkupExtension<DynamicResource>
BindingExtension
pochodzi zIMarkupExtension<BindingBase>
Wszystkie klasy implementujące IMarkupExtension lub IMarkupExtension<T> muszą być oznaczone adnotacjami za RequireServiceAttribute pomocą elementu lub AcceptEmptyServiceProviderAttribute. Aby uzyskać więcej informacji, zobacz Dostawcy usług.
IMarkupExtension Dwa interfejsy definiują tylko jedną metodę o nazwie ProvideValue
:
public interface IMarkupExtension
{
object ProvideValue(IServiceProvider serviceProvider);
}
public interface IMarkupExtension<out T> : IMarkupExtension
{
new T ProvideValue(IServiceProvider serviceProvider);
}
Ponieważ IMarkupExtension<T> pochodzi z IMarkupExtension i zawiera new
słowo kluczowe w , ProvideValue
zawiera obie ProvideValue
metody.
Często rozszerzenia znaczników XAML definiują właściwości, które przyczyniają się do zwracanej wartości, a ProvideValue
metoda ma jeden argument typu IServiceProvider
. Aby uzyskać więcej informacji na temat dostawców usług, zobacz Dostawcy usług.
Tworzenie rozszerzenia znaczników
Poniższe rozszerzenie znaczników XAML pokazuje, jak utworzyć własne rozszerzenie znaczników. Umożliwia utworzenie Color wartości przy użyciu składników odcieni, nasycenia i jasności. Definiuje cztery właściwości dla czterech składników koloru, w tym składnik alfa zainicjowany do 1. Klasa pochodzi z IMarkupExtension<Color>
, aby wskazać wartość zwracaną Color :
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);
}
}
To rozszerzenie znaczników jest oznaczone adnotacją, AcceptEmptyServiceProviderAttribute ponieważ nie używa usługi od dostawcy usług. Aby uzyskać więcej informacji, zobacz Dostawcy usług.
Ponieważ IMarkupExtension<T> pochodzi z IMarkupExtensionklasy , klasa musi zawierać dwie ProvideValue
metody, jedna, która zwraca wartość Color i drugą, która zwraca element , ale druga metoda może wywołać pierwszą object
metodę.
Korzystanie z rozszerzenia znaczników
Poniższy kod XAML demonstruje różne podejścia, których można użyć do wywołania HslColorExtension
elementu w celu określenia koloru elementu BoxView:
<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>
W tym przykładzie, gdy HslColorExtension
jest tagiem XML cztery właściwości są ustawiane jako atrybuty, ale gdy pojawia się między nawiasami klamrowymi, cztery właściwości są oddzielone przecinkami bez znaków cudzysłowu. Wartości domyślne dla H
wartości , S
i L
to 0, a wartość A
domyślna to 1, więc te właściwości można pominąć, jeśli chcesz, aby zostały ustawione na wartości domyślne. W ostatnim przykładzie pokazano przykład, w którym jasność wynosi 0, co zwykle powoduje kolor, ale kanał alfa wynosi 0,5, więc jest pół przezroczysty i jest szary na białym tle strony:
Dostawcy usług
Używając argumentu do IServiceProvider
ProvideValue
, rozszerzenia znaczników XAML mogą uzyskać dostęp do danych dotyczących pliku XAML, w którym są używane. Na przykład usługa umożliwia pobieranie danych o obiekcie, IProvideValueTarget
do którego jest stosowane rozszerzenie znaczników:
IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
Interfejs IProvideValueTarget
definiuje dwie właściwości i TargetObject
TargetProperty
. Gdy te informacje są uzyskiwane w HslColorExtension
klasie, TargetObject
jest właściwością BoxView i TargetProperty
Color
.BoxView Jest to właściwość, na której ustawiono rozszerzenie znaczników XAML.
Wszystkie klasy implementujące IMarkupExtension lub IMarkupExtension<T> muszą być oznaczone adnotacjami za pomocą elementu RequireServiceAttribute lub AcceptEmptyServiceProviderAttribute:
Dla każdego użycia
serviceProvider.GetService(typeof(T))
metody w metodzieProvideValue
klasa powinna być oznaczona adnotacjami :[RequireService(typeof(T))]
[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"); ... } }
Jeśli rozszerzenie znaczników nie używa żadnej usługi od dostawcy usług, klasa powinna być oznaczona adnotacją .
[AcceptEmptyServiceProvider]
Te adnotacje są wymagane ze względu na optymalizację kompilatora XAML, która umożliwia generowanie bardziej wydajnego kodu, co pomaga zmniejszyć rozmiar aplikacji i zwiększyć wydajność środowiska uruchomieniowego.