Sdílet prostřednictvím


Vytváření rozšíření značek XAML

Na programové úrovni je rozšíření značek XAML třída, která implementuje IMarkupExtension nebo IMarkupExtension<T> rozhraní. Zdrojový kód standardních rozšíření značek popsaných níže můžete prozkoumat v adresáři Xamarin.Forms MarkupExtensions úložiště GitHub.

Je také možné definovat vlastní rozšíření značek XAML odvozením nebo IMarkupExtension IMarkupExtension<T>. Obecný formulář použijte, pokud rozšíření značek získá hodnotu určitého typu. Toto je případ s několika Xamarin.Forms rozšířeními značek:

  • TypeExtension odvozuje z IMarkupExtension<Type>
  • ArrayExtension odvozuje z IMarkupExtension<Array>
  • DynamicResourceExtension odvozuje z IMarkupExtension<DynamicResource>
  • BindingExtension odvozuje z IMarkupExtension<BindingBase>
  • ConstraintExpression odvozuje z IMarkupExtension<Constraint>

IMarkupExtension Obě rozhraní definují pouze jednu metodu s názvem ProvideValue:

public interface IMarkupExtension
{
    object ProvideValue(IServiceProvider serviceProvider);
}

public interface IMarkupExtension<out T> : IMarkupExtension
{
    new T ProvideValue(IServiceProvider serviceProvider);
}

Vzhledem k tomu, IMarkupExtension<T> že je odvozeno od IMarkupExtension klíčového slova a obsahuje klíčové new slovo on ProvideValue, obsahuje obě ProvideValue metody.

Rozšíření značek XAML velmi často definují vlastnosti, které přispívají k návratové hodnotě. (Zjevná výjimka je NullExtension, v níž ProvideValue se jednoduše vrátí null.) Metoda ProvideValue má jeden argument typu IServiceProvider , který bude popsán dále v tomto článku.

Rozšíření značek pro určení barvy

Následující rozšíření značek XAML umožňuje vytvořit Color hodnotu pomocí komponent odstínu, sytosti a světelnosti. Definuje čtyři vlastnosti pro čtyři součásti barvy, včetně alfa komponenty inicializované na hodnotu 1. Třída je odvozena od IMarkupExtension<Color> označení návratové Color hodnoty:

public class HslColorExtension : IMarkupExtension<Color>
{
    public double H { set; get; }

    public double S { set; get; }

    public double L { set; get; }

    public double A { set; get; } = 1.0;

    public Color ProvideValue(IServiceProvider serviceProvider)
    {
        return Color.FromHsla(H, S, L, A);
    }

    object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
    {
        return (this as IMarkupExtension<Color>).ProvideValue(serviceProvider);
    }
}

Vzhledem k tomu IMarkupExtension<T> , odvozuje z IMarkupExtension, třída musí obsahovat dvě ProvideValue metody, jeden, který vrací Color a druhý, který vrací object, ale druhá metoda může jednoduše volat první metodu.

Stránka Ukázka barvy HSL ukazuje různé způsoby, jak HslColorExtension se může zobrazit v souboru XAML a určit barvu pro BoxView:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MarkupExtensions"
             x:Class="MarkupExtensions.HslColorDemoPage"
             Title="HSL Color Demo">

    <ContentPage.Resources>
        <ResourceDictionary>
            <Style TargetType="BoxView">
                <Setter Property="WidthRequest" Value="80" />
                <Setter Property="HeightRequest" Value="80" />
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
            </Style>
        </ResourceDictionary>
    </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>

Všimněte si, že když HslColorExtension je značka XML, jsou čtyři vlastnosti nastaveny jako atributy, ale když se zobrazí mezi složenými složenými závorkami, jsou čtyři vlastnosti odděleny čárkami bez uvozovek. Výchozí hodnoty pro H, a jsou L 0 a výchozí hodnota A je 1, takže tyto vlastnosti lze vynechat, pokud je chcete nastavit Sna výchozí hodnoty. Poslední příklad ukazuje příklad, ve kterém je světelnost 0, což obvykle vede k černému, ale alfa kanál je 0,5, takže je polovina průhledná a zobrazuje se šedá na bílém pozadí stránky:

Ukázka barvy HSL

Rozšíření značek pro přístup k rastrovým obrázkům

Argumentem ProvideValue je objekt, který implementuje IServiceProvider rozhraní, které je definováno v oboru názvů .NET System . Toto rozhraní má jeden člen, metodu pojmenovanou GetService argumentem Type .

