Xamarin.Forms 상대 바인딩Xamarin.Forms Relative Bindings

샘플 다운로드 샘플 다운로드Download Sample Download the sample

상대 바인딩을 사용하면 바인딩 대상의 위치에 상대적으로 바인딩 소스를 설정할 수 있습니다.Relative bindings provide the ability to set the binding source relative to the position of the binding target. 상대 바인딩은 RelativeSource 태그 확장을 사용하여 생성되며, 바인딩 식의 Source 속성으로 설정됩니다.They are created with the RelativeSource markup extension, and set as the Source property of a binding expression.

RelativeSource 태그 확장은 다음 속성을 정의하는 RelativeSourceExtension 클래스에서 지원됩니다.The RelativeSource markup extension is supported by the RelativeSourceExtension class, which defines the following properties:

  • RelativeBindingSourceMode 형식의 Mode: 바인딩 대상의 위치에 상대적으로 바인딩 소스의 위치를 설명합니다.Mode, of type RelativeBindingSourceMode, describes the location of the binding source relative to the position of the binding target.
  • int 형식의 AncestorLevel: Mode 속성이 FindAncestor인 경우 살펴보아야 할 선택적 상위 항목 수준입니다.AncestorLevel, of type int, an optional ancestor level to look for, when the Mode property is FindAncestor.
  • Type 형식의 AncestorType: Mode 속성이 FindAncestor인 경우 살펴보아야 할 상위 항목 유형입니다.AncestorType, of type Type, the type of ancestor to look for, when the Mode property is FindAncestor.

참고

XAML 파서를 사용하면 RelativeSourceExtension 클래스를 RelativeSource로 축약할 수 있습니다.The XAML parser allows the RelativeSourceExtension class to be abbreviated as RelativeSource.

Mode 속성은 RelativeBindingSourceMode 열거형 멤버 중 하나로 설정되어야 합니다.The Mode property should be set to one of the RelativeBindingSourceMode enumeration members:

  • TemplatedParent: 바운드 요소가 존재하는 템플릿이 적용되는 요소를 나타냅니다.TemplatedParent indicates the element to which the template, in which the bound element exists, is applied. 자세한 내용은 템플릿화된 부모에 바인딩을 참조하세요.For more information, see Bind to a templated parent.
  • Self: 바인딩이 설정되는 요소를 나타냅니다. 해당 요소의 속성 하나를 동일한 요소의 다른 속성에 바인딩할 수 있습니다.Self indicates the element on which the binding is being set, allowing you to bind one property of that element to another property on the same element. 자세한 내용은 자기 자신에게 바인딩을 참조하세요.For more information, see Bind to self.
  • FindAncestor: 바운드 요소의 시각적 트리에 있는 상위 항목을 나타냅니다.FindAncestor indicates the ancestor in the visual tree of the bound element. 이 모드는 AncestorType 속성으로 표현되는 상위 항목 컨트롤에 바인딩하는 데 사용해야 합니다.This mode should be used to bind to an ancestor control represented by the AncestorType property. 자세한 내용은 상위 항목에 바인딩을 참조하세요.For more information, see Bind to an ancestor.
  • FindAncestorBindingContext: 바운드 요소의 시각적 트리에 있는 상위 항목의 BindingContext를 나타냅니다.FindAncestorBindingContext indicates the BindingContext of the ancestor in the visual tree of the bound element. 이 모드는 AncestorType 속성으로 표현되는 상위 항목의 BindingContext에 바인딩하는 데 사용해야 합니다.This mode should be used to bind to the BindingContext of an ancestor represented by the AncestorType property. 자세한 내용은 상위 항목에 바인딩을 참조하세요.For more information, see Bind to an ancestor.

Mode 속성은 RelativeSourceExtension 클래스의 콘텐츠 속성입니다.The Mode property is the content property of the RelativeSourceExtension class. 따라서 중괄호가 사용된 XAML 태그 식의 경우 식의 Mode= 부분을 제거할 수 있습니다.Therefore, for XAML markup expressions expressed with curly braces, you can eliminate the Mode= part of the expression.

