Xamarin.Forms 기본 바인딩Xamarin.Forms Basic Bindings

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

Xamarin.Forms 데이터 바인딩은 두 개의 개체 사이의 속성 쌍을 연결하며, 이러한 개체 중 적어도 하나는 일반적으로 사용자 인터페이스 개체입니다.A Xamarin.Forms data binding links a pair of properties between two objects, at least one of which is usually a user-interface object. 이러한 두 개체는 대상원본이라고 합니다.These two objects are called the target and the source:

  • 대상은 데이터 바인딩이 설정된 개체(및 속성)입니다.The target is the object (and property) on which the data binding is set.
  • 원본은 데이터 바인딩에서 참조하는 개체(및 속성)입니다.The source is the object (and property) referenced by the data binding.

이 구분은 경우에 따라 다소 혼란스러울 수 있습니다. 가장 간단한 경우 데이터는 소스에서 대상으로 이동합니다. 즉 대상 속성의 값이 소스 속성의 값에서 설정됩니다.This distinction can sometimes be a little confusing: In the simplest case, data flows from the source to the target, which means that the value of the target property is set from the value of the source property. 하지만 어떤 경우에는 데이터가 대상에서 원본으로 또는 양방향으로 이동할 수 있습니다.However, in some cases, data can alternatively flow from the target to the source, or in both directions. 혼란을 방지하기 위해 데이터를 받는 것이 아니라 데이터를 제공하는 경우에도 대상이 항상 데이터 바인딩이 설정된 개체라는 점을 명심하세요.To avoid confusion, keep in mind that the target is always the object on which the data binding is set even if it's providing data rather than receiving data.

바인딩 컨텍스트가 있는 바인딩Bindings with a Binding Context

데이터 바인딩은 일반적으로 XAML에 완전히 지정되지만 코드에서 데이터 바인딩을 확인하는 것이 좋습니다.Although data bindings are usually specified entirely in XAML, it's instructive to see data bindings in code. 기본 코드 바인딩 페이지에는 LabelSlider가 있는 XAML 파일이 포함됩니다.The Basic Code Binding page contains a XAML file with a Label and a Slider:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DataBindingDemos.BasicCodeBindingPage"
             Title="Basic Code Binding">
    <StackLayout Padding="10, 0">
        <Label x:Name="label"
               Text="TEXT"
               FontSize="48"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <Slider x:Name="slider"
                Maximum="360"
                VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

Slider는 0 - 360의 범위로 설정됩니다.The Slider is set for a range of 0 to 360. 이 프로그램의 목적은 Slider를 조작하여 Label을 회전시키는 것입니다.The intent of this program is to rotate the Label by manipulating the Slider.

데이터 바인딩이 없으면 SliderValueChanged 이벤트를 SliderValue 속성에 액세스하고 해당 값을 LabelRotation 속성으로 설정하는 이벤트 처리기로 설정합니다.Without data bindings, you would set the ValueChanged event of the Slider to an event handler that accesses the Value property of the Slider and sets that value to the Rotation property of the Label. 데이터 바인딩은 이 작업을 자동화하므로 이벤트 처리기와 그 안에 있는 코드가 더 이상 필요하지 않습니다.The data binding automates that job; the event handler and the code within it are no longer necessary.

Element, VisualElement, ViewView 파생문이 포함된 BindableObject에서 파생되는 모든 클래스의 인스턴스에 바인딩을 설정할 수 있습니다.You can set a binding on an instance of any class that derives from BindableObject, which includes Element, VisualElement, View, and View derivatives. 바인딩은 항상 대상 개체에 설정됩니다.The binding is always set on the target object. 바인딩은 원본 개체를 참조합니다.The binding references the source object. 데이터 바인딩을 설정하려면 대상 클래스의 다음 두 멤버를 사용합니다.To set the data binding, use the following two members of the target class:

  • BindingContext 속성은 원본 개체를 지정합니다.The BindingContext property specifies the source object.
  • SetBinding 메서드는 대상 속성 및 원본 속성을 지정합니다.The SetBinding method specifies the target property and source property.

