티스토리 뷰
이 문서에서는 다음 주제를 다룹니다.
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 값의 위치를 지정해주세요.
1 2 3 4 5 6 7 8 | < 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 표기는 생략할 수 있습니다.
1 2 3 | < 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 샘플에서 다룹니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | < 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에서 특별한 목적으로 사용되기 때문에 일반적인 방법으로 표현할 수 없습니다.
1 2 | <!-- 중괄호({, })는 XAML에서 특별한 문자이므로 아래는 오류발생 --> < Label Text = "{중괄호 내부 텍스트}" /> |
중괄호 문자를 표현하려면 탈출문자열 {}을 사용해야 합니다.
1 2 | <!-- 중괄호({, })를 사용하려면 탈출문자열 {}를 사용할 것--> < Label Text = "{}{중괄호 내부 텍스트}" /> |
Resource Dictionary
VisualElement
Class는
ResourceDictionary
객체를 사용할 수 있는
Resource
Property를 제공합니다.
XAML에서는 x:Key
와 함께 값을 Dictionary에 추가할 수 있습니다. ResourceDictionary
에 저장된 값은
하위 Element에서 참조할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | < 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
를 중괄호({, })와 함께 사용합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | < 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샘플에
나타납니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | < 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을 사용하여 지정합니다.
1 2 3 4 5 6 7 8 9 10 | < 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을 직접 제작할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
- VisualStudio
- WPF
- .NET Standard
- Xamarin.Forms eBook
- c#
- React
- Vue
- npm
- Xamarin.iOS
- flutter
- ios
- ASP.NET Core
- Xamarin.Forms
- TypeScript
- Xamarin
- Xamarin.Forms 요약
- windows
- Android
- material-ui
- MS SQL
- Total
- Today
- Yesterday