티스토리 뷰
이 문서에서는 다음 주제를 다룹니다.
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 |
- Xamarin.Forms eBook
- .NET Standard
- Xamarin
- npm
- ASP.NET Core
- Xamarin.Forms
- Vue
- material-ui
- c#
- TypeScript
- VisualStudio
- ios
- flutter
- Xamarin.iOS
- MS SQL
- Android
- Xamarin.Forms 요약
- StringComparison
- React
- WPF
- Total
- Today
- Yesterday