이 예제에서 Label은 바인딩 대상이고 Slider는 바인딩 원본입니다.In this example, the Label is the binding target, and the Slider is the binding source. Slider 원본의 변경은 Label 대상의 회전에 영향을 줍니다.Changes in the Slider source affect the rotation of the Label target. 데이터는 원본에서 대상으로 이동합니다.Data flows from the source to the target.

BindableObject에서 정의된 SetBinding 메서드에 Binding 클래스에서 파생되는 BindingBase 형식의 인수가 있지만, BindableObjectExtensions 클래스에서 정의된 다른 SetBinding 메서드가 있습니다.The SetBinding method defined by BindableObject has an argument of type BindingBase from which the Binding class derives, but there are other SetBinding methods defined by the BindableObjectExtensions class. 기본 코드 바인딩 샘플의 코드 숨김 파일은 이 클래스의 더 간단한 SetBinding 확장 메서드를 사용합니다.The code-behind file in the Basic Code Binding sample uses a simpler SetBinding extension method from this class.

public partial class BasicCodeBindingPage : ContentPage
{
    public BasicCodeBindingPage()
    {
        InitializeComponent();

        label.BindingContext = slider;
        label.SetBinding(Label.RotationProperty, "Value");
    }
}

Label 개체는 바인딩 대상이므로 이 속성이 설정되고 메서드가 호출되는 개체입니다.The Label object is the binding target so that's the object on which this property is set and on which the method is called. BindingContext 속성은 바인딩 원본, 즉 Slider를 나타냅니다.The BindingContext property indicates the binding source, which is the Slider.

SetBinding 메서드는 바인딩 대상에서 호출되지만 대상 속성과 원본 속성을 모두 지정합니다.The SetBinding method is called on the binding target but specifies both the target property and the source property. 대상 속성은 BindableProperty 개체, 즉 Label.RotationProperty로 지정됩니다.The target property is specified as a BindableProperty object: Label.RotationProperty. 원본 속성은 문자열로 지정되고 SliderValue 속성을 나타냅니다.The source property is specified as a string and indicates the Value property of Slider.

SetBinding 메서드는 데이터 바인딩의 가장 중요한 규칙 중 하나를 표시합니다.The SetBinding method reveals one of the most important rules of data bindings:

대상 속성은 바인딩 가능한 속성으로 지원되어야 합니다.The target property must be backed by a bindable property.

이 규칙은 대상 개체가 BindableObject에서 파생되는 클래스의 인스턴스여야 함을 암시합니다.This rule implies that the target object must be an instance of a class that derives from BindableObject. 바인딩 가능한 개체 및 속성에 대한 개요는 바인딩 가능한 속성 문서를 참조하세요.See the Bindable Properties article for an overview of bindable objects and bindable properties.

문자열로 지정된 원본 속성에 대해 이러한 규칙은 없습니다.There is no such rule for the source property, which is specified as a string. 내부적으로 리플렉션은 실제 속성에 액세스하는 데 사용됩니다.Internally, reflection is used to access the actual property. 그러나 이 특별한 경우에는 Value 속성도 바인딩 가능한 속성으로 지원됩니다.In this particular case, however, the Value property is also backed by a bindable property.

코드는 다소 간소화될 수 있습니다. 즉, RotationProperty 바인딩 가능한 속성은 VisualElement에서 정의되고 LabelContentPage에도 상속되므로 SetBinding 호출에서 클래스 이름이 필요하지 않습니다.The code can be simplified somewhat: The RotationProperty bindable property is defined by VisualElement, and inherited by Label and ContentPage as well, so the class name isn't required in the SetBinding call:

label.SetBinding(RotationProperty, "Value");

그러나 클래스 이름이 포함되면 대상 개체를 알리는 데 도움이 됩니다.However, including the class name is a good reminder of the target object.