Xamarin.Forms 태그 확장에 대한 자세한 내용은 XAML 태그 확장을 참조하세요.For more information about Xamarin.Forms markup extensions, see XAML Markup Extensions.

자기 자신에게 바인딩Bind to self

Self 상대 바인딩 모드는 요소의 속성을 동일한 요소의 다른 속성에 바인딩하는 데 사용됩니다.The Self relative binding mode is used bind a property of an element to another property on the same element:

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

이 예제에서 BoxViewWidthRequest 속성을 고정된 크기로 설정하고 HeightRequest 속성은 WidthRequest 속성에 바인딩됩니다.In this example, the BoxView sets its WidthRequest property to a fixed size, and the HeightRequest property binds to the WidthRequest property. 따라서 두 속성은 동일하며 다음과 같이 정사각형이 그려집니다.Therefore, both properties are equal and so a square is drawn:

iOS 및 Android의 셀프 모드 상대 바인딩 스크린샷Screenshot of a Self mode relative binding, on iOS and Android

중요

요소의 속성을 동일한 요소의 다른 속성에 바인딩할 때는 두 속성의 유형이 같아야 합니다.When binding a property of an element to another property on the same element, the properties must be the same type. 또는 바인딩에 값을 변환하는 변환기를 지정할 수도 있습니다.Alternatively, you can specify a converter on the binding to convert the value.

이 바인딩 모드는 개체의 BindingContext를 자기 자신의 속성에 설정하는 용도로 자주 사용됩니다.A common use of this binding mode is set an object's BindingContext to a property on itself. 다음 코드에서 그 예를 볼 수 있습니다.The following code shows an example of this:

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

이 예제에서, 페이지의 BindingContext가 자기 자신의 DefaultViewModel 속성으로 설정되었습니다.In this example, the BindingContext of the page is set to the DefaultViewModel property of itself. 이 속성은 페이지의 코드 숨김 파일에 정의되어 있으며, viewmodel 인스턴스를 제공합니다.This property is defined in the code-behind file for the page, and provides a viewmodel instance. ListView는 viewmodel의 Employees 속성에 바인딩됩니다.The ListView binds to the Employees property of the viewmodel.

상위 항목에 바인딩Bind to an ancestor

FindAncestorFindAncestorBindingContext 상대 바인딩 모드는 시각적 트리에서 특정 유형의 부모 요소에 바인딩하는 데 사용됩니다.The FindAncestor and FindAncestorBindingContext relative binding modes are used to bind to parent elements, of a certain type, in the visual tree. FindAncestor 모드는 Element 형식에서 파생되는 부모 요소에 바인딩하는 데 사용됩니다.The FindAncestor mode is used to bind to a parent element, which derives from the Element type. FindAncestorBindingContext 모드는 부모 요소의 BindingContext에 바인딩하는 데 사용됩니다.The FindAncestorBindingContext mode is used to bind to the BindingContext of a parent element.

경고

FindAncestorFindAncestorBindingContext 상대 바인딩 모드를 사용할 때는 AncestorType 속성을 Type으로 설정해야 합니다. 그러지 않으면 XamlParseException이 throw됩니다.The AncestorType property must be set to a Type when using the FindAncestor and FindAncestorBindingContext relative binding modes, otherwise a XamlParseException is thrown.

Mode 속성이 명시적으로 설정되지 않은 경우, AncestorType 속성을 Element에서 파생된 형식으로 설정하면 Mode 속성이 암시적으로 FindAncestor로 설정됩니다.If the Mode property isn't explicitly set, setting the AncestorType property to a type that derives from Element will implicitly set the Mode property to FindAncestor. 마찬가지로, AncestorType 속성을 Element에서 파생되지 않은 형식으로 설정하면 Mode 속성이 암시적으로 FindAncestorBindingContext로 설정됩니다.Similarly, setting the AncestorType property to a type that does not derive from Element will implicitly set the Mode property to FindAncestorBindingContext.