Níže ImageResourceExtension uvedená třída ukazuje jedno možné použití a GetService získání objektu IServiceProvider IXmlLineInfoProvider, který může poskytnout informace o řádcích a znakech označující, kde byla zjištěna konkrétní chyba. V tomto případě je vyvolána výjimka, pokud Source vlastnost nebyla nastavena:

[ContentProperty("Source")]
class ImageResourceExtension : IMarkupExtension<ImageSource>
{
    public string Source { set; get; }

    public ImageSource ProvideValue(IServiceProvider serviceProvider)
    {
        if (String.IsNullOrEmpty(Source))
        {
            IXmlLineInfoProvider lineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
            IXmlLineInfo lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
            throw new XamlParseException("ImageResourceExtension requires Source property to be set", lineInfo);
        }

        string assemblyName = GetType().GetTypeInfo().Assembly.GetName().Name;
        return ImageSource.FromResource(assemblyName + "." + Source, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
    }

    object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
    {
        return (this as IMarkupExtension<ImageSource>).ProvideValue(serviceProvider);
    }
}

ImageResourceExtension je užitečné, když soubor XAML potřebuje získat přístup k souboru obrázku uloženému jako vložený prostředek v projektu knihovny .NET Standard. Používá Source vlastnost k volání statické ImageSource.FromResource metody. Tato metoda vyžaduje plně kvalifikovaný název prostředku, který se skládá z názvu sestavení, názvu složky a názvu souboru odděleného tečkami. Druhý argument metody ImageSource.FromResource poskytuje název sestavení a je vyžadován pouze pro sestavení vydané verze v UPW. Bez ohledu na to, ImageSource.FromResource musí být volána ze sestavení, které obsahuje bitmapu, což znamená, že toto rozšíření prostředků XAML nemůže být součástí externí knihovny, pokud obrázky nejsou také v této knihovně. (Viz Další informace o přístupu k bitmapám uloženým jako vložené prostředky najdete v článku Vložené obrázky .)

Ačkoli ImageResourceExtension vyžaduje Source , aby byla vlastnost nastavena, Source vlastnost je uvedena v atributu jako vlastnost obsahu třídy. To znamená, že Source= část výrazu ve složených závorkách se dá vynechat. Na stránce Image Ukázka prostředku obrázku načítají prvky dva obrázky pomocí názvu složky a názvu souboru odděleného tečkami:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MarkupExtensions"
             x:Class="MarkupExtensions.ImageResourceDemoPage"
             Title="Image Resource Demo">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Image Source="{local:ImageResource Images.SeatedMonkey.jpg}"
               Grid.Row="0" />

        <Image Source="{local:ImageResource Images.FacePalm.jpg}"
               Grid.Row="1" />

    </Grid>
</ContentPage>

Tady je spuštěný program:

Obrázek ukázky prostředku

Poskytovatelé služeb

Rozšíření značek XAML můžou pomocí argumentu IServiceProvider ProvideValuezískat přístup k užitečným informacím o souboru XAML, ve kterém se používají. Pokud ale chcete argument použít IServiceProvider úspěšně, potřebujete vědět, jaký druh služeb jsou k dispozici v konkrétních kontextech. Nejlepší způsob, jak tuto funkci pochopit, je prozkoumání zdrojového kódu existujících rozšíření značek XAML ve složce MarkupExtensions v Xamarin.Forms úložišti na GitHubu. Mějte na paměti, že některé typy služeb jsou interní pro Xamarin.Forms.

V některých rozšířeních značek XAML může být tato služba užitečná:

 IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;

Rozhraní IProvideValueTarget definuje dvě vlastnosti TargetObject a TargetProperty. Pokud jsou tyto informace získány ImageResourceExtension ve třídě, TargetObject je Image a TargetProperty je BindableProperty objekt pro Source vlastnost Image. Toto je vlastnost, pro kterou bylo nastaveno rozšíření značek XAML.

Volání GetService s argumentem typeof(IProvideValueTarget) ve skutečnosti vrátí objekt typu SimpleValueTargetProvider, který je definován v Xamarin.Forms.Xaml.Internals oboru názvů. Pokud přetypujete návratovou GetService hodnotu tohoto typu, můžete také získat přístup k ParentObjects vlastnosti, což je pole obsahující Image prvek, Grid nadřazený prvek a ImageResourceDemoPage nadřazený objekt Grid.

Závěr

Rozšíření značek XAML hrají zásadní roli v XAML tím, že rozšiřují schopnost nastavit atributy z různých zdrojů. Navíc pokud existující rozšíření značek XAML neposkytují přesně to, co potřebujete, můžete také napsat vlastní.