2부. 필수 XAML 구문

XAML은 주로 개체를 인스턴스화하고 초기화하도록 설계되었습니다. 그러나 XML 문자열로 쉽게 나타낼 수 없는 복합 개체로 속성을 설정해야 하는 경우가 많으며, 경우에 따라 한 클래스에서 정의된 속성을 자식 클래스에서 설정해야 합니다. 이러한 두 요구 사항에는 속성 요소 및 연결된 속성의 필수 XAML 구문 기능이 필요합니다.

속성 요소

XAML에서 클래스의 속성은 일반적으로 XML 특성으로 설정됩니다.

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large"
       TextColor="Aqua" />

그러나 XAML에서 속성을 설정하는 다른 방법이 있습니다. 이 대안을 TextColor사용하려면 먼저 기존 TextColor 설정을 삭제합니다.

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large" />

시작 및 끝 태그로 구분하여 빈 요소 Label 태그를 엽니다.

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large">

</Label>

이러한 태그 내에서 클래스 이름과 마침표로 구분된 속성 이름으로 구성된 시작 및 끝 태그를 추가합니다.

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large">
    <Label.TextColor>

    </Label.TextColor>
</Label>

다음과 같이 속성 값을 새 태그의 콘텐츠로 설정합니다.

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large">
    <Label.TextColor>
        Aqua
    </Label.TextColor>
</Label>

속성을 지정 TextColor 하는 이러한 두 가지 방법은 기능적으로 동일하지만 동일한 속성에 대해 두 가지 방법을 사용하지 마세요. 이는 속성을 효과적으로 두 번 설정하며 모호할 수 있기 때문입니다.

이 새로운 구문을 사용하면 몇 가지 편리한 용어를 도입할 수 있습니다.

  • Label는 개체 요소입니다. Xamarin.Forms XML 요소로 표현되는 개체입니다.
  • Text, VerticalOptionsFontAttributesFontSize 속성 특성입니다. XML 특성으로 표현되는 속성입니다 Xamarin.Forms .
  • 마지막 코드 TextColor 조각에서 속성 요소가 되었습니다. Xamarin.Forms 속성이지만 이제 XML 요소입니다.

속성 요소의 정의는 처음에는 XML 구문을 위반하는 것처럼 보일 수 있지만 그렇지 않습니다. 마침표는 XML에서 특별한 의미가 없습니다. XML 디코더 Label.TextColor 의 경우 단순히 일반 자식 요소입니다.

그러나 XAML에서는 이 구문이 매우 특별합니다. 속성 요소에 대한 규칙 중 하나는 태그에 Label.TextColor 다른 어떤 것도 표시할 수 없다는 것입니다. 속성 값은 항상 속성 요소 시작 태그와 끝 태그 사이의 콘텐츠로 정의됩니다.

두 개 이상의 속성에 속성 요소 구문을 사용할 수 있습니다.

<Label Text="Hello, XAML!"
       VerticalOptions="Center">
    <Label.FontAttributes>
        Bold
    </Label.FontAttributes>
    <Label.FontSize>
        Large
    </Label.FontSize>
    <Label.TextColor>
        Aqua
    </Label.TextColor>
</Label>

또는 모든 속성에 속성 요소 구문을 사용할 수 있습니다.

<Label>
    <Label.Text>
        Hello, XAML!
    </Label.Text>
    <Label.FontAttributes>
        Bold
    </Label.FontAttributes>
    <Label.FontSize>
        Large
    </Label.FontSize>
    <Label.TextColor>
        Aqua
    </Label.TextColor>
    <Label.VerticalOptions>
        Center
    </Label.VerticalOptions>
</Label>

처음에 속성 요소 구문은 비교적 매우 간단한 항목에 대한 불필요한 긴 바람 대체처럼 보일 수 있으며, 이러한 예에서는 확실히 그 예입니다.

그러나 속성 값이 너무 복잡하여 단순 문자열로 표현될 수 없는 경우 속성 요소 구문이 필수적입니다. 속성 요소 태그 내에서 다른 개체를 인스턴스화하고 해당 속성을 설정할 수 있습니다. 예를 들어 속성 설정이 있는 값과 같은 VerticalOptionsLayoutOptions 속성을 명시적으로 설정할 수 있습니다.