Slider를 조작하면 이에 따라 Label이 회전합니다.As you manipulate the Slider, the Label rotates accordingly:

기본 코드 바인딩Basic Code Binding

기본 Xaml 바인딩 페이지는 XAML에서 전체 데이터 바인딩을 정의한다는 점을 제외하고는 기본 코드 바인딩과 동일합니다.The Basic Xaml Binding page is identical to Basic Code Binding except that it defines the entire data binding in XAML:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DataBindingDemos.BasicXamlBindingPage"
             Title="Basic XAML Binding">
    <StackLayout Padding="10, 0">
        <Label Text="TEXT"
               FontSize="80"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               BindingContext="{x:Reference Name=slider}"
               Rotation="{Binding Path=Value}" />

        <Slider x:Name="slider"
                Maximum="360"
                VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

코드에서와 마찬가지로 데이터 바인딩은 대상 개체, 즉 Label에 설정됩니다.Just as in code, the data binding is set on the target object, which is the Label. 두 개의 XAML 태그 확장이 포함됩니다.Two XAML markup extensions are involved. 이러한 확장은 중괄호 구분 기호로 즉시 인식할 수 있습니다.These are instantly recognizable by the curly brace delimiters:

  • x:Reference 태그 확장은 원본 개체, 즉 slider라는 Slider를 참조하는 데 필요합니다.The x:Reference markup extension is required to reference the source object, which is the Slider named slider.
  • Binding 태그 확장에서 LabelRotation 속성을 SliderValue 속성에 연결합니다.The Binding markup extension links the Rotation property of the Label to the Value property of the Slider.

XAML 태그 확장에 대한 자세한 내용은 XAML 태그 확장 문서를 참조하세요.See the article XAML Markup Extensions for more information about XAML markup extensions. x:Reference 태그 확장은 ReferenceExtension 클래스에서 지원되고, BindingBindingExtension 클래스에서 지원됩니다.The x:Reference markup extension is supported by the ReferenceExtension class; Binding is supported by the BindingExtension class. XML 네임스페이스 접두사가 표시되면 x:Reference는 XAML 2009 사양의 일부이지만 Binding은 Xamin.Forms의 일부입니다.As the XML namespace prefixes indicate, x:Reference is part of the XAML 2009 specification, while Binding is part of Xamarin.Forms. 따옴표는 중괄호 안에 표시되지 않습니다.Notice that no quotation marks appear within the curly braces.

BindingContext를 설정할 때 x:Reference 태그 확장을 잊어버리기 쉽습니다.It's easy to forget the x:Reference markup extension when setting the BindingContext. 다음과 같이 실수로 속성을 바인딩 원본 이름으로 직접 설정하는 것이 일반적입니다.It's common to mistakenly set the property directly to the name of the binding source like this:

BindingContext="slider"

하지만 이는 올바르지 않습니다.But that's not right. 해당 태그는 BindingContext 속성을 "slider" 문자로 철자되는 string 개체로 설정합니다!That markup sets the BindingContext property to a string object whose characters spell "slider"!

원본 속성은 Binding 클래스의 Path 속성에 해당하는 BindingExtensionPath 속성으로 지정됩니다.Notice that the source property is specified with the Path property of BindingExtension, which corresponds with the Path property of the Binding class.

기본 XAML 바인딩 페이지에 표시된 태그는 간소화할 수 있습니다. 즉, x:ReferenceBinding과 같은 XAML 태그 확장에는 ‘콘텐츠 속성’ 특성이 정의될 수 있으며, 이는 XAML 태그 확장의 경우 속성 이름을 표시할 필요가 없음을 의미합니다. The markup shown on the Basic XAML Binding page can be simplified: XAML markup extensions such as x:Reference and Binding can have content property attributes defined, which for XAML markup extensions means that the property name doesn't need to appear. Name 속성은 x:Reference의 콘텐츠 속성이고, Path 속성은 Binding의 콘텐츠 속성입니다. 즉 다음 식에서 해당 속성을 제외할 수 있습니다.The Name property is the content property of x:Reference, and the Path property is the content property of Binding, which means that they can be eliminated from the expressions:

<Label Text="TEXT"
       FontSize="80"
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand"
       BindingContext="{x:Reference slider}"
       Rotation="{Binding Value}" />

바인딩 컨텍스트가 없는 바인딩Bindings without a Binding Context

BindingContext 속성은 데이터 바인딩의 중요한 구성 요소이지만 항상 필요한 것은 아닙니다.The BindingContext property is an important component of data bindings, but it is not always necessary. 대신 원본 개체를 SetBinding 호출 또는 Binding 태그 확장에 지정할 수 있습니다.The source object can instead be specified in the SetBinding call or the Binding markup extension.

이는 대체 코드 바인딩 샘플에 나와 있습니다.This is demonstrated in the Alternative Code Binding sample. XAML 파일은 SliderLabelScale 속성을 제어하도록 정의된다는 점을 제외하고는 기본 코드 바인딩 샘플과 비슷합니다.The XAML file is similar to the Basic Code Binding sample except that the Slider is defined to control the Scale property of the Label. 이러한 이유로 Slider는 –2 - 2의 범위로 설정됩니다.For that reason, the Slider is set for a range of –2 to 2:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DataBindingDemos.AlternativeCodeBindingPage"
             Title="Alternative Code Binding">
    <StackLayout Padding="10, 0">
        <Label x:Name="label"
               Text="TEXT"
               FontSize="40"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <Slider x:Name="slider"
                Minimum="-2"
                Maximum="2"
                VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

코드 숨김 파일은 BindableObject에서 정의된 SetBinding 메서드를 사용하여 바인딩을 설정합니다.The code-behind file sets the binding with the SetBinding method defined by BindableObject. 인수는 Binding 클래스에 대한 생성자입니다.The argument is a constructor for the Binding class:

public partial class AlternativeCodeBindingPage : ContentPage
{
    public AlternativeCodeBindingPage()
    {
        InitializeComponent();

        label.SetBinding(Label.ScaleProperty, new Binding("Value", source: slider));
    }
}

Binding 생성자에는 6개의 매개 변수가 있으므로 source 매개 변수는 명명된 인수로 지정됩니다.The Binding constructor has 6 parameters, so the source parameter is specified with a named argument. 인수는 slider 개체입니다.The argument is the slider object.

이 프로그램을 실행하면 약간 놀랄 수도 있습니다.Running this program might be a little surprising:

대체 코드 바인딩Alternative Code Binding

왼쪽의 iOS 화면에서는 페이지가 처음 나타날 때 화면이 표시되는 모양을 보여 줍니다.The iOS screen on the left shows how the screen looks when the page first appears. Label은 어디에 있을까요?Where is the Label?

문제는 Slider의 초기 값이 0이라는 것입니다.The problem is that the Slider has an initial value of 0. 이로 인해 LabelScale 속성도 0으로 설정되어 기본값인 1을 재정의합니다.This causes the Scale property of the Label to be also set to 0, overriding its default value of 1. 따라서 초기에는 Label이 표시되지 않습니다.This results in the Label being initially invisible. Android 및 UWP(유니버설 Windows 플랫폼) 스크린샷에서 보여 주듯이 Slider를 조작하여 Label이 다시 나타나도록 할 수 있지만 초기에 표시되지 않으면 당혹스럽게 만듭니다.As the Android and Universal Windows Platform (UWP) screenshots demonstrate, you can manipulate the Slider to make the Label appear again, but its initial disappearance is disconcerting.

다음 문서에서 Scale 속성의 기본값에서 Slider를 초기화하여 이 문제를 방지하는 방법을 알아봅니다.You'll discover in the next article how to avoid this problem by initializing the Slider from the default value of the Scale property.

참고

