前言
{x:bind}是随着UWP被推出而被添加的,可以说是Win10 UWP开发专有扩展。虽然 {x:Bind} 缺少{Binding} 中的一些功能,但它运行时所花费的时间和使用的内存量均比 {Binding} 要少,且支持更好的调试。
使用Binding绑定
属性 | 说明 |
Path | 用于指定绑定的数据源的属性 例:Text="{Binding Name}" |
Mode | 绑定模式,Mode一共有三种,OneTime,OneWay,TwoWay,默认值为OneWay OneTime:只绑定一次 OneWay:单向绑定 TwoWay:双向绑定 例:Text="{Binding Name, Mode=OneTime}" |
RelativeSource | RelativeSource是一种相对关系找数据源的绑定。目前有两种:Self和TemplatedParent Self:目标元素应用作此绑定的源。当要将元素的一个属性绑定到同一元素的另一个属性时,就使用该模式 TemplatedParent:指定引用了该 ControlTemplate模板资源的控件是此绑定的源 |
ElementName | 用于绑定元素,可用于两个控件属性相互绑定,需要注意两点: 指定的ElementName必须在当前XAML名称范围里 如果绑定目标位于数据模板或控件模板中,则为模板化父级的XAML名称范围 |
Source | 用于指定绑定的对象,不设定明确的绑定source,这样Binding就去从本控件类为开始根据可视树的层次结构自下而上查找不为空的Datacontext属性的值作为数据源 Source,ElementName和RelativeSource三者是互斥的,指定多余一种的绑定方式会引发异常 |
Converter | 转换器,在对象值和我们绑定目标的类型不一致时进行转换 |
ConverterParameter | 指定可在转换器逻辑中使用的转换器参数,参数不能绑定只能指定常量值传入转换器中 |
ConverterLanguage | 指定转换器要使用的区域性,不能绑定只能指定常量值传入转换器中 |
FallbackValue | FallbackValue的用途是:当绑定对象不存在时,我们就使用FallbackValue的值 |
TargetNullValue | TargetNullValue的用途是:当绑定对象为空时,我们就使用TargetNullValue的值 |
UpdateSourceTrigger | UpdateSourceTrigger的值有三种:Default,PropertyChanged,Explicit |
Converter转换器的使用
使用转换器我们要实现IValueConverter接口:
public class BoolVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
bool? result = value as Nullable<bool>;
if(result == true)
{
return Visibility.Visible;
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
如果你的值需要转换回去,你也可以继续实现ConvertBack方法
<Page>
<Page.Resources>
<local:BoolVisibilityConverter x:Key="BoolVisibilityConverter"/>
</Page.Resources>
<Grid>
<Border Visibility="{Binding Busy, Converter={StaticResource BoolVisibilityConverter}}"/>
</Grid>
</Page>
ConverterParameter和ConverterLanguage
<Border Visibility="{Binding Busy, Converter={StaticResource BoolVisibilityConverter},
ConverterParameter=One, ConverterLanguage=en-US}"/>
使用x:Bind绑定
属性 | 说明 |
Path | 用于指定绑定的数据源的属性 例:Text="{x:Bind Name}" |
Mode | 绑定模式,Mode一共有三种,OneTime,OneWay,TwoWay,默认值为OneTime OneTime:只绑定一次 OneWay:单向绑定 TwoWay:双向绑定 例:Text="{x:Bind Name, Mode=OneWay}" |
BindBack | 支持从目标类型转换到数据源类型,类似转换器IValueConverter的ConvertBack方法功能 |
Converter | 转换器,在对象值和我们绑定目标的类型不一致时进行转换 |
ConverterParameter | 指定可在转换器逻辑中使用的转换器参数,参数不能绑定只能指定常量值传入转换器中 |
ConverterLanguage | 指定转换器要使用的区域性,不能绑定只能指定常量值传入转换器中 |
FallbackValue | FallbackValue的用途是:当绑定对象不存在时,我们就使用FallbackValue的值 |
TargetNullValue | TargetNullValue的用途是:当绑定对象为空时,我们就使用TargetNullValue的值 |
UpdateSourceTrigger | UpdateSourceTrigger的值有三种:Default,PropertyChanged,Explicit |
x:Bind 的数据源
与传统Binding绑定较大的区别,是 x:Bind 的数据源为当前 View(即页面 Page 或用户控件UserControl)自身,也就是说,它使用 Page 或 User Control 的实例为作数据源;因此如果你设置了 Path 属性, x:Bind 会到当前 Code-Bebind 类中找对应名称的成员(属性、字段、方法)
在传统Binding绑定中,Binding 的数据源可以通过四种形式指定,它们分别是 DataContext(默认)、RelativeSource、Source、ElementName。而 x:Bind 既然将当前 View 的实例作为唯一数据源,那么我们就完全不需要像传统 Binding 一样设置 DataContext;而对于后面三种设置数据源的方式, x:Bind 也仅支持以下两种情况:
ElementName
x:Bind -> {x:Bind slider1.Value}
Binding -> {Binding Value, ElementName=slider1}
RelativeSource: Self
x:Bind -> <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... />
Binding -> <Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... />
绑定模式
x:Bind 的 Binding Mode 值有以下三项:OneWay、OneTime、TwoWay;它的默认值是 OneTime,OneTime 的意思是仅在界面初始化时去初始化界面中的绑定
更具体来说,x:Bind 的绑定是在 Page 或 User Control 的 Loading 事件中初始化的;也就是说,在 Mode=OneTime(默认值)时,仅当一个属性值的设置在 View 的构造函数中时(在 Loading 事件之前)才会在 x:Bind 初始化中被更新到 UI 中;在其它位置(如 Loaded 事件或某一操作的响应事件中等等)修改此属性的值,都不会再被更新(即使调用了 INotifyPropertyChanged 中的 PropertyChanged 事件)
转换(Converting)
在数据源属性类型和绑定目标属性类型不一致时,如果我们使用传统的 Binding,可以将一个实现了 IValueConverter 的对象设置到 Binding 的 Converter 属性来实现值的转换。而使用 x:Bind,除了这种方式之外,还有更方便的——绑定属性到函数。也就是说,你可以将一个函数放到 x:Bind 中。当然,x:Bind 仍然是在当前 View 的 Code-Behind 代码中来找所指定的函数。参考如下代码:
<Border
x:Name="border"
Background="{x:Bind GetBrush(IsPass), Mode=OneWay}">
<Image Margin="20" Source="{x:Bind GetImage(IsPass), Mode=OneWay}" />
</Border>
public Brush GetBrush(bool isPass)
{
return isPass ? new SolidColorBrush(Colors.LimeGreen) : new SolidColorBrush(Colors.Crimson);
}
private ImageSource GetImage(bool isPass)
{
return isPass ? new BitmapImage(new Uri("ms-appx:///Assets/Happy.png")) : new BitmapImage(new Uri("ms-appx:///Assets/Sad.png"));
}
在上面的例子中,两处被绑定的函数均接受一个参数,事实上,这里支持多个参数。所以这一点也要比 IValueConverter 方便;此外,绑定属性到函数也支持类似于 IValueConverter 中的双向转换,除了能从数据源类型转换到目标类型,也支持从目标类型转换到数据源类型,方法是使用 BindBack 属性指定另外一个方法。
另外,还一个非常便捷的转换是 Visibility 和 bool 之间的转换:控件的 Visibility 可以直接绑定到一个布尔属性或字段;当布尔值为 true 时,Visibility 的值是 Visible,反之,是 Collapsed。参考如下代码:
<Button Content="Logout" Visibility="{x:Bind IsLogin}" />
在 DataTemplate 中使用
为列表控件(如 ListView 等)设置 ItemTemplate 属性时,要用到 DataTemplate;如果在 DataTemplate 中使用 x:Bind,要怎么做呢?
首先要为 DataTemplate 指定 x:DataType,告诉它要展示的数据 Model 类,一般情况下,这需要引入 xmlns 命令空间;然后,在 DataTemplate 内部,使用 x:Bind 直接绑定到该 Model 的相关属性。参考以下代码:
<UserControl ...
xmlns:models="using:xBindTest.Models">
<UserControl.Resources>
<DataTemplate x:Key="FriendItemTemplate" x:DataType="models:Friend">
<StackPanel Margin="0,4">
<TextBlock
FontSize="20"
FontWeight="SemiBold"
Text="{x:Bind Name}" />
<TextBlock
Margin="{StaticResource ContentMargin}"
FontSize="14"
Text="{x:Bind Email}" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ListView ItemTemplate="{StaticResource FriendItemTemplate}" ItemsSource="{x:Bind AllFriends}" />
</Grid>
</UserControl>
绑定到事件
在使用传统绑定时,对于控件操作的响应,我们一般会用到命令或行为(当控件不支持 Command 或对控件的某一特定事件进行响应时,如 ListView 控件的 SelectionChanged 事件);然而 x:Bind 可以轻松地实现同样的操作,因为它支持绑定到事件,来看代码:
<Button Click="{x:Bind ShowInfoTest1}" Content="Show Info" />
public void ShowInfoTest1()
{
Info = "Update Info in method: ShowInfoTest1()";
}
像绑定属性一样简单,不同的是,被绑定的不再是属性,而是事件名,而 Path 也不是属性名,而是方法名。相比 ICommand 或行为对此操作的实现,要简单的多。
这里需要补充的是,关于方法的签名:
- 参数可以为空,如:
void ShowInfoTest1()
- 也可以与被绑定事件的签名一致,如:
void ShowInfoTest1(object sender, RoutedEventArgs e)
- 还可以是个数与事件签名的个数一致,事件签名中每个参数类型都可以转换为方法中所定义的参数类型,如:
void ShowInfoTest1(object sender, object e)
如果不一致,在项目编译时就不会通过。
另外,在绑定到事件中,x:Bind 除了支持上述灵活的方法签名,对于方法的返回值并没有要求,不仅可以是 void,也可以是其它任何返回类型;并且也支持 async 方法的绑定。