티스토리 뷰
이 문서에서는 다음 주제를 다룹니다.
XAML 파서는 Converter를 사용하여 XAML Attribute의 문자열을 지정된 Type 인스턴스로 변경합니다.
.NET 기본 데이터 유형(int, double 등)에 대해서는 TryParse와 같은 표준 Converter를 사용합니다.
그 외의 경우에는 Property나 Class에 수식된
TypeConverter 파생 Class와
TypeConverterAttribute를 통해
XAML 문자열을 지정된 Type 인스턴스로 변환합니다.
때로는 변환과정에 다른 처리를 추가할 수 있다면 편리할 때가 있습니다. 예를 들어 값을 Dictionary로부터 조회하거나, Static Property나 Field에서 값을 조회하거나, 변환 중에 특별한 처리가 필요할 수 있습니다.
이 것이 바로 XAML Markup Extension의 역할입니다. Markup Extension이라는 이름에도 불구하고 XML을 확장하는 것이 아닙니다. XAML은 항상 순수한 XML로 구성되며 XAML Markup Extension은 XAML 문자열을 변환하는 C# 컨버팅을 확장하는 것입니다.
코드 인프라
XAML Markup Extension은
IMarkupExtension
interface를 구현한 Class를 말합니다. 이러한 Class들은 이름에 Extension이라는 접미사를 포함하지만
XAML에서는 Extension 접미사 없이 사용할 수 있습니다.
아래는 모든 XAML 구현에서 지원되는 XAML Markup Extension으로 Xamarin.Forms.Xaml 어셈블리에 정의되어 있습니다.
x:Static(StaticExtension에 의해 지원됨)x:Reference(ReferenceExtension에 의해 지원됨)x:Type(TypeExtension에 의해 지원됨)x:Null(NullExtension에 의해 지원됨)x:Array(ArrayExtension에 의해 지원됨)
아래 4개의 XAML Markup Extension은 Xamarin.Fomrs를 포함한 수많은 XAML 구현에서 지원됩니다. Windows Presentation Foundation(WPF)로부터 시작되었으며 Silverlight, Windows Phone 7, 8, Windows 8, 10 등 모든 Microsoft XAML 구현에서 지원됩니다.
StaticResource(StaticResourceExtension에 의해 지원됨)DynamicResource(DynamicResourceExtension에 의해 지원됨)Binding(BindingExtension에 의해 지원됨, Chapter 16. Data binding에서 다시 다룹니다)TemplateBinding(TemplateBindingExtension에 의해 지원됨, 이 책에서 다루진 않습니다)
다음은
RelativeLayout과 함께 사용하기 위해
Xamarin.Forms에 추가된 XAML Markup Extension 입니다.
ConstraintExpression(이 책에서 다루지 않음)
Static Member에 접근
x:Static은
Static Propery, Field, Enum, 상수(const) 값을 XAML에서 사용할 수 있게 해줍니다.
Member
Property에는 조회할 Static 값의 위치를 지정해주세요.
<Label Text="Just some text">
<Label.TextColor>
<x:StaticExtension Member="Color.Black" />
</Label.TextColor>
<Label.FontAttributes>
<x:StaticExtension Member="FontAttributes.Italic" />
</Label.FontAttributes>
</Label>
중괄호({, })를 사용하면 보다 간결하게 표현할 수 있습니다.
Member Property 표기는 생략할 수 있습니다.
<Label Text="Just some text"
BackgroundColor="{x:Static Member=Color.Accent}"
TextColor="{x:Static Color.Black}" />
SharedStatics 샘플은
x:Static 사용예제를 제공합니다.
Static 값은
AppConstants Class에
정의되어 있습니다. 이 예제는 앱의 공통상수를 정의한 후 앱 전체에서 사용하는 방법을 소개합니다.
XML namespace를 추가하면 .NET Framework에 정의된 Static Property, Field, Enum 값을 사용할 수 있습니다. 이에 관해서는 SystemStatics 샘플에서 다룹니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="SystemStatics.SystemStaticsPage">
<!--System.Math.PI을 사용 -->
<Button Text="π BorderWidth"
BorderWidth="{x:Static sys:Math.PI}" />
<!--System.Environment.NewLine을 사용 -->
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="3줄의 텍스트" />
<Span Text="{x:Static sys:Environment.NewLine}" />
<Span Text="Environment.NewLine를" />
<Span Text="{x:Static sys:Environment.NewLine}" />
<Span Text="사용하여 구분" />
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ContentPage>
중괄호({, })는 XAML에서 특별한 목적으로 사용되기 때문에 일반적인 방법으로 표현할 수 없습니다.
<!-- 중괄호({, })는 XAML에서 특별한 문자이므로 아래는 오류발생 -->
<Label Text="{중괄호 내부 텍스트}" />
중괄호 문자를 표현하려면 탈출문자열 {}을 사용해야 합니다.
<!-- 중괄호({, })를 사용하려면 탈출문자열 {}를 사용할 것-->
<Label Text="{}{중괄호 내부 텍스트}" />
Resource Dictionary
VisualElement Class는
ResourceDictionary
객체를 사용할 수 있는
Resource
Property를 제공합니다.
XAML에서는 x:Key와 함께 값을 Dictionary에 추가할 수 있습니다. ResourceDictionary에 저장된 값은
하위 Element에서 참조할 수 있습니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceSharing.ResourceSharingPage">
<!-- VisualElement에서 제공하는 Resource에 값을 추가 -->
<ContentPage.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions">Center</LayoutOptions>
<LayoutOptions x:Key="vertOptions" Alignment="Center" Expands="True" />
<x:Double x:Key="borderWidth">3</x:Double>
<Color x:Key="textColor">Red</Color>
</ContentPage.Resources>
</ResourceDictionary>
<!-- ContentPage 하위 Element들은 ResourceDictionary 값 사용가능 -->
</ContentPage>
일반적인 StaticResource 사용
대부분의 경우
StaticResource Markup Extension은
ResourceDictionary에 추가된 값을 참조하기 위해 사용됩니다.
이에 관해서는
ResourceSharing
샘플에서 예제를 제공합니다.
값을 참조하기 위해서 StaticResourceExtension Element나 StaticResource를 중괄호({, })와 함께 사용합니다.
<StackLayout>
<!-- ResourceDictionary 정의 -->
<StackLayout.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions">Center</LayoutOptions>
<LayoutOptions x:Key="vertOptions" Alignment="Center" Expands="True" />
<x:Double x:Key="borderWidth">3</x:Double>
<Color x:Key="textColor">Red</Color>
<OnPlatform x:Key="backgroundColor"
x:TypeArguments="Color"
Android="#404040" />
<OnPlatform x:Key="borderColor"
x:TypeArguments="Color"
Android="White"
WinPhone="Black" />
<x:String x:Key="fontSize">Large</x:String>
</ResourceDictionary>
</StackLayout.Resources>
<!-- StaticResourceExtension Element를 통한 접근 -->
<Button Text=" Carpe diem ">
<Button.HorizontalOptions>
<StaticResourceExtension Key="horzOptions" />
</Button.HorizontalOptions>
<Button.VerticalOptions>
<StaticResourceExtension Key="vertOptions" />
</Button.VerticalOptions>
<Button.BorderWidth>
<StaticResourceExtension Key="borderWidth" />
</Button.BorderWidth>
<Button.TextColor>
<StaticResourceExtension Key="textColor" />
</Button.TextColor>
<Button.BackgroundColor>
<StaticResourceExtension Key="backgroundColor" />
</Button.BackgroundColor>
<Button.BorderColor>
<StaticResourceExtension Key="borderColor" />
</Button.BorderColor>
<Button.FontSize>
<StaticResourceExtension Key="fontSize" />
</Button.FontSize>
</Button>
<!-- StaticResource를 중괄호와 사용하는 방법 -->
<Button Text=" Sapere aude "
HorizontalOptions="{StaticResource Key=horzOptions}"
VerticalOptions="{StaticResource Key=vertOptions}"
BorderWidth="{StaticResource Key=borderWidth}"
TextColor="{StaticResource Key=textColor}"
BackgroundColor="{StaticResource Key=backgroundColor}"
BorderColor="{StaticResource Key=borderColor}"
FontSize="{StaticResource Key=fontSize}" />
<!-- StaticResource를 중괄호와 사용하는 방법2 (Key 생략가능) -->
<Button Text=" Discere faciendo "
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
TextColor="{StaticResource textColor}"
BackgroundColor="{StaticResource backgroundColor}"
BorderColor="{StaticResource borderColor}"
FontSize="{StaticResource fontSize}" />
</StackLayout>
x:Static와 StaticResource는 전혀 다른 Markup Extension이므로 주의해주세요.
Dictionary Tree
XAML 파서가 StaticResource를 만나면 XAML Tree를 거슬러 올라가며 ResourceDictionary찾아
Key에 해당하는 값을 찾습니다. 값을 찾지 못할 경우 최종적으로 App Class를 검색하고 값이 없으면 오류를 발생시킵니다.
Visual Tree 상으로 하위의 ResourceDictionary와 부모의 ResourceDictionary에 동일한 Key 값이 존재하면
하위에 존재하는 값이 사용됩니다. 이러한 예제는
ResourceTrees샘플에
나타납니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResourceSharing.ResourceSharingPage">
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="textColor">Red</Color>
<Color x:Key="backColor">#404040</Color>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<StackLayout.Resources>
<ResourceDictionary>
<Color x:Key="textColor">Blue</Color>
</ResourceDictionary>
</StackLayout.Resources>
<!--
부모와 자식 ResourceDictionary에
동일한 Key가 포함될 경우 자식이 부모를 Override함
(버튼은 파란 텍스트에 회색 배경을 가짐)
-->
<Button Text="ResourceDictionary Tree"
TextColor="{StaticResource textColor}"
BackgroundColor="{StaticResource backColor}" />
</StackLayout>
</ContentPage>
DynamicResource
StaticResource Markup Extension은 InitializeComponemt가 호출될 때
Visual Tree 상의 ResourceDictionary를 검색하며 처음 Key가 일치하는 값을 사용합니다.
StaticResource 대신
DynamicResource를
사용할 수도 있습니다. DynamicResource는 StaticResource과 동일하게 값을 검색하고 사용합니다.
하지만 DynamicResource는 ResourceDictionary와 연결를 지속적으로 유지하고
ResourceDictionary의 값이 변경될 때 마다 반영합니다.
반대로 StaticResource는 처음 한번만 값을 검색하고 반영합니다.
DynamicVsStatic 샘플은
StaticResource와 DynamicResource 간의 차이를 보여줍니다.
DynamicResource를 사용하는 Property는 반드시 Bindable Property에 의해 구현되어야 하며
이에 관해서는
Chapter 11, The bindable infrastructure에서 소개합니다.
덜 사용되는 Markup Extension
x:Null Markup Extension은
null값을 할당합니다.
x:Type Markup Extension은
.NET의 Type 값을 할당합니다.
x:Array Markup Extension은
배열을 정의합니다. 배열 값의 유형은 Type Property에 x:Type Markup Extension을 사용하여 지정합니다.
<SomeElement SomeProperty="{x:Null}" />
<AnotherElement TypeProperty="{x:Type Color}" />
<x:Array x:Key="array" Type="{x:Type x:String}">
<x:String>One String</x:String>
<x:String>Two String</x:String>
<x:String>Red String</x:String>
<x:String>Blue String</x:String>
</x:Array>
Custom Markup Extension
IMarkupExtension interface와
ProvideValue
메서드를 구현함으로써 XAML Markup Extension을 직접 제작할 수 있습니다.
public class HslColorExtension : IMarkupExtension
{
public HslColorExtension() { A = 1; }
public double H { set; get; }
public double S { set; get; }
public double L { set; get; }
public double A { set; get; }
public object ProvideValue(IServiceProvider serviceProvider)
{
return Color.FromHsla(H, S, L, A);
}
}
HslColorExtension
Class는 IMarkupExtension를 구현한 Custom Markup Extension입니다. HslColorExtension Class는 H, S, L, A Property 값을 설정하면
Color 값을 반환합니다. 이 Class는
이 책에 전반애 걸쳐 다루는
Xamarin.FormsBook.Toolkit이라는
Xamarin.Forms 라이브러리의 첫번째 항목입니다.
CustomExtensionDemo 샘플은
이 라이브러리를 레퍼런스에 추가하고 이 Custom Mrkup Extension을 사용하는 방법을 보여줍니다.
관련 링크
'Xamarin.Forms Book > 요약' 카테고리의 다른 글
| 11장 요약. Bindable 인프라 (0) | 2018.08.27 |
|---|---|
| 9장 요약. 플랫폼별 API 호출 (0) | 2018.08.18 |
| 8장 요약. 코드와 XAML의 조화 (0) | 2018.08.18 |
| 7장 요약. XAML 및 코드 (0) | 2018.08.15 |
| 6장 요약. 버튼 클릭 (0) | 2018.08.15 |
| 5장 요약. 크기 처리 (0) | 2018.08.12 |
| 4장 요약. 스택 스크롤 (0) | 2018.08.12 |
| 3장 요약. 텍스트 자세히 알아보기 (0) | 2018.08.11 |
- Vue
- windows
- React
- MS SQL
- .NET Standard
- Android
- material-ui
- Xamarin
- WPF
- npm
- Xamarin.iOS
- ASP.NET Core
- flutter
- Xamarin.Forms eBook
- ios
- linux
- TypeScript
- VisualStudio
- Xamarin.Forms 요약
- Xamarin.Forms
- Total
- Today
- Yesterday