<Label>
    ...
    <Label.VerticalOptions>
        <LayoutOptions Alignment="Center" />
    </Label.VerticalOptions>
</Label>

또 다른 예: 두 Grid 개의 속성이 이름이 지정 RowDefinitions 되고 ColumnDefinitions. 이러한 두 속성은 형식 RowDefinitionCollection 이며 컬렉션과 ColumnDefinition 개체입니다 RowDefinitionColumnDefinitionCollection. 이러한 컬렉션을 설정하려면 속성 요소 구문을 사용해야 합니다.

다음은 클래스에 대한 GridDemoPage XAML 파일의 시작 부분으로, 컬렉션 및 ColumnDefinitions 컬렉션에 대한 속성 요소 태그를 RowDefinitions 보여 줍니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.GridDemoPage"
             Title="Grid Demo Page">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        ...
    </Grid>
</ContentPage>

자동 크기 셀, 픽셀 너비 및 높이의 셀 및 별 설정을 정의하기 위한 약어 구문을 확인합니다.

연결된 속성

행과 열을 정의하려면 컬렉션 및 ColumnDefinitions 컬렉션에 RowDefinitions 대한 속성 요소가 필요하다는 것을 살펴보 Grid 았습니다. 그러나 프로그래머가 각 자식 Grid 이 있는 행과 열을 나타내는 방법도 있어야 합니다.

각 자식의 Grid 태그 내에서 다음 특성을 사용하여 해당 자식의 행과 열을 지정합니다.

  • Grid.Row
  • Grid.Column

이러한 특성의 기본값은 0입니다. 자식이 다음 특성을 사용하여 둘 이상의 행 또는 열에 걸쳐 있는지 여부를 나타낼 수도 있습니다.

  • Grid.RowSpan
  • Grid.ColumnSpan

이러한 두 특성의 기본값은 1입니다.

전체 GridDemoPage.xaml 파일은 다음과 같습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.GridDemoPage"
             Title="Grid Demo Page">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>

        <Label Text="Autosized cell"
               Grid.Row="0" Grid.Column="0"
               TextColor="White"
               BackgroundColor="Blue" />

        <BoxView Color="Silver"
                 HeightRequest="0"
                 Grid.Row="0" Grid.Column="1" />

        <BoxView Color="Teal"
                 Grid.Row="1" Grid.Column="0" />

        <Label Text="Leftover space"
               Grid.Row="1" Grid.Column="1"
               TextColor="Purple"
               BackgroundColor="Aqua"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

        <Label Text="Span two rows (or more if you want)"
               Grid.Row="0" Grid.Column="2" Grid.RowSpan="2"
               TextColor="Yellow"
               BackgroundColor="Blue"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

        <Label Text="Span two columns"
               Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
               TextColor="Blue"
               BackgroundColor="Yellow"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

        <Label Text="Fixed 100x100"
               Grid.Row="2" Grid.Column="2"
               TextColor="Aqua"
               BackgroundColor="Red"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

    </Grid>
</ContentPage>

0의 설정은 Grid.RowGrid.Column 필요하지 않지만 일반적으로 명확성을 위해 포함됩니다.

모양은 다음과 같습니다.

그리드 레이아웃

구문에서만 판단하면 이러한 , , 및 특성이 정적 필드 또는 속성인 Grid것처럼 보이지만 흥미롭게 Grid 도 이름이 지정된 RowRowSpanColumnSpanColumn것을 정의하지는 않습니다.Grid.ColumnSpanGrid.RowSpanGrid.ColumnGrid.Row

대신 , GridColumnSpanProperty.라는 RowPropertyColumnPropertyRowSpanProperty네 개의 바인딩 가능한 속성을 정의합니다. 연결된 속성이라고 하는 바인딩 가능한 속성의 특수 형식입니다. 클래스에 의해 정의되지만 해당 Grid 클래스의 자식에 설정됩니다 Grid.

