Xamarin.Forms 상대 바인딩

Download Sample 샘플 다운로드

상대 바인딩을 사용하면 바인딩 대상의 위치에 상대적으로 바인딩 소스를 설정할 수 있습니다. 상대 바인딩은 RelativeSource 태그 확장을 사용하여 생성되며, 바인딩 식의 Source 속성으로 설정됩니다.

RelativeSource 태그 확장은 다음 속성을 정의하는 RelativeSourceExtension 클래스에서 지원됩니다.

  • RelativeBindingSourceMode 형식의 Mode: 바인딩 대상의 위치에 상대적으로 바인딩 소스의 위치를 설명합니다.
  • int 형식의 AncestorLevel: Mode 속성이 FindAncestor인 경우 살펴보아야 할 선택적 상위 항목 수준입니다. nAncestorLevel은(는) AncestorTypen-1 인스턴스를 건너뜁니다.
  • Type 형식의 AncestorType: Mode 속성이 FindAncestor인 경우 살펴보아야 할 상위 항목 유형입니다.

참고 항목

XAML 파서를 사용하면 RelativeSourceExtension 클래스를 RelativeSource로 축약할 수 있습니다.

Mode 속성은 RelativeBindingSourceMode 열거형 멤버 중 하나로 설정되어야 합니다.

  • TemplatedParent: 바운드 요소가 존재하는 템플릿이 적용되는 요소를 나타냅니다. 자세한 내용은 템플릿화된 부모에 바인딩을 참조하세요.
  • Self: 바인딩이 설정되는 요소를 나타냅니다. 해당 요소의 속성 하나를 동일한 요소의 다른 속성에 바인딩할 수 있습니다. 자세한 내용은 자기 자신에게 바인딩을 참조하세요.
  • FindAncestor: 바운드 요소의 시각적 트리에 있는 상위 항목을 나타냅니다. 이 모드는 AncestorType 속성으로 표현되는 상위 항목 컨트롤에 바인딩하는 데 사용해야 합니다. 자세한 내용은 상위 항목에 바인딩을 참조하세요.
  • FindAncestorBindingContext: 바운드 요소의 시각적 트리에 있는 상위 항목의 BindingContext를 나타냅니다. 이 모드는 AncestorType 속성으로 표현되는 상위 항목의 BindingContext에 바인딩하는 데 사용해야 합니다. 자세한 내용은 상위 항목에 바인딩을 참조하세요.

Mode 속성은 RelativeSourceExtension 클래스의 콘텐츠 속성입니다. 따라서 중괄호가 사용된 XAML 태그 식의 경우 식의 Mode= 부분을 제거할 수 있습니다.

Xamarin.Forms 태그 확장에 대한 자세한 내용은 XAML 태그 확장을 참조하세요.

자기 자신에게 바인딩

Self 상대 바인딩 모드는 요소의 속성을 동일한 요소의 다른 속성에 바인딩하는 데 사용됩니다.

<BoxView Color="Red"
         WidthRequest="200"
         HeightRequest="{Binding Source={RelativeSource Self}, Path=WidthRequest}"
         HorizontalOptions="Center" />

이 예제에서 BoxViewWidthRequest 속성을 고정된 크기로 설정하고 HeightRequest 속성은 WidthRequest 속성에 바인딩됩니다. 따라서 두 속성은 동일하며 다음과 같이 정사각형이 그려집니다.

Screenshot of a Self mode relative binding, on iOS and Android

Important

요소의 속성을 동일한 요소의 다른 속성에 바인딩할 때는 두 속성의 유형이 같아야 합니다. 또는 바인딩에 값을 변환하는 변환기를 지정할 수도 있습니다.

이 바인딩 모드는 개체의 BindingContext를 자기 자신의 속성에 설정하는 용도로 자주 사용됩니다. 다음 코드에서 그 예를 볼 수 있습니다.

<ContentPage ...
             BindingContext="{Binding Source={RelativeSource Self}, Path=DefaultViewModel}">
    <StackLayout>
        <ListView ItemsSource="{Binding Employees}">
            ...
        </ListView>
    </StackLayout>
</ContentPage>

이 예제에서, 페이지의 BindingContext가 자기 자신의 DefaultViewModel 속성으로 설정되었습니다. 이 속성은 페이지의 코드 숨김 파일에 정의되어 있으며, viewmodel 인스턴스를 제공합니다. ListView는 viewmodel의 Employees 속성에 바인딩됩니다.

상위 항목에 바인딩

FindAncestorFindAncestorBindingContext 상대 바인딩 모드는 시각적 트리에서 특정 유형의 부모 요소에 바인딩하는 데 사용됩니다. FindAncestor 모드는 Element 형식에서 파생되는 부모 요소에 바인딩하는 데 사용됩니다. FindAncestorBindingContext 모드는 부모 요소의 BindingContext에 바인딩하는 데 사용됩니다.

Warning

FindAncestorFindAncestorBindingContext 상대 바인딩 모드를 사용할 때는 AncestorType 속성을 Type으로 설정해야 합니다. 그러지 않으면 XamlParseException이 throw됩니다.

