Udostępnij za pośrednictwem


Tworzenie rozszerzeń znaczników XAML

Przeglądaj przykład. Przeglądanie przykładu

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 z IMarkupExtension<Type>
  • ArrayExtension pochodzi z IMarkupExtension<Array>
  • DynamicResourceExtension pochodzi z IMarkupExtension<DynamicResource>
  • BindingExtension pochodzi z IMarkupExtension<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 , ProvideValuezawiera 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ą objectmetodę.

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 Hwartości , Si 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:

Pokaz kolorów HSL.

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 metodzie ProvideValue 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.