코드에서 이러한 연결된 속성을 사용하려는 경우 클래스는 Grid 명명된 SetRowGetColumn정적 메서드 등을 제공합니다. 그러나 XAML에서 이러한 연결된 속성은 using 단순 속성 이름의 자식 Grid 에서 특성으로 설정됩니다.

연결된 속성은 클래스와 속성 이름을 마침표로 구분하여 포함하는 특성으로 XAML 파일에서 항상 인식할 수 있습니다. 연결된 속성은 한 클래스(이 경우Grid)로 정의되지만 다른 개체(이 경우의 Grid자식)에 연결되기 때문에 연결된 속성이라고 합니다. 레이아웃 중에 Grid 이러한 연결된 속성의 값을 심문하여 각 자식의 위치를 알 수 있습니다.

클래스는 AbsoluteLayout 명명 LayoutBounds 된 두 개의 연결된 속성과 LayoutFlags. 다음은 다음의 비례 위치 지정 및 크기 조정 기능을 사용하여 구현된 검사erboard 패턴입니다AbsoluteLayout.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.AbsoluteDemoPage"
             Title="Absolute Demo Page">

    <AbsoluteLayout BackgroundColor="#FF8080">
        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.33, 0, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="1, 0, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0, 0.33, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.67, 0.33, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.33, 0.67, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="1, 0.67, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0, 1, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.67, 1, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

  </AbsoluteLayout>
</ContentPage>

결과는 다음과 같습니다.

절대 레이아웃

이와 같은 경우 XAML을 사용하는 지혜에 의문을 제기할 수 있습니다. 물론 직사각형의 LayoutBounds 반복과 규칙성은 코드에서 더 잘 실현될 수 있음을 시사합니다.

이는 확실히 합법적인 문제이며 사용자 인터페이스를 정의할 때 코드 및 태그 사용의 균형을 맞추는 데 아무런 문제가 없습니다. XAML에서 일부 시각적 개체를 정의한 다음 코드 숨김 파일의 생성자를 사용하여 루프에서 더 잘 생성될 수 있는 시각적 개체를 추가할 수 있습니다.

콘텐츠 속성

이전 예제StackLayout에서 , GridAbsoluteLayout 개체는 해당 속성ContentPage으로 Content 설정되며 이러한 레이아웃의 자식은 실제로 컬렉션의 Children 항목입니다. 그러나 이러한 Content 속성과 Children 속성은 XAML 파일에 없습니다.

XamlPlusCode 샘플과 같은 속성 요소로 및 Children 속성을 포함 Content수 있습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.XamlPlusCodePage"
             Title="XAML + Code Page">
    <ContentPage.Content>
        <StackLayout>
            <StackLayout.Children>
                <Slider VerticalOptions="CenterAndExpand"
                        ValueChanged="OnSliderValueChanged" />

                <Label x:Name="valueLabel"
                       Text="A simple Label"
                       FontSize="Large"
                       HorizontalOptions="Center"
                       VerticalOptions="CenterAndExpand" />

                <Button Text="Click Me!"
                      HorizontalOptions="Center"
                      VerticalOptions="CenterAndExpand"
                      Clicked="OnButtonClicked" />
            </StackLayout.Children>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

진짜 질문은 : 왜 이러한 속성 요소는 XAML 파일에 필요하지 않습니다 ?

XAML에서 Xamarin.Forms 사용하기 위해 정의된 요소는 클래스의 ContentProperty 특성에 플래그가 지정된 속성 하나를 가질 수 있습니다. 온라인 Xamarin.Forms 설명서에서 클래스를 ContentPage 조회하면 다음 특성이 표시됩니다.

[Xamarin.Forms.ContentProperty("Content")]
public class ContentPage : TemplatedPage

Content , 속성 요소 태그가 필요하지 않습니다. 시작 태그와 끝 ContentPage 태그 사이에 표시되는 모든 XML 콘텐츠는 속성에 Content 할당된 것으로 간주됩니다.