Mode 속성이 명시적으로 설정되지 않은 경우, AncestorType 속성을 Element에서 파생된 형식으로 설정하면 Mode 속성이 암시적으로 FindAncestor로 설정됩니다. 마찬가지로, AncestorType 속성을 Element에서 파생되지 않은 형식으로 설정하면 Mode 속성이 암시적으로 FindAncestorBindingContext로 설정됩니다.

참고 항목

FindAncestorBindingContext 모드를 사용하는 상대 바인딩은 모든 상위 항목의 BindingContext이(가) 변경될 때 다시 적용됩니다.

다음 XAML은 Mode 속성이 암시적으로 FindAncestorBindingContext로 설정되는 예제를 보여 줍니다.

<ContentPage ...
             BindingContext="{Binding Source={RelativeSource Self}, Path=DefaultViewModel}">
    <StackLayout>
        <ListView ItemsSource="{Binding Employees}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal">
                            <Label Text="{Binding Fullname}"
                                   VerticalOptions="Center" />
                            <Button Text="Delete"
                                    Command="{Binding Source={RelativeSource AncestorType={x:Type local:PeopleViewModel}}, Path=DeleteEmployeeCommand}"
                                    CommandParameter="{Binding}"
                                    HorizontalOptions="EndAndExpand" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

이 예제에서, 페이지의 BindingContext가 자기 자신의 DefaultViewModel 속성으로 설정되었습니다. 이 속성은 페이지의 코드 숨김 파일에 정의되어 있으며, viewmodel 인스턴스를 제공합니다. ListView는 viewmodel의 Employees 속성에 바인딩됩니다. ListView의 각 항목의 모양을 정의하는 DataTemplateButton을 포함합니다. 단추의 Command 속성은 부모의 viewmodel에서 DeleteEmployeeCommand에 바인딩되어 있습니다. Button을 탭하면 직원 한 명이 삭제됩니다.

Screenshot of a FindAncestor mode relative binding, on iOS and Android

이에 더해, 선택적 AncestorLevel 속성은 시각적 트리에 특정 유형의 상위 항목이 둘 이상 있는 경우 상위 항목을 쉽게 구분하는 데 도움이 됩니다.

<Label Text="{Binding Source={RelativeSource AncestorType={x:Type Entry}, AncestorLevel=2}, Path=Text}" />

이 예제에서 Label.Text 속성은 바인딩의 대상 요소에서 시작하는 상향 경로에서 발견된 두 번째 EntryText 속성에 바인딩됩니다.

참고 항목

AncestorLevel 속성은 바인딩 대상 요소에 가장 가까운 상위 항목을 찾도록 1로 설정되어야 합니다.

템플릿화된 부모에 바인딩

TemplatedParent 상대 바인딩 모드는 컨트롤 템플릿 내부에서 해당 템플릿이 적용되는 런타임 개체 인스턴스(템플릿화된 부모)에 바인딩하는 데 사용됩니다. 이 모드는 상대 바인딩이 컨트롤 템플릿 내부에 있는 경우에만 적용되며, TemplateBinding을 설정하는 것과 비슷합니다.

다음 XAML은 TemplatedParent 상대 바인딩 모드의 예를 보여 줍니다.

<ContentPage ...>
    <ContentPage.Resources>
        <ControlTemplate x:Key="CardViewControlTemplate">
            <Frame BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
                   BackgroundColor="{Binding CardColor}"
                   BorderColor="{Binding BorderColor}"
                   ...>
                <Grid>
                    ...
                    <Label Text="{Binding CardTitle}"
                           ... />
                    <BoxView BackgroundColor="{Binding BorderColor}"
                             ... />
                    <Label Text="{Binding CardDescription}"
                           ... />
                </Grid>
            </Frame>
        </ControlTemplate>
    </ContentPage.Resources>
    <StackLayout>        
        <controls:CardView BorderColor="DarkGray"
                           CardTitle="John Doe"
                           CardDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elit dolor, convallis non interdum."
                           IconBackgroundColor="SlateGray"
                           IconImageSource="user.png"
                           ControlTemplate="{StaticResource CardViewControlTemplate}" />
        <controls:CardView BorderColor="DarkGray"
                           CardTitle="Jane Doe"
                           CardDescription="Phasellus eu convallis mi. In tempus augue eu dignissim fermentum. Morbi ut lacus vitae eros lacinia."
                           IconBackgroundColor="SlateGray"
                           IconImageSource="user.png"
                           ControlTemplate="{StaticResource CardViewControlTemplate}" />
        <controls:CardView BorderColor="DarkGray"
                           CardTitle="Xamarin Monkey"
                           CardDescription="Aliquam sagittis, odio lacinia fermentum dictum, mi erat scelerisque erat, quis aliquet arcu."
                           IconBackgroundColor="SlateGray"
                           IconImageSource="user.png"
                           ControlTemplate="{StaticResource CardViewControlTemplate}" />
    </StackLayout>
</ContentPage>

이 예제에서, ControlTemplate의 루트 요소인 FrameBindingContext는 해당 템플릿이 적용되는 런타임 개체 인스턴스로 설정됩니다. 따라서 Frame과 그 자식은 각 CardView 개체의 속성에 대해 바인딩 식이 확인됩니다.

Screenshot of a TemplatedParent mode relative binding, on iOS and Android

컨트롤 템플릿에 대한 자세한 내용은 Xamarin.Forms 컨트롤 템플릿을 참조하세요.