또한 VisualElement 클래스는 VisualElement의 크기를 가로 및 세로 방향으로 다르게 확장할 수 있는 ScaleXScaleY 속성을 정의합니다.The VisualElement class also defines ScaleX and ScaleY properties, which can scale the VisualElement differently in the horizontal and vertical directions.

대체 XAML 바인딩 페이지에는 XAML에서 완전히 동일한 바인딩이 표시됩니다.The Alternative XAML Binding page shows the equivalent binding entirely in XAML:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DataBindingDemos.AlternativeXamlBindingPage"
             Title="Alternative XAML Binding">
    <StackLayout Padding="10, 0">
        <Label Text="TEXT"
               FontSize="40"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               Scale="{Binding Source={x:Reference slider},
                               Path=Value}" />

        <Slider x:Name="slider"
                Minimum="-2"
                Maximum="2"
                VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

이제 Binding 태그 확장에는 쉼표로 구분된 두 개의 속성 세트인 SourcePath가 있습니다.Now the Binding markup extension has two properties set, Source and Path, separated by a comma. 원하는 경우 동일한 줄에 나타날 수 있습니다.They can appear on the same line if you prefer:

Scale="{Binding Source={x:Reference slider}, Path=Value}" />

Source 속성은 포함된 x:Reference 태그 확장으로 설정되며, 그렇지 않으면 BindingContext를 설정하는 것과 동일한 구문이 포함됩니다.The Source property is set to an embedded x:Reference markup extension that otherwise has the same syntax as setting the BindingContext. 중괄호 안에 따옴표가 표시되지 않으며, 두 속성은 쉼표로 구분해야 합니다.Notice that no quotation marks appear within the curly braces, and that the two properties must be separated by a comma.

Binding 태그 확장의 콘텐츠 속성은 Path이지만, 태그 확장의 Path= 부분은 식의 첫 번째 속성인 경우에만 제거할 수 있습니다.The content property of the Binding markup extension is Path, but the Path= part of the markup extension can only be eliminated if it is the first property in the expression. Path= 부분을 제거하려면 다음 두 속성을 교환해야 합니다.To eliminate the Path= part, you need to swap the two properties:

Scale="{Binding Value, Source={x:Reference slider}}" />

XAML 태그 확장은 일반적으로 중괄호로 구분되지만, 개체 요소로도 표현할 수 있습니다.Although XAML markup extensions are usually delimited by curly braces, they can also be expressed as object elements:

<Label Text="TEXT"
       FontSize="40"
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand">
    <Label.Scale>
        <Binding Source="{x:Reference slider}"
                 Path="Value" />
    </Label.Scale>
</Label>

이제 SourcePath 속성은 일반 XAML 특성입니다. 값이 따옴표 안에 표시되고, 특성은 쉼표로 구분되지 않습니다.Now the Source and Path properties are regular XAML attributes: The values appear within quotation marks and the attributes are not separated by a comma. 또한 x:Reference 태그 확장은 개체 요소가 될 수 있습니다.The x:Reference markup extension can also become an object element:

<Label Text="TEXT"
       FontSize="40"
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand">
    <Label.Scale>
        <Binding Path="Value">
            <Binding.Source>
                <x:Reference Name="slider" />
            </Binding.Source>
        </Binding>
    </Label.Scale>
</Label>

이 구문은 일반적이지 않지만, 때때로 복잡한 개체가 관련되는 경우에는 필요합니다.This syntax isn't common, but sometimes it's necessary when complex objects are involved.

지금까지 표시된 예제에서는 BindingContext 속성과 BindingSource 속성을 x:Reference 태그 확장으로 설정하여 페이지의 다른 보기를 참조했습니다.The examples shown so far set the BindingContext property and the Source property of Binding to an x:Reference markup extension to reference another view on the page. 이 두 속성은 Object 형식이며, 바인딩 원본에 적합한 속성이 포함된 개체로 설정할 수 있습니다.These two properties are of type Object, and they can be set to any object that includes properties that are suitable for binding sources.