StackLayout, GridAbsoluteLayoutRelativeLayout 모든 파생 Layout<View>항목은 설명서에서 Xamarin.Forms 조회 Layout<T> 하는 경우 다른 ContentProperty 특성이 표시됩니다.

[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout ...

이를 통해 명시적 Children 속성 요소 태그 없이 레이아웃의 콘텐츠를 컬렉션에 Children 자동으로 추가할 수 있습니다.

다른 클래스에는 ContentProperty 특성 정의도 있습니다. 예를 들어 콘텐츠 속성은 Label .입니다 Text. 다른 사용자에 대한 API 설명서를 확인합니다.

OnPlatform과의 플랫폼 차이점

단일 페이지 애플리케이션에서는 iOS 상태 막대를 덮어쓰지 않도록 페이지에서 속성을 설정하는 Padding 것이 일반적입니다. 코드에서 이 용도로 Device.RuntimePlatform 속성을 사용할 수 있습니다.

if (Device.RuntimePlatform == Device.iOS)
{
    Padding = new Thickness(0, 20, 0, 0);
}

XAML에서 및 On 클래스를 사용하여 OnPlatform 비슷한 작업을 수행할 수도 있습니다. 먼저 페이지 위쪽에 있는 Padding 속성에 대한 속성 요소를 포함합니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>

    </ContentPage.Padding>
    ...
</ContentPage>

이러한 태그 내에 태그를 OnPlatform 포함합니다. OnPlatform 는 제네릭 클래스입니다. 제네릭 형식 인수(이 경우 Thickness속성 형식 Padding )를 지정해야 합니다. 다행히 XAML 특성은 특히 호출 x:TypeArguments된 제네릭 인수를 정의합니다. 설정 중인 속성의 형식과 일치해야 합니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">

        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

OnPlatform에는 개체의 속성이 IListOn 있습니다Platforms. 해당 속성에 속성 요소 태그를 사용합니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <OnPlatform.Platforms>

            </OnPlatform.Platforms>
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

이제 요소를 추가 On 합니다. 각 속성에 Platform 대해 속성 및 속성에 Value 대한 태그를 설정할 속성은 다음과 같습니다 Thickness .

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <OnPlatform.Platforms>
                <On Platform="iOS" Value="0, 20, 0, 0" />
                <On Platform="Android" Value="0, 0, 0, 0" />
                <On Platform="UWP" Value="0, 0, 0, 0" />
            </OnPlatform.Platforms>
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

이 태그는 간소화할 수 있습니다. 콘텐츠 속성 OnPlatformPlatforms다음과 같습니다. 따라서 이러한 속성 요소 태그를 제거할 수 있습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
            <On Platform="Android" Value="0, 0, 0, 0" />
            <On Platform="UWP" Value="0, 0, 0, 0" />
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

속성 OnPlatform 형식IList<string>이므로 값이 같으면 여러 플랫폼을 포함할 수 있습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
            <On Platform="Android, UWP" Value="0, 0, 0, 0" />
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Android 및 UWP는 기본값 Padding으로 설정되므로 해당 태그를 제거할 수 있습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

XAML에서 플랫폼 종속 Padding 속성을 설정하는 표준 방법입니다. Value 설정을 단일 문자열로 나타낼 수 없는 경우 해당 설정에 대한 속성 요소를 정의할 수 있습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS">
                <On.Value>
                    0, 20, 0, 0
                </On.Value>
            </On>
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

참고 항목

OnPlatform 태그 확장을 XAML에서 사용하여 플랫폼별로 UI 모양을 사용자 지정할 수도 있습니다. 클래스와 On 동일한 기능을 OnPlatform 제공하지만 보다 간결한 표현을 제공합니다. 자세한 내용은 OnPlatform 태그 확장을 참조 하세요.

요약

속성 요소 및 연결된 속성을 사용하여 대부분의 기본 XAML 구문이 설정되었습니다. 그러나 리소스 사전과 같이 간접적인 방식으로 속성을 개체로 설정해야 하는 경우도 있습니다. 이 방법은 다음 부분인 3부 에서 다룹니다. XAML 태그 확장입니다.