Xamarin.Forms ControlTemplate에서 바인딩Binding from a Xamarin.Forms ControlTemplate

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

템플릿 바인딩을 사용하면 컨트롤 템플릿의 컨트롤을 공용 속성에 데이터 바인딩할 수 있기 때문에 컨트롤 템플릿의 컨트롤에 대한 속성 값을 쉽게 변경할 수 있습니다. 이 문서에서는 템플릿 바인딩을 사용하여 컨트롤 템플릿에서 데이터 바인딩을 수행하는 방법을 보여줍니다.Template bindings allow controls in a control template to data bind to public properties, enabling property values on controls in the control template to be easily changed. This article demonstrates using template bindings to perform data binding from a control template.

TemplateBinding은 컨트롤 템플릿을 소유한 대상 뷰의 부모의 바인딩 가능한 속성에 컨트롤 템플릿의 컨트롤 속성을 바인딩하는 데 사용됩니다.A TemplateBinding is used to bind a control's property in a control template to a bindable property on the parent of the target view that owns the control template. 예를 들어 ControlTemplate 내부의 Label 인스턴스에 따라 표시된 텍스트를 정의하는 대신 템플릿 바인딩을 사용하여 Label.Text 속성을 표시될 텍스트를 정의하는 바인딩 가능한 속성에 바인딩할 수 있습니다.For example, rather than defining the text displayed by Label instances inside the ControlTemplate, you could use a template binding to bind the Label.Text property to bindable properties that define the text to be displayed.

TemplateBindingTemplateBinding원본이 항상 컨트롤 템플릿을 소유하는 대상 뷰의 부모로 자동 설정되는 것을 제외하고는 기존 Binding과 비슷합니다.A TemplateBinding is similar to an existing Binding, except that the source of a TemplateBinding is always automatically set to the parent of the target view that owns the control template. 그러나 ControlTemplate 외부의 TemplateBinding을 사용하는 것은 지원되지 않습니다.However, note that using a TemplateBinding outside of a ControlTemplate is not supported.

XAML에서 TemplateBinding 만들기Creating a TemplateBinding in XAML

다음 코드 예제에 설명된 대로 XAML에서 TemplateBinding 태그 확장을 사용하여 TemplateBinding을 만듭니다.In XAML, a TemplateBinding is created using the TemplateBinding markup extension, as demonstrated in the following code example:

<ControlTemplate x:Key="TealTemplate">
  <Grid>
    ...
    <Label Text="{TemplateBinding Parent.HeaderText}" ... />
    ...
    <Label Text="{TemplateBinding Parent.FooterText}" ... />
  </Grid>
</ControlTemplate>

Label.Text 속성을 정적 텍스트로 설정하기보다 해당 속성은 템플릿 바인딩을 사용하여 ControlTemplate을 소유하는 대상 뷰의 부모의 바인딩 가능한 속성에 바인딩할 수 있습니다.Rather than set the Label.Text properties to static text, the properties can use template bindings to bind to bindable properties on the parent of the target view that owns the ControlTemplate. 그러나 템플릿 바인딩은 HeaderTextFooterText보다는 Parent.HeaderTextParent.FooterText에 바인딩됩니다.However, note that the template bindings bind to Parent.HeaderText and Parent.FooterText, rather than HeaderText and FooterText. 다음 코드 예제에 설명된 것처럼 이 예제에서는 바인딩 가능한 속성을 부모보다는 대상 뷰의 상위 부모에서 정의하기 때문입니다.This is because in this example, the bindable properties are defined on the grandparent of the target view, rather than the parent, as demonstrated in the following code example:

<ContentPage ...>
    <ContentView ... ControlTemplate="{StaticResource TealTemplate}">
          ...
    </ContentView>
</ContentPage>

