{x:Bind} 标记扩展

注意 有关在应用中对 {x:Bind} 使用数据绑定的常规信息(有关 {x:Bind}{Binding} 之间的全面比较),请参阅 数据绑定深入

{x:Bind} 标记扩展(Windows 10 的新增功能)是 {Binding} 的替代方法。 {x:Bind} 在比 {Binding} 更少的时间和内存中运行,并支持更好的调试。

在 XAML 编译时, {x:Bind} 将转换为从数据源的属性获取值的代码,并在标记中指定的属性上设置该值。 绑定对象可以选择性地配置为观察数据源属性值的变化,并根据这些更改刷新自身。Mode="OneWay" 还可以选择将其配置为将自己的值中的更改推送回源属性(Mode="TwoWay")。

由 {x:Bind}{Binding} 创建的绑定对象基本上是等效的。 但 {x:Bind} 执行在编译时生成的特殊用途代码, {Binding} 使用常规用途运行时对象检查。 因此,{x:Bind}绑定(通常称为编译绑定)具有优异的性能,能够提供绑定表达式的编译时验证,并支持调试,您可以在生成的作为页面部分类的代码文件中设置断点。 可以在文件夹中obj找到这些文件,其名称类似于(对于 C#)。 <view name>.g.cs

小窍门

{x:Bind} 具有 OneTime 的默认模式,与 {Binding} 不同,它具有 OneWay 的默认模式。 这是出于性能原因选择的,因为使用 OneWay 会导致生成更多代码来挂钩和处理更改检测。 可以显式指定使用 OneWay 或 TwoWay 绑定的模式。 还可以使用 x:DefaultBindMode 为标记树的特定段更改 {x:Bind} 的默认模式。 指定的模式适用于该元素及其子元素上的任何 {x:Bind} 表达式,这些表达式未显式指定模式作为绑定的一部分。

XAML 属性用法

<object property="{x:Bind}" .../>
-or-
<object property="{x:Bind propertyPath}" .../>
-or-
<object property="{x:Bind bindingProperties}" .../>
-or-
<object property="{x:Bind propertyPath, bindingProperties}" .../>
-or-
<object property="{x:Bind pathToFunction.functionName(functionParameter1, functionParameter2, ...), bindingProperties}" .../>
术语 Description
propertyPath 一个字符串,指定绑定的属性路径。 有关详细信息,请参阅下面的 “属性路径 ”部分。
bindingProperties
propName=value[, propName=value]* 使用名称/值对语法指定的一个或多个绑定属性。
propName 要对绑定对象设置的属性的字符串名称。 例如,“Converter”。
value 要设置属性的值。 参数的语法取决于所设置的属性。 下面是 propName=用法的示例,其中该值本身是标记扩展: Converter={StaticResource myConverterClass} 有关详细信息,请参阅下面 可以使用 {x:Bind} 部分设置的属性

例子

<Page x:Class="QuizGame.View.HostView" ... >
    <Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Page>

此示例 XAML 将 {x:Bind}ListView.ItemTemplate 属性配合使用。 请注意 x:DataType 值的声明。

  <DataTemplate x:Key="SimpleItemTemplate" x:DataType="data:SampleDataGroup">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{x:Bind Title}"/>
      <TextBlock Text="{x:Bind Description}"/>
    </StackPanel>
  </DataTemplate>

属性路径

PropertyPath 设置 {x:Bind} 表达式的路径路径 是一个属性路径,用于指定要绑定到的属性、子属性、字段或方法的值(源)。 可以显式提及 Path 属性的名称: {x:Bind Path=...}。 或者可以省略它: {x:Bind ...}

属性路径解析

{x:Bind} 不使用 DataContext 作为默认源,而是使用页面或用户控件本身。 因此,它将在页面代码文件或用户控件的隐藏代码中查找属性、字段和方法。 若要向 {x:Bind} 公开视图模型,通常需要在页面或用户控件的后台代码中添加新的字段或属性。 属性路径中的步骤由点(.)分隔,可以包含多个分隔符来遍历连续子属性。 无论用于实现绑定到的对象的编程语言如何,都使用点分隔符。

例如:在页面中,Text=“{x:Bind Employee.FirstName}”将在页面上查找 Employee 成员,然后在 Employee 返回的对象上查找 FirstName 成员。 如果要将项控件绑定到包含员工依赖项的属性,则属性路径可能是“Employee.Dependents”,而项目控件的项模板将负责在“依赖项”中显示项。

对于 C++/CX, {x:Bind} 无法绑定到页面或数据模型中的专用字段和属性 - 需要具有可绑定的公共属性。 绑定接口的表面需要作为 CX 类/接口暴露,以便我们可以获取相关的元数据。 不需要 [Bindable] 属性。

使用 x:Bind 时,无需将 ElementName=xxx 用作绑定表达式的一部分。 相反,可以使用元素的名称作为绑定路径的第一部分,因为命名元素将成为表示根绑定源的页面或用户控件中的字段。

Collections

如果数据源是集合,则属性路径可以通过集合中的位置或索引指定项。 例如,“Teams[0].Players”,这其中的“[]”把表示请求零索引集合中第一项的“0”括起来。

若要使用索引器,模型需要在要编制索引的属性的类型上实现 IList<T>IVector<T> 。 (注意 IReadOnlyList<T> 和 IVectorView<T> 不支持索引器语法。如果索引属性的类型支持 INotifyCollectionChangedIObservableVector ,并且绑定为 OneWay 或 TwoWay,则它将在这些接口上注册和侦听更改通知。 更改检测逻辑将基于所有集合更改进行更新,即使这不会影响特定的索引值。 这是因为侦听逻辑在集合的所有实例中很常见。

如果数据源是字典或映射,则属性路径可以通过其字符串名称指定集合中的项。 例如<,TextBlock Text=“{x:Bind Players['John Smith']}”/> 将在名为“John Smith”的字典中查找一个项目。 名称需要括在引号中,可以使用单引号或双引号。 Hat (^) 可用于转义字符串中的引号。 通常最简单的方法是使用与 XAML 属性中所用引号不同的替代引号。 (注意 IReadOnlyDictionary<T> 和 IMapView<T> 不支持索引器语法。

若要使用字符串索引器,模型需要对要编制索引的属性的类型实现 IDictionary<字符串, T>IMap<字符串, T>。 如果索引属性的类型支持 IObservableMap ,并且绑定为 OneWay 或 TwoWay,则它将在这些接口上注册和侦听更改通知。 更改检测逻辑将基于所有集合更改进行更新,即使这不会影响特定的索引值。 这是因为侦听逻辑在集合的所有实例中很常见。

附加属性

若要绑定到 附加属性,需要在点后面将类和属性名称放入括号中。 例如 Text=“{x:Bind Button22.(Grid.Row)}”。 如果未在 Xaml 命名空间中声明该属性,则需要使用 xml 命名空间作为前缀,该命名空间应映射到文档头的代码命名空间。

铸造

已编译的绑定是强类型绑定,将解析路径中每个步骤的类型。 如果返回的类型没有成员,则它在编译时会失败。 您可以指定类型转换以告知绑定过程中对象的实际类型。

在下列情况下,obj 是一个类型对象的属性,但包含一个文本框,因此可以使用 Text=“{x:Bind(TextBox)obj”。Text}“Text=”{x:Bind obj.(TextBox.Text)}”。

groups3 字段在 Text="{x:Bind ((data:SampleDataGroup)groups3[0]).Title}" 中是一个对象的字典,因此必须将它强制转换为 data:SampleDataGroup。 请注意 xml 数据的用法: 命名空间前缀,用于将对象类型映射到不属于默认 XAML 命名空间的代码命名空间。

注意:C# 样式的类型转换语法比附加属性语法更灵活,是今后推荐使用的语法。

无路径转换

本地绑定解析器没有提供关键字来将 this 作为函数参数,但它支持无路径转换(例如,{x:Bind (x:String)}),可以用作函数参数。 因此, {x:Bind MethodName((namespace:TypeOfThis))} 是执行概念上等效 {x:Bind MethodName(this)}内容的有效方法。

示例:

Text="{x:Bind local:MainPage.GenerateSongTitle((local:SongItem))}"

<Page
    x:Class="AppSample.MainPage"
    ...
    xmlns:local="using:AppSample">

    <Grid>
        <ListView ItemsSource="{x:Bind Songs}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:SongItem">
                    <TextBlock
                        Margin="12"
                        FontSize="40"
                        Text="{x:Bind local:MainPage.GenerateSongTitle((local:SongItem))}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>
namespace AppSample
{
    public class SongItem
    {
        public string TrackName { get; private set; }
        public string ArtistName { get; private set; }

        public SongItem(string trackName, string artistName)
        {
            ArtistName = artistName;
            TrackName = trackName;
        }
    }

    public sealed partial class MainPage : Page
    {
        public List<SongItem> Songs { get; }
        public MainPage()
        {
            Songs = new List<SongItem>()
            {
                new SongItem("Track 1", "Artist 1"),
                new SongItem("Track 2", "Artist 2"),
                new SongItem("Track 3", "Artist 3")
            };

            this.InitializeComponent();
        }

        public static string GenerateSongTitle(SongItem song)
        {
            return $"{song.TrackName} - {song.ArtistName}";
        }
    }
}

绑定路径中的函数

从 Windows 10 版本 1607 开始,{x:Bind} 支持使用函数作为绑定路径的叶节点。 这是一项功能强大的数据绑定功能,可用于在标记中实现多个方案。 请查看函数绑定详情。

事件绑定

事件绑定是编译绑定中的一个独特功能。 它使你能够使用绑定为事件指定处理程序,而不必将其设为后台代码中的方法。 例如:Click="{x:Bind rootFrame.GoForward}"

对于事件,目标方法不得重载,并且还必须:

  • 匹配事件的签名。
  • 或者没有参数。
  • 或者具有与事件参数类型可分配类型相同数量的参数。

在生成的代码隐藏中,已编译的绑定处理事件并将其路由到模型上的方法,并在事件发生时评估绑定表达式的路径。 这意味着,与属性绑定不同,它不会跟踪模型的更改。

有关属性路径的字符串语法的详细信息,请参阅 Property-path 语法,请记住 {x:Bind}此处所述的差异。

使用 {x:Bind} 可设置的属性

{x:Bind} 通过 bindingProperties 占位符语法进行说明,因为标记扩展中可以设置多个读/写属性。 可以使用逗号分隔 的 propName= 对按任意顺序设置属性。 请注意,不能在绑定表达式中包含换行符。 某些属性需要的类型没有可用的类型转换器,因此这些属性需要在{x:Bind}中嵌套其自己的标记扩展。

这些属性的工作方式与 Binding 类的属性大致相同。

资产 Description
路径 请参阅上面的 “属性路径 ”部分。
转换器 指定绑定引擎调用的转换器对象。 转换器可以在 XAML 中设置,但前提是引用在对资源字典中该对象的 {StaticResource} 标记扩展 引用中分配的对象实例。
ConverterLanguage 指定要由转换器使用的区域性。 (如果要设置 ConverterLanguage ,则还应设置 Converter。)文化信息设置为基于标准的标识符。 有关详细信息,请参阅 ConverterLanguage
ConverterParameter 指定可在转换器逻辑中使用的转换器参数。 (如果要设置 ConverterParameter ,还应设置 Converter。)大多数转换器使用简单的逻辑从传递的值获取所需的全部信息来转换,并且不需要 ConverterParameter 值。 ConverterParameter 参数适用于中等高级转换器实现,这些实现具有多个逻辑,这些逻辑用于关闭 ConverterParameter 中传递的内容。 可以编写使用字符串以外的值的转换器,但这种情况并不常见,有关详细信息,请参阅 ConverterParameter 中的备注。
FallbackValue 指定要在无法解析源或路径时显示的值。
模式 将绑定模式指定为以下字符串之一:“OneTime”、“OneWay”或“TwoWay”。 默认值为“OneTime”。 请注意,这不同于 {Binding} 的默认值,在大多数情况下为“OneWay”。
TargetNullValue 指定在源值解析但显式 为 null 时要显示的值。
BindBack 指定要用于双向绑定的反向方向的函数。
UpdateSourceTrigger 指定何时将更改从控件推送回 TwoWay 绑定中的模型。 除 TextBox.Text 以外的所有属性的默认值为 PropertyChanged,而 TextBox.Text 的默认值为 LostFocus。

注释

如果要将标记从 {Binding} 转换为 {x:Bind},请注意 Mode 属性的默认值之间的差异。 x:DefaultBindMode 可用于更改标记树特定段的 x:Bind 的默认模式。 所选模式将在该元素及其子元素上应用任何 x:Bind 表达式,这些表达式不会显式指定模式作为绑定的一部分。 OneTime 比 OneWay 的性能更高,因为使用 OneWay 将导致生成更多代码来挂钩并处理更改检测。

注解

由于 {x:Bind} 使用生成的代码来实现其优势,因此在编译时需要类型信息。 这意味着不能绑定到事先不知道类型的属性。 因此,不能将 {x:Bind}DataContext 属性一起使用,该属性的类型为 Object,在运行时也会更改。

对数据模板使用 {x:Bind} 时,必须通过设置 x:DataType 值来指示要绑定到的类型,如 “示例 ”部分所示。 还可以将类型设置为接口或基类类型,然后在必要时使用类型转换来构建完整表达式。

编译的绑定取决于代码生成。 因此,如果在资源字典中使用 {x:Bind} ,则资源字典需要具有代码隐藏类。 有关代码示例,请参阅 带 {x:Bind} 的资源字典

包含已编译绑定的页面和用户控件将在生成的代码中具有“Bindings”属性。 这包括以下方法:

  • Update() - 这将更新所有已编译绑定的值。 任何单向/双向绑定都将连接侦听器以检测更改。
  • Initialize() - 如果绑定尚未初始化,则将调用 Update() 初始化绑定
  • StopTracking() - 这将取消为单向绑定和双向绑定创建的所有侦听器。 可以使用 Update() 方法重新初始化它们。

注释

从 Windows 10 版本 1607 开始,XAML 框架提供内置布尔值到 Visibility 转换器。 转换器将 true 映射到 Visible 枚举值, 将 false 映射到 Collapsed ,以便无需创建转换器即可将 Visibility 属性绑定到布尔值。 请注意,这不是函数绑定的功能,而是属性绑定的特性。 若要使用内置转换器,应用的最低目标 SDK 版本必须为 14393 或更高版本。 当应用面向早期版本的 Windows 10 时,不能使用它。 有关目标版本的详细信息,请参阅 版本自适应代码

小窍门

如果需要为值指定单个大括号(如 PathConverterParameter 中),请在其前面加上反斜杠: \{ 或者,将包含需要转义的大括号的整个字符串括在辅助引号集中,例如 ConverterParameter='{Mix}'

转换器ConverterLanguageConverterLanguage 都与将值或类型从绑定源转换为与绑定目标属性兼容的类型或值的方案相关。 有关详细信息和示例,请参阅 数据绑定的“数据转换”部分。

{x:Bind} 只是标记扩展,无法以编程方式创建或作此类绑定。 有关标记扩展的详细信息,请参阅 XAML 概述