다음을 통해 공유


XAML 태그 확장 만들기

프로그래밍 방식 수준에서 XAML 태그 확장은 또는 IMarkupExtension<T> 인터페이스를 IMarkupExtension 구현하는 클래스입니다. GitHub 리포지토리의 MarkupExtensions 디렉터리에서 아래에 설명된 표준 태그 확장의 Xamarin.Forms 소스 코드를 탐색할 수 있습니다.

파생하거나 IMarkupExtension<T>파생하여 사용자 고유의 사용자 지정 XAML 태그 확장을 정의할 수도 있습니다IMarkupExtension. 태그 확장에서 특정 형식의 값을 가져오는 경우 제네릭 양식을 사용합니다. 다음과 같은 몇 가지 태그 확장이 Xamarin.Forms 있습니다.

  • TypeExtensionIMarkupExtension<Type>에서 파생됩니다.
  • ArrayExtensionIMarkupExtension<Array>에서 파생됩니다.
  • DynamicResourceExtensionIMarkupExtension<DynamicResource>에서 파생됩니다.
  • BindingExtensionIMarkupExtension<BindingBase>에서 파생됩니다.
  • ConstraintExpressionIMarkupExtension<Constraint>에서 파생됩니다.

IMarkupExtension 인터페이스는 각각 다음과 같은 ProvideValue하나의 메서드만 정의합니다.

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

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

IMarkupExtension<T> 키워드(keyword) 파생 IMarkupExtension 되고 포함 ProvideValuenew 되므로 두 메서드가 모두 ProvideValue 포함됩니다.

XAML 태그 확장은 반환 값에 영향을 주는 속성을 정의하는 경우가 많습니다. (명백한 예외는 NullExtension단순히 .를 반환null하는 ProvideValue 것입니다.) 메서드에는 ProvideValue 이 문서의 뒷부분에 설명될 형식 IServiceProvider 의 단일 인수가 있습니다.

색 지정을 위한 태그 확장

다음 XAML 태그 확장을 사용하면 색조, 채도 및 광도 구성 요소를 사용하여 값을 생성 Color 할 수 있습니다. 1로 초기화된 알파 구성 요소를 포함하여 색의 네 가지 구성 요소에 대한 네 가지 속성을 정의합니다. 클래스는 반환 값을 나타내 Color 기 위해 파생됩니다IMarkupExtension<Color>.

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);
    }
}

IMarkupExtension<T> 파생되므로 IMarkupExtension클래스는 반환되는 메서드와 반환 objectColor 하는 메서드 ProvideValue 를 포함해야 하지만 두 번째 메서드는 단순히 첫 번째 메서드를 호출할 수 있습니다.

HSL 색 데모 페이지에는 XAML 파일에 표시되어 다음과 같은 색을 지정할 수 있는 BoxView다양한 방법이 HslColorExtension 나와 있습니다.

<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>

XML 태그인 경우 HslColorExtension 네 개의 속성이 특성으로 설정되지만 중괄호 사이에 나타나면 네 개의 속성은 따옴표 없이 쉼표로 구분됩니다. 의 기본값H은 0이고 L 기본값 A 은 1이므로 기본값으로 설정하려는 경우 해당 속성을 생략할 수 S있습니다. 마지막 예제에서는 광도가 0이면 일반적으로 검은색이 되지만 알파 채널은 0.5이므로 반 투명하고 페이지의 흰색 배경에 회색으로 표시되는 예제를 보여 줍니다.

HSL 색 데모

비트맵에 액세스하기 위한 태그 확장

인수 ProvideValue 는 .NET System 네임스페이스에 IServiceProvider 정의된 인터페이스를 구현하는 개체입니다. 이 인터페이스에는 인수를 사용하여 명명 GetService 된 메서드인 멤버가 하나 있습니다 Type .

아래 표시된 클래스는 ImageResourceExtension 특정 오류가 감지된 위치를 나타내는 줄 및 문자 정보를 제공할 수 있는 개체를 사용하고 IServiceProviderGetService 가져올 IXmlLineInfoProvider 수 있는 한 가지 사용 방법을 보여줍니다. 이 경우 속성이 설정되지 않은 경우 예외가 Source 발생합니다.

[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 는 XAML 파일이 .NET Standard 라이브러리 프로젝트에 포함된 리소스로 저장된 이미지 파일에 액세스해야 하는 경우에 유용합니다. 이 속성은 Source 정적 ImageSource.FromResource 메서드를 호출하는 데 사용됩니다. 이 메서드에는 어셈블리 이름, 폴더 이름 및 마침표로 구분된 파일 이름으로 구성된 정규화된 리소스 이름이 필요합니다. 메서드의 ImageSource.FromResource 두 번째 인수는 어셈블리 이름을 제공하며 UWP의 릴리스 빌드에만 필요합니다. 관계없이 비트맵을 포함하는 어셈블리에서 호출해야 합니다. 즉, ImageSource.FromResource 이미지가 해당 라이브러리에 있지 않으면 이 XAML 리소스 확장이 외부 라이브러리의 일부가 될 수 없습니다. (다음을 참조하세요. 포함된 리소스로 저장된 비트맵에 액세스하는 방법에 대한 자세한 내용은 포함된 이미지 문서입니다.)

ImageResourceExtension 속성을 설정 Source 해야 Source 하지만 속성은 특성에 클래스의 콘텐츠 속성으로 표시됩니다. 즉 Source= , 중괄호 안에 있는 식 부분을 생략할 수 있습니다. 이미지 리소스 데모 페이지에서 Image 요소는 폴더 이름과 파일 이름을 마침표로 구분하여 두 이미지를 가져옵니다.

<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>

실행 중인 프로그램은 다음과 같습니다.

이미지 리소스 데모

서비스 공급자

인수를 IServiceProviderProvideValue사용하여 XAML 태그 확장 프로그램은 사용 중인 XAML 파일에 대한 유용한 정보에 액세스할 수 있습니다. 그러나 인수를 IServiceProvider 성공적으로 사용하려면 특정 컨텍스트에서 사용할 수 있는 서비스 종류를 알아야 합니다. 이 기능을 이해하는 가장 좋은 방법은 GitHub의 리포지토리에 있는 MarkupExtensions 폴더에 있는 Xamarin.Forms기존 XAML 태그 확장의 소스 코드를 연구하는 것입니다. 일부 유형의 서비스는 내부 Xamarin.Forms입니다.

일부 XAML 태그 확장에서는 이 서비스가 유용할 수 있습니다.

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

인터페이스는 IProvideValueTarget 두 가지 속성을 정의하고 TargetProperty. TargetObject 클래스에서 ImageResourceExtension 이 정보를 가져올 때는 해당 속성ImageImage 개체 Source 이고 BindablePropertyTargetProperty . TargetObject XAML 태그 확장이 설정된 속성입니다.

인수 typeof(IProvideValueTarget) 가 있는 호출은 GetService 실제로 네임스페이스에 정의된 형식SimpleValueTargetProvider의 개체를 Xamarin.Forms.Xaml.Internals 반환합니다. 해당 형식으로 GetService 반환 값을 캐스팅하는 경우 요소, 부모 및 ImageResourceDemoPage 상위GridGrid 포함하는 Image 배열인 속성에 액세스할 ParentObjects 수도 있습니다.

결론

XAML 태그 확장은 다양한 원본에서 특성을 설정하는 기능을 확장하여 XAML에서 중요한 역할을 합니다. 또한 기존 XAML 태그 확장이 필요한 항목을 정확하게 제공하지 않는 경우 사용자 고유의 태그를 작성할 수도 있습니다.