템플릿 바인딩의 원본은 항상 컨트롤 템플릿을 소유하는 대상 뷰의 부모로 자동 설정되며 여기서는 ContentView 인스턴스입니다.The source of the template binding is always automatically set to the parent of the target view that owns the control template, which here is the ContentView instance. 템플릿 바인딩은 Parent 속성을 사용하여 ContentPage 인스턴스인 ContentView 인스턴스의 부모 요소를 반환합니다.The template binding uses the Parent property to return the parent element of the ContentView instance, which is the ContentPage instance. 따라서 ControlTemplateTemplateBinding을 사용하여 Parent.HeaderText에 바인딩하고 Parent.FooterText는 다음 코드 예제에 표시된 것처럼 ContentPage에서 정의된 바인딩 가능한 속성을 찾습니다.Therefore, using a TemplateBinding in the ControlTemplate to bind to Parent.HeaderText and Parent.FooterText locates the bindable properties that are defined on the ContentPage, as demonstrated in the following code example:

public static readonly BindableProperty HeaderTextProperty =
  BindableProperty.Create ("HeaderText", typeof(string), typeof(HomePage), "Control Template Demo App");
public static readonly BindableProperty FooterTextProperty =
  BindableProperty.Create ("FooterText", typeof(string), typeof(HomePage), "(c) Xamarin 2016");

public string HeaderText {
  get { return (string)GetValue (HeaderTextProperty); }
}

public string FooterText {
  get { return (string)GetValue (FooterTextProperty); }
}

이로 인해 결국 다음 스크린샷에 표시된 모양이 됩니다.This results in the appearance shown in the following screenshots:

C#에서 TemplateBinding 만들기Creating a TemplateBinding in C#

다음 코드 예제에 표시된 것처럼 TemplateBinding 생성자를 사용하여 TemplateBinding을 만듭니다.In C#, a TemplateBinding is created by using the TemplateBinding constructor, as demonstrated in the following code example:

class TealTemplate : Grid
{
  public TealTemplate ()
  {
    ...
    var topLabel = new Label { TextColor = Color.White, VerticalOptions = LayoutOptions.Center };
    topLabel.SetBinding (Label.TextProperty, new TemplateBinding ("Parent.HeaderText"));
    ...
    var bottomLabel = new Label { TextColor = Color.White, VerticalOptions = LayoutOptions.Center };
    bottomLabel.SetBinding (Label.TextProperty, new TemplateBinding ("Parent.FooterText"));
    ...
  }
}

Label.Text 속성을 정적 텍스트로 설정하기보다 해당 속성은 템플릿 바인딩을 사용하여 ControlTemplate을 소유하는 대상 뷰의 부모의 바인딩 가능한 속성에 바인딩할 수 있습니다.Rather than set the Label.Text properties to static text, the properties can use template bindings to bind to bindable properties on the parent of the target view that owns the ControlTemplate. SetBinding 메서드를 두 번째 매개 변수로 TemplateBinding 인스턴스를 지정하여 템플릿 바인딩을 만듭니다.The template binding is created by using the SetBinding method, specifying a TemplateBinding instance as the second parameter. 다음 코드 예제에 설명된 것처럼 바인딩 가능한 속성은 부모보다는 대상 뷰의 상위 부모에서 정의되므로 템플릿 바인딩은 Parent.HeaderTextParent.FooterText에 바인딩됩니다.Note that the template bindings bind to Parent.HeaderText and Parent.FooterText, because the bindable properties are defined on the grandparent of the target view, rather than the parent, as demonstrated in the following code example:

public class HomePageCS : ContentPage
{
  ...
  public HomePageCS ()
  {
    Content = new ContentView {
      ControlTemplate = tealTemplate,
      Content = new StackLayout {
        ...
      },
      ...
    };
    ...
  }
}

바인딩 가능한 속성은 앞에서 설명한 대로 ContentPage에서 정의됩니다.The bindable properties are defined on the ContentPage, as outlined earlier.

ViewModel 속성에 BindableProperty 바인딩Binding a BindableProperty to a ViewModel Property