앞서의 문서에서 BindingContext 또는 Source 속성은 정적 속성 또는 필드의 값을 참조하는 x:Static 태그 확장, 리소스 사전에 저장된 개체를 참조하는 StaticResource 태그 확장으로 설정하거나, 일반적으로(항상은 아님) ViewModel의 인스턴스인 개체로 직접 설정할 수 있음을 알 수 있습니다.In the articles ahead, you'll discover that you can set the BindingContext or Source property to an x:Static markup extension to reference the value of a static property or field, or a StaticResource markup extension to reference an object stored in a resource dictionary, or directly to an object, which is generally (but not always) an instance of a ViewModel.

또한 BindingContext 속성을 Binding 개체로 설정하여 BindingSourcePath 속성에서 바인딩 컨텍스트를 정의할 수도 있습니다.The BindingContext property can also be set to a Binding object so that the Source and Path properties of Binding define the binding context.

바인딩 컨텍스트 상속Binding Context Inheritance

이 문서에서는 BindingContext 속성 또는 Binding 개체의 Source 속성을 사용하여 원본 개체를 지정할 수 있음을 살펴보았습니다.In this article, you've seen that you can specify the source object using the BindingContext property or the Source property of the Binding object. 둘 다 설정되는 경우 BindingSource 속성이 BindingContext보다 우선합니다.If both are set, the Source property of the Binding takes precedence over the BindingContext.

BindingContext 속성에는 다음과 같은 매우 중요한 특징이 있습니다.The BindingContext property has an extremely important characteristic:

BindingContext 속성의 설정은 시각적 트리를 통해 상속됩니다.The setting of the BindingContext property is inherited through the visual tree.

보다시피, 이 방법은 바인딩 식을 간소화하는 데 매우 유용할 수 있으며, 경우에 따라, 특히 MVVM(Model-View-ViewModel) 시나리오에서는 필수적입니다.As you'll see, this can be very handy for simplifying binding expressions, and in some cases — particularly in Model-View-ViewModel (MVVM) scenarios — it is essential.

바인딩 컨텍스트 상속 샘플은 바인딩 컨텍스트의 상속에 대한 간단한 데모입니다.The Binding Context Inheritance sample is a simple demonstration of the inheritance of the binding context:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DataBindingDemos.BindingContextInheritancePage"
             Title="BindingContext Inheritance">
    <StackLayout Padding="10">

        <StackLayout VerticalOptions="FillAndExpand"
                     BindingContext="{x:Reference slider}">

            <Label Text="TEXT"
                   FontSize="80"
                   HorizontalOptions="Center"
                   VerticalOptions="EndAndExpand"
                   Rotation="{Binding Value}" />

            <BoxView Color="#800000FF"
                     WidthRequest="180"
                     HeightRequest="40"
                     HorizontalOptions="Center"
                     VerticalOptions="StartAndExpand"
                     Rotation="{Binding Value}" />
        </StackLayout>

        <Slider x:Name="slider"
                Maximum="360" />

    </StackLayout>
</ContentPage>

StackLayoutBindingContext 속성은 slider 개체로 설정됩니다.The BindingContext property of the StackLayout is set to the slider object. 이 바인딩 컨텍스트는 LabelBoxView 모두에서 상속되며, 둘 모두의 Rotation 속성이 SliderValue 속성으로 설정됩니다.This binding context is inherited by both the Label and the BoxView, both of which have their Rotation properties set to the Value property of the Slider:

바인딩 컨텍스트 상속Binding Context Inheritance

다음 문서에서는 바인딩 모드에서 대상 개체와 원본 개체 간의 데이터 흐름을 변경하는 방법을 보여 줍니다.In the next article, you'll see how the binding mode can change the flow of data between target and source objects.

Channel 9YouTube에서 더 많은 Xamarin 비디오를 찾습니다.Find more Xamarin videos on Channel 9 and YouTube.