{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} 表达式,这些表达式未显式指定模式作为绑定的一部分。
用于演示 {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}" .../>
术语 | 说明 |
---|---|
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”,并且项目控件的项目模板将负责显示“Dependents”中的项。
对于 C++/CX, {x:Bind} 无法绑定到页面或数据模型中的私有字段和属性 - 需要具有可绑定的公共属性。 绑定的外围应用需要作为 CX 类/接口公开,以便我们可以获取相关的元数据。 无需使用 Bindable 属性。
使用 x:Bind 时,无需将 ElementName=xxx 用作绑定表达式的一部分。 相反,你可以使用元素的名称作为绑定路径的第一部分,因为已命名的元素变为表示根绑定源的页面或用户控件内的字段。
集合
如果数据源是一个集合,则属性路径可以按照位置或索引来指定集合中的项目。 例如“Teams[0].Players”,其中文本“[]”中包含“0”,用以请求从零开始编制索引的集合中的第一个项目。
若要使用索引器,模型需要在要编制索引的属性的类型上实现 IList<T> 或 IVector<T>。 (注意 IReadOnlyList<T> 和 IVectorView<T> 不支持索引器语法。如果索引属性的类型支持 INotifyCollectionChanged 或 IObservableVector ,并且绑定为 OneWay 或 TwoWay,则它将在这些接口上注册和侦听更改通知。 更改检测逻辑将基于所有集合更改进行更新,即使这不会影响特定的索引值。 这是因为侦听逻辑在集合的所有实例中很常见。
如果数据源是字典或映射,则属性路径可以通过其字符串名称指定集合中的项。 例如,<TextBlock Text="{x:Bind Players['John Smith']}" /> 将在字典中查找名为“John Smith”的项。 名称需要括在引号中,可以使用单引号或双引号。 Hat (^) 可用于转义字符串中的引号。 通常最简单的做法是替换使用用于 XAML 属性的引号。 (请注意,IReadOnlyDictionary<T> 和 IMapView<T> 不支持索引器语法。)
若要使用字符串索引器,模型需要对要编制索引的属性的类型实现 IDictionary<字符串、T> 或 IMap<字符串。> 如果索引属性的类型支持 IObservableMap ,并且绑定为 OneWay 或 TwoWay,则它将在这些接口上注册和侦听更改通知。 更改检测逻辑将基于所有集合更改进行更新,即使这不会影响特定的索引值。 这是因为侦听逻辑在集合的所有实例中很常见。
附加属性
若要绑定到附加属性,需要将类和属性名称放入点号后面的括号内。 例如 Text=“{x:Bind Button22.(Grid.Row)}”。 如果未在 Xaml 命名空间中声明该属性,则需要使用 xml 命名空间作为前缀,该命名空间应映射到文档头的代码命名空间。
强制转换
已编译的绑定是强类型绑定,将解析路径中每个步骤的类型。 如果返回的类型没有成员,则它在编译时会失败。 可以指定强制转换来指示绑定对象的实际类型。
在下列情况下,obj 是一个类型对象的属性,但包含一个文本框,因此可以使用 Text=“{x:Bind(TextBox)obj”。Text}“ 或 Text=”{x:Bind obj.(TextBox.Text)}”。
Text="{x:Bind ((data:SampleDataGroup)groups3[0]).Title}" 中的 groups3 字段是一个对象字典,因此必须将其转换为 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=value 对。 请注意,不能在绑定表达式中包含换行符。 某些属性需要的类型没有类型转换,因此这些属性需要其自己的嵌套在 {x:Bind} 中的标记扩展。
这些属性的工作方式与 Binding 类的属性大致相同。
properties | 说明 |
---|---|
路径 | 请参阅上面的属性路径部分。 |
Converter | 指定绑定引擎调用的转换器对象。 转换器可以在 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 时,你无法使用它。 有关目标版本的详细信息,请参阅版本自适应代码。
提示:如果需要为值指定单个大括号(如 Path 或 ConverterParameter 中),请在其前面加上反斜杠: 。 \{
此外,将包含需要转义的括号的整个字符串放在第二组引号中,例如 ConverterParameter='{Mix}'
。
Converter、ConverterLanguage 和 ConverterLanguage 都与如下方案相关:将绑定源中的值或类型转换为与绑定目标属性兼容的类型或值。 有关详细信息和相关示例,请参阅深入了解数据绑定的“数据转换”部分。
{x:Bind} 只是标记扩展,无法以编程方式创建或操作此类绑定。 有关标记扩展的详细信息,请参阅 XAML 概述。