앞서 설명한 대로 TemplateBinding은 컨트롤 템플릿을 소유한 대상 뷰의 부모의 바인딩 가능한 속성에 컨트롤 템플릿의 컨트롤 속성을 바인딩하는 데 사용됩니다.As previously stated, a TemplateBinding binds a control's property in a control template to a bindable property on the parent of the target view that owns the control template. 결국 이러한 바인딩 가능한 속성은 ViewModels의 속성에 바인딩될 수 있습니다.In turn, these bindable properties can be bound to properties in ViewModels.

다음 코드 예제에서는 ViewModel에서 두 속성을 정의합니다.The following code example defines two properties on a ViewModel:

public class HomePageViewModel
{
  public string HeaderText { get { return "Control Template Demo App"; } }
  public string FooterText { get { return "(c) Xamarin 2016"; } }
}

HeaderTextFooterText ViewModel 속성은 다음 XAML 코드 예제에 표시된 대로 바인딩될 수 있습니다.The HeaderText and FooterText ViewModel properties can be bound to, as shown in the following XAML code example:

<ContentPage xmlns:local="clr-namespace:SimpleTheme;assembly=SimpleTheme"
             HeaderText="{Binding HeaderText}" FooterText="{Binding FooterText}" ...>
    <ContentPage.BindingContext>
        <local:HomePageViewModel />
    </ContentPage.BindingContext>
    <ContentView ControlTemplate="{StaticResource TealTemplate}" ...>
    ...
    </ContentView>
</ContentPage>

HeaderTextFooterText 바인딩 가능한 속성은 HomePageViewModel 클래스 인스턴스로 BindingContext를 설정했기 때문에 HomePageViewModel.HeaderTextHomePageViewModel.FooterText 속성에 바인딩됩니다.The HeaderText and FooterText bindable properties are bound to the HomePageViewModel.HeaderText and HomePageViewModel.FooterText properties, due to setting the BindingContext to an instance of the HomePageViewModel class. 전반적으로 이로 인해 결국 ViewModel 속성에 바인딩하는 ContentPageBindableProperty 인스턴스에 바인딩된 ControlTemplate의 컨트롤 속성이 됩니다.Overall, this results in control properties in the ControlTemplate being bound to BindableProperty instances on the ContentPage, which in turn bind to ViewModel properties.

동등한 C# 코드는 다음 코드 예제와 같습니다.The equivalent C# code is shown in the following code example:

public class HomePageCS : ContentPage
{
  ...
  public HomePageCS ()
  {
    BindingContext = new HomePageViewModel ();
    this.SetBinding (HeaderTextProperty, "HeaderText");
    this.SetBinding (FooterTextProperty, "FooterText");
    ...
  }
}

뷰 모델에 직접 바인딩할 수도 있으므로 Parent.BindingContext.PropertyName 등에 컨트롤 템플릿을 바인딩하여 ContentPage에서 HeaderTextFooterText에 대한 BindableProperty을 선언하지 않아도 됩니다.You can also bind to the view model properties directly, so that you don't need to declare BindablePropertys for HeaderText and FooterText on the ContentPage, by binding the control template to Parent.BindingContext.PropertyName e.g.:

<ControlTemplate x:Key="TealTemplate">
  <Grid>
    ...
    <Label Text="{TemplateBinding Parent.BindingContext.HeaderText}" ... />
    ...
    <Label Text="{TemplateBinding Parent.BindingContext.FooterText}" ... />
  </Grid>
</ControlTemplate>

ViewModels에 데이터 바인딩에 대한 자세한 내용은 데이터 바인딩에서 MVVM까지를 참조하세요.For more information about data binding to ViewModels, see From Data Bindings to MVVM.

요약Summary

이 문서에서는 템플릿 바인딩을 사용하여 컨트롤 템플릿에서 데이터 바인딩을 수행하는 방법을 보여줍니다.This article demonstrated using template bindings to perform data binding from a control template. 템플릿 바인딩을 사용하면 컨트롤 템플릿의 컨트롤을 공용 속성에 데이터 바인딩할 수 있기 때문에 컨트롤 템플릿의 컨트롤에 대한 속성 값을 쉽게 변경할 수 있습니다.Template bindings allow controls in a control template to data bind to public properties, enabling property values on controls in the control template to be easily changed.