다음 XAML은 Mode 속성이 암시적으로 FindAncestorBindingContext로 설정되는 예제를 보여 줍니다.The following XAML shows an example where the Mode property will be implicitly set to 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 속성으로 설정되었습니다.In this example, the BindingContext of the page is set to the DefaultViewModel property of itself. 이 속성은 페이지의 코드 숨김 파일에 정의되어 있으며, viewmodel 인스턴스를 제공합니다.This property is defined in the code-behind file for the page, and provides a viewmodel instance. ListView는 viewmodel의 Employees 속성에 바인딩됩니다.The ListView binds to the Employees property of the viewmodel. ListView의 각 항목의 모양을 정의하는 DataTemplateButton을 포함합니다.The DataTemplate, which defines the appearance of each item in the ListView, contains a Button. 단추의 Command 속성은 부모의 viewmodel에서 DeleteEmployeeCommand에 바인딩되어 있습니다.The button's Command property is bound to the DeleteEmployeeCommand in its parent's viewmodel. Button을 탭하면 직원 한 명이 삭제됩니다.Tapping a Button deletes an employee:

iOS 및 Android의 FindAncestor 모드 상대 바인딩 스크린샷Screenshot of a FindAncestor mode relative binding, on iOS and Android

이에 더해, 선택적 AncestorLevel 속성은 시각적 트리에 특정 유형의 상위 항목이 둘 이상 있는 경우 상위 항목을 쉽게 구분하는 데 도움이 됩니다.In addition, the optional AncestorLevel property can help disambiguate ancestor lookup in scenarios where there is possibly more than one ancestor of that type in the visual tree:

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

이 예제에서 Label.Text 속성은 바인딩의 대상 요소에서 시작하는 상향 경로에서 발견된 두 번째 EntryText 속성에 바인딩됩니다.In this example, the Label.Text property binds to the Text property of the second Entry that's encountered on the upward path, starting at the target element of the binding.

참고

AncestorLevel 속성은 바인딩 대상 요소에 가장 가까운 상위 항목을 찾도록 1로 설정되어야 합니다.The AncestorLevel property should be set to 1 to find the ancestor nearest to the binding target element.

템플릿화된 부모에 바인딩Bind to a templated parent

TemplatedParent 상대 바인딩 모드는 컨트롤 템플릿 내부에서 해당 템플릿이 적용되는 런타임 개체 인스턴스(템플릿화된 부모)에 바인딩하는 데 사용됩니다.The TemplatedParent relative binding mode is used to bind from within a control template to the runtime object instance to which the template is applied (known as the templated parent). 이 모드는 상대 바인딩이 컨트롤 템플릿 내부에 있는 경우에만 적용되며, TemplateBinding을 설정하는 것과 비슷합니다.This mode is only applicable if the relative binding is within a control template, and is similar to setting a TemplateBinding.

다음 XAML은 TemplatedParent 상대 바인딩 모드의 예를 보여 줍니다.The following XAML shows an example of the TemplatedParent relative binding mode:

<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는 해당 템플릿이 적용되는 런타임 개체 인스턴스로 설정됩니다.In this example, the Frame, which is the root element of the ControlTemplate, has its BindingContext set to the runtime object instance to which the template is applied. 따라서 Frame과 그 자식은 각 CardView 개체의 속성에 대해 바인딩 식이 확인됩니다.Therefore, the Frame and its children resolve their binding expressions against the properties of each CardView object:

iOS 및 Android의 TemplatedParent 모드 상대 바인딩 스크린샷Screenshot of a TemplatedParent mode relative binding, on iOS and Android

컨트롤 템플릿에 대한 자세한 내용은 Xamarin.Forms 컨트롤 템플릿을 참조하세요.For more information about control templates, see Xamarin.Forms Control Templates.