3부. XAML 태그 확장
XAML 태그 확장은 다른 원본에서 간접적으로 참조되는 개체 또는 값으로 속성을 설정할 수 있도록 하는 XAML의 중요한 기능을 구성합니다. XAML 태그 확장은 개체를 공유하고 애플리케이션 전체에서 사용되는 상수를 참조하는 데 특히 중요하지만 데이터 바인딩에서 가장 큰 유틸리티를 찾습니다.
XAML 태그 확장
일반적으로 XAML을 사용하여 개체의 속성을 문자열, 숫자, 열거형 멤버 또는 백그라운드에서 값으로 변환되는 문자열과 같은 명시적 값으로 설정합니다.
그러나 속성이 다른 위치에 정의된 값을 대신 참조해야 하거나 런타임에 코드를 약간 처리해야 하는 경우도 있습니다. 이러한 목적을 위해 XAML 태그 확장을 사용할 수 있습니다.
이러한 XAML 태그 확장은 XML의 확장이 아닙니다. XAML은 전적으로 유효한 XML입니다. 구현하는 클래스 IMarkupExtension
의 코드에 의해 지원되기 때문에 "확장"이라고 합니다. 사용자 고유의 사용자 지정 태그 확장을 작성할 수 있습니다.
대부분의 경우 XAML 태그 확장은 중괄호로 구분된 특성 설정으로 표시되기 때문에 XAML 파일에서 즉시 인식할 수 있습니다. { 및 }이지만 태그 확장이 태그에 기존 요소로 표시되는 경우도 있습니다.
공유 리소스
일부 XAML 페이지에는 속성이 동일한 값으로 설정된 여러 보기가 포함되어 있습니다. 예를 들어 이러한 Button
개체에 대한 많은 속성 설정은 동일합니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<StackLayout>
<Button Text="Do this!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
<Button Text="Do that!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
<Button Text="Do the other thing!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
</StackLayout>
</ContentPage>
이러한 속성 중 하나를 변경해야 하는 경우 세 번이 아니라 한 번만 변경하는 것이 좋습니다. 코드인 경우 상수 및 정적 읽기 전용 개체를 사용하여 이러한 값을 일관되고 쉽게 수정할 수 있습니다.
XAML에서 인기 있는 솔루션 중 하나는 이러한 값 또는 개체를 리소스 사전에 저장하는 것입니다. 클래스는 VisualElement
형식의 키와 형식 ResourceDictionary
값이 있는 사전인 형식 string
의 object
속성을 Resources
정의합니다. 이 사전에 개체를 배치한 다음 XAML의 태그에서 참조할 수 있습니다.
페이지에서 리소스 사전을 사용하려면 속성 요소 태그 쌍 Resources
을 포함합니다. 페이지 맨 위에 배치하는 것이 가장 편리합니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
</ContentPage.Resources>
...
</ContentPage>
또한 태그를 명시적으로 포함 ResourceDictionary
해야 합니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
<ResourceDictionary>
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
이제 다양한 형식의 개체와 값을 리소스 사전에 추가할 수 있습니다. 이러한 형식은 인스턴스화할 수 있어야 합니다. 예를 들어 추상 클래스일 수는 없습니다. 이러한 형식에는 공용 매개 변수가 없는 생성자도 있어야 합니다. 각 항목에는 특성으로 x:Key
지정된 사전 키가 필요합니다. 예시:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center"
Expands="True" />
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
이러한 두 항목은 구조체 형식 LayoutOptions
의 값이며 각각 고유한 키와 하나 또는 두 개의 속성 집합이 있습니다. 코드 및 태그에서는 정적 필드를 LayoutOptions
사용하는 것이 훨씬 더 일반적이지만 여기서는 속성을 설정하는 것이 더 편리합니다.
이제 이러한 단추의 속성과 VerticalOptions
속성을 이러한 리소스로 설정 HorizontalOptions
해야 하며, 이 작업은 XAML 태그 확장으로 StaticResource
수행됩니다.
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
StaticResource
태그 확장은 항상 중괄호로 구분되며 사전 키를 포함합니다.
이름은 StaticResource
지원되는 이름과 DynamicResource
Xamarin.Forms 구별됩니다. DynamicResource
는 런타임 중에 변경될 수 있는 값과 연결된 사전 키에 대한 것이며 StaticResource
, 페이지의 요소가 생성될 때 사전의 요소에 한 번만 액세스합니다.
속성의 BorderWidth
경우 사전에 double을 저장해야 합니다. XAML은 다음과 같은 x:Double
x:Int32
일반적인 데이터 형식에 대한 태그를 편리하게 정의합니다.
<ContentPage.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center"
Expands="True" />
<x:Double x:Key="borderWidth">
3
</x:Double>
</ResourceDictionary>
</ContentPage.Resources>
당신은 세 줄에 넣을 필요가 없습니다. 이 회전 각도에 대한 이 사전 항목은 한 줄만 차지합니다.
<ContentPage.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center"
Expands="True" />
<x:Double x:Key="borderWidth">
3
</x:Double>
<x:Double x:Key="rotationAngle">-15</x:Double>
</ResourceDictionary>
</ContentPage.Resources>
이러한 두 리소스는 값과 동일한 방식으로 LayoutOptions
참조할 수 있습니다.
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="Red"
FontSize="24" />
형식의 리소스의 경우 이러한 형식 Color
의 특성을 직접 할당할 때 사용하는 것과 동일한 문자열 표현을 사용할 수 있습니다. 형식 변환기는 리소스를 만들 때 호출됩니다. 형식의 리소스 Color
는 다음과 같습니다.
<Color x:Key="textColor">Red</Color>
프로그램에서 속성을 열거형의 NamedSize
멤버(예: .)로 Large
설정하는 FontSize
경우가 많습니다. 클래스는 FontSizeConverter
메서드를 사용하여 플랫폼 종속 값으로 변환하기 위해 백그라운드에서 작동합니다 Device.GetNamedSized
. 그러나 글꼴 크기 리소스를 정의할 때는 다음과 같이 숫자 값을 형식으로 x:Double
사용하는 것이 더 좋습니다.
<x:Double x:Key="fontSize">24</x:Double>
이제 리소스 설정을 제외한 Text
모든 속성이 정의됩니다.
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
리소스 사전 내에서 플랫폼에 대해 서로 다른 값을 정의하는 데 사용할 OnPlatform
수도 있습니다. 개체가 OnPlatform
다양한 텍스트 색에 대한 리소스 사전의 일부가 될 수 있는 방법은 다음과 같습니다.
<OnPlatform x:Key="textColor"
x:TypeArguments="Color">
<On Platform="iOS" Value="Red" />
<On Platform="Android" Value="Aqua" />
<On Platform="UWP" Value="#80FF80" />
</OnPlatform>
OnPlatform
이 속성은 사전의 개체이고 x:TypeArguments
제네릭 클래스이기 때문에 특성이 모두 x:Key
가져옵니다. 개체가 iOS
초기화되면 , Android
및 UWP
특성이 값으로 변환 Color
됩니다.
다음은 6개의 공유 값에 액세스하는 세 개의 단추가 있는 최종 전체 XAML 파일입니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center"
Expands="True" />
<x:Double x:Key="borderWidth">3</x:Double>
<x:Double x:Key="rotationAngle">-15</x:Double>
<OnPlatform x:Key="textColor"
x:TypeArguments="Color">
<On Platform="iOS" Value="Red" />
<On Platform="Android" Value="Aqua" />
<On Platform="UWP" Value="#80FF80" />
</OnPlatform>
<x:Double x:Key="fontSize">24</x:Double>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
<Button Text="Do that!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
<Button Text="Do the other thing!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
</StackLayout>
</ContentPage>
스크린샷은 일관된 스타일 지정 및 플랫폼 종속 스타일을 확인합니다.
페이지 맨 위에 컬렉션을 정의하는 Resources
것이 가장 일반적이지만 속성 Resources
이 정의되며 VisualElement
페이지의 다른 요소에 컬렉션을 가질 Resources
수 있습니다. 예를 들어 이 예제에서 StackLayout
하나를 추가해 봅니다.
<StackLayout>
<StackLayout.Resources>
<ResourceDictionary>
<Color x:Key="textColor">Blue</Color>
</ResourceDictionary>
</StackLayout.Resources>
...
</StackLayout>
이제 단추의 텍스트 색이 파란색임을 알 수 있습니다. 기본적으로 XAML 파서가 태그 확장을 발견 StaticResource
할 때마다 시각적 트리를 검색하고 해당 키를 포함하는 첫 번째 ResourceDictionary
검색을 사용합니다.
리소스 사전에 저장된 가장 일반적인 개체 유형 중 하나는 속성 설정 컬렉션을 정의하는 개체입니다 Xamarin.FormsStyle
. 스타일은 스타일 문서에서 설명합니다.
XAML을 새로운 개발자가 시각적 요소(예: Label
)를 배치할 Button
ResourceDictionary
수 있는지 궁금해하는 경우가 있습니다. 그것은 확실히 가능하지만, 그것은 많은 의미가 없습니다. 개체를 ResourceDictionary
공유하는 것이 목적입니다. 시각적 요소를 공유할 수 없습니다. 동일한 인스턴스는 단일 페이지에 두 번 표시할 수 없습니다.
x:Static 태그 확장
그들의 이름의 유사성에도 불구하고, x:Static
StaticResource
매우 다르다. StaticResource
는 다음 중 하나에 액세스하는 동안 x:Static
리소스 사전에서 개체를 반환합니다.
- 공용 정적 필드
- 공용 정적 속성
- 공용 상수 필드
- 열거형 멤버입니다.
StaticResource
태그 확장은 리소스 사전을 정의하는 XAML 구현에서 지원되지만 x:Static
접두사에서 알 수 있듯이 x
XAML의 내장 부분입니다.
다음은 정적 필드 및 열거형 멤버를 명시적으로 참조하는 방법을 x:Static
보여 주는 몇 가지 예입니다.
<Label Text="Hello, XAML!"
VerticalOptions="{x:Static LayoutOptions.Start}"
HorizontalTextAlignment="{x:Static TextAlignment.Center}"
TextColor="{x:Static Color.Aqua}" />
지금까지, 이것은 매우 인상적이지 않습니다. 그러나 태그 확장은 사용자 고유의 x:Static
코드에서 정적 필드 또는 속성을 참조할 수도 있습니다. 예를 들어 애플리케이션 전체의 AppConstants
여러 페이지에서 사용할 수 있는 일부 정적 필드가 포함된 클래스는 다음과 같습니다.
using System;
using Xamarin.Forms;
namespace XamlSamples
{
static class AppConstants
{
public static readonly Thickness PagePadding;
public static readonly Font TitleFont;
public static readonly Color BackgroundColor = Color.Aqua;
public static readonly Color ForegroundColor = Color.Brown;
static AppConstants()
{
switch (Device.RuntimePlatform)
{
case Device.iOS:
PagePadding = new Thickness(5, 20, 5, 0);
TitleFont = Font.SystemFontOfSize(35, FontAttributes.Bold);
break;
case Device.Android:
PagePadding = new Thickness(5, 0, 5, 0);
TitleFont = Font.SystemFontOfSize(40, FontAttributes.Bold);
break;
case Device.UWP:
PagePadding = new Thickness(5, 0, 5, 0);
TitleFont = Font.SystemFontOfSize(50, FontAttributes.Bold);
break;
}
}
}
}
XAML 파일에서 이 클래스의 정적 필드를 참조하려면 이 파일이 있는 XAML 파일 내에서 어떤 방법으로 표시해야 합니다. XML 네임스페이스 선언을 사용하여 이 작업을 수행합니다.
표준 Xamarin.Forms XAML 템플릿의 일부로 만든 XAML 파일에는 두 개의 XML 네임스페이스 선언이 포함되어 있습니다. 하나는 클래스 액세스 Xamarin.Forms 용이고 다른 하나는 XAML에 내장된 태그 및 특성을 참조하기 위한 것입니다.
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
다른 클래스에 액세스하려면 추가 XML 네임스페이스 선언이 필요합니다. 각 추가 XML 네임스페이스 선언은 새 접두사를 정의합니다. 공유 애플리케이션 .NET Standard 라이브러리 AppConstants
에 로컬 클래스에 액세스하려면 XAML 프로그래머가 접두사를 local
사용하는 경우가 많습니다. 네임스페이스 선언은 C# namespace
정의 또는 using
지시문에 표시되는 이름인 .NET 네임스페이스 이름이라고도 하는 CLR(공용 언어 런타임) 네임스페이스 이름을 나타내야 합니다.
xmlns:local="clr-namespace:XamlSamples"
.NET Standard 라이브러리가 참조하는 어셈블리에서 .NET 네임스페이스에 대한 XML 네임스페이스 선언을 정의할 수도 있습니다. 예를 들어 netstandard 어셈블리에 있는 표준 .NET System
네임스페이스의 접두사는 다음과 같습니다sys
. 다른 어셈블리이므로 어셈블리 이름(이 경우 netstandard)도 지정해야 합니다.
xmlns:sys="clr-namespace:System;assembly=netstandard"
키워드(keyword) clr-namespace
콜론과 .NET 네임스페이스 이름 뒤에 세미콜론, 키워드(keyword)assembly
, 등호 및 어셈블리 이름이 옵니다.
예, 콜론이 clr-namespace
따르지만 등호는 다음과 같습니다 assembly
. 이 구문은 의도적으로 정의되었습니다. 대부분의 XML 네임스페이스 선언은 URI 체계 이름(예: http
항상 콜론 뒤에 오는)을 시작하는 URI를 참조합니다. clr-namespace
이 문자열의 부분은 해당 규칙을 모방하기 위한 것입니다.
이러한 네임스페이스 선언은 모두 StaticConstantsPage 샘플에 포함됩니다. 차원은 BoxView
100으로 설정 Math.PI
되고 Math.E
크기가 100으로 조정됩니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
xmlns:sys="clr-namespace:System;assembly=netstandard"
x:Class="XamlSamples.StaticConstantsPage"
Title="Static Constants Page"
Padding="{x:Static local:AppConstants.PagePadding}">
<StackLayout>
<Label Text="Hello, XAML!"
TextColor="{x:Static local:AppConstants.BackgroundColor}"
BackgroundColor="{x:Static local:AppConstants.ForegroundColor}"
Font="{x:Static local:AppConstants.TitleFont}"
HorizontalOptions="Center" />
<BoxView WidthRequest="{x:Static sys:Math.PI}"
HeightRequest="{x:Static sys:Math.E}"
Color="{x:Static local:AppConstants.ForegroundColor}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="100" />
</StackLayout>
</ContentPage>
화면을 기준으로 하는 결과 BoxView
크기는 플랫폼에 따라 달라집니다.
기타 표준 태그 확장
여러 태그 확장은 XAML에 내장되어 있으며 XAML 파일에서 Xamarin.Forms 지원됩니다. 이들 중 일부는 자주 사용되지 않지만 필요할 때 필수적입니다.
- 속성에 기본적으로 값
null
이 아닌 값이 있지만 설정null
하려는 경우 태그 확장으로{x:Null}
설정합니다. - 속성이 형식
Type
인 경우 태그 확장을{x:Type someClass}
사용하여 개체에 할당할Type
수 있습니다. - 태그 확장을 사용하여 XAML에서 배열을 정의할
x:Array
수 있습니다. 이 태그 확장에는 배열에 있는 요소의 형식을 나타내는 명명된Type
필수 특성이 있습니다. - 태그 확장은
Binding
4부에서 설명합니다. 데이터 바인딩 기본 사항. RelativeSource
태그 확장은 상대 바인딩에서 설명합니다.
ConstraintExpression 태그 확장
태그 확장에는 속성이 있을 수 있지만 XML 특성처럼 설정되지는 않습니다. 태그 확장에서 속성 설정은 쉼표로 구분되며 중괄호 안에 따옴표가 나타나지 않습니다.
클래스와 함께 Xamarin.Forms RelativeLayout
사용되는 태그 확장으로 ConstraintExpression
설명될 수 있습니다. 자식 보기의 위치 또는 크기를 상수로 지정하거나 부모 또는 다른 명명된 뷰를 기준으로 지정할 수 있습니다. 구문을 사용하면 다른 뷰의 ConstraintExpression
속성과 1번을 사용하여 Factor
보기 Constant
의 위치 또는 크기를 설정할 수 있습니다. 코드가 필요한 것보다 더 복잡한 항목
예를 들면 다음과 같습니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.RelativeLayoutPage"
Title="RelativeLayout Page">
<RelativeLayout>
<!-- Upper left -->
<BoxView Color="Red"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}" />
<!-- Upper right -->
<BoxView Color="Green"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Width,
Factor=1,
Constant=-40}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}" />
<!-- Lower left -->
<BoxView Color="Blue"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=1,
Constant=-40}" />
<!-- Lower right -->
<BoxView Color="Yellow"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Width,
Factor=1,
Constant=-40}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=1,
Constant=-40}" />
<!-- Centered and 1/3 width and height of parent -->
<BoxView x:Name="oneThird"
Color="Red"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Width,
Factor=0.33}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.33}"
RelativeLayout.WidthConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Width,
Factor=0.33}"
RelativeLayout.HeightConstraint=
"{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.33}" />
<!-- 1/3 width and height of previous -->
<BoxView Color="Blue"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=RelativeToView,
ElementName=oneThird,
Property=X}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=RelativeToView,
ElementName=oneThird,
Property=Y}"
RelativeLayout.WidthConstraint=
"{ConstraintExpression Type=RelativeToView,
ElementName=oneThird,
Property=Width,
Factor=0.33}"
RelativeLayout.HeightConstraint=
"{ConstraintExpression Type=RelativeToView,
ElementName=oneThird,
Property=Height,
Factor=0.33}" />
</RelativeLayout>
</ContentPage>
이 샘플에서 수행해야 하는 가장 중요한 단원은 태그 확장의 구문입니다. 태그 확장의 중괄호 내에 따옴표가 나타나지 않아야 합니다. XAML 파일에 태그 확장을 입력할 때 속성 값을 따옴표로 묶는 것이 좋습니다. 유혹에 저항!
실행 중인 프로그램은 다음과 같습니다.
요약
여기에 표시된 XAML 태그 확장은 XAML 파일에 대한 중요한 지원을 제공합니다. 그러나 아마도 가장 가치있는 XAML 태그 확장은Binding
이 시리즈의 다음 부분인 4 부에서 다루는 것입니다. 데이터 바인딩 기본 사항.