从 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. 例如,可以使用模板绑定将 Label.Text 属性绑定到定义要显示的文本的可绑定属性,而不是定义通过 ControlTemplate 中的 Label 实例显示的文字。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.

TemplateBinding 类似于现有的 Binding,区别在于 TemplateBinding 的源始终自动设置为拥有控件模板的目标视图的父级 。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 之外使用 TemplateBindingHowever, note that using a TemplateBinding outside of a ControlTemplate is not supported.

在 XAML 中创建 TemplateBindingCreating 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>

属性可以使用模板绑定来绑定到拥有 ControlTemplate 的目标视图的父级上的可绑定属性,而不是将 Label.Text 属性设置为静态文本 。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. 但请注意,模板绑定绑定到 Parent.HeaderTextParent.FooterText,而不是 HeaderTextFooterTextHowever, 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 属性返回 ContentView 实例的父元素,即 ContentPage 实例。The template binding uses the Parent property to return the parent element of the ContentView instance, which is the ContentPage instance. 因此,使用 ControlTemplate 中的 TemplateBinding 绑定到 Parent.HeaderTextParent.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&#35 中创建模板绑定;Creating a TemplateBinding in C#

在 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"));
    ...
  }
}

属性可以使用模板绑定来绑定到拥有 ControlTemplate 的目标视图的父级上的可绑定属性,而不是将 Label.Text 属性设置为静态文本 。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.

将 BindableProperty 绑定到 ViewModel 属性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. 反之,这些可绑定属性可绑定到 Viewmodel 中的属性。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>

由于将 BindingContext 设置为 HomePageViewModel 类的实例,因此可将HeaderTextFooterText 可绑定属性绑定到 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. 总体而言,这使得 ControlTemplate 中的控件属性绑定到 ContentPage 上的 BindableProperty 实例,而这些实例又绑定到 ViewModel 属性。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 来为 ContentPage 上的 HeaderTextFooterText 声明 BindableProperty。例如 PropertyName :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>

有关将数据绑定到 Viewmodel 的详细信息,请参阅从数据绑定到 MVVMFor 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.