Xamarin.Forms Data Binding介绍

很多时候我们需要将某个View1 值的改变显示在另外一个View2 上,对View1的对应事件编码可实现我们想要的效果,如果只是想处理值的改变,可以通过连接两个View的对应属性即可,称为Data Binding。Data Binding在Model-View-ViewModel (MVVM)设计模式中起着重要作用。
Data Binding中设计两个概念SourceTarget。当Source的值发生改变时Data Binding会自动将这个新的值更新到Target。对Target和Source有特殊要求,Target必须继承BindableProperty类(VisualElement通过继承Element继承了BindableObject,所以Xamarin.Forms中视图的大部分属性都是BindableProperty类型),Source必须实现INotifyPropertyChanged接口提供一种通知机制监听Source值的改变(BindableObject实现了INotifyPropertyChanged接口)。

简单的Data Binding使用

本示例以Slider的Value属性作Source,Label的Opacity属性作Target,实现拖动滑块影响Label透明度的效果。

代码方式设置Data Binding:

Xamarin.Forms Data Binding介绍_第1张图片

核心代码设置Target对象的BindingContext属性(BindableObject类型)。再调用Target 对象的SetBinding方法设置绑定属性关系,第一个参数targetProperty为BindableProperty类型,表示目标属性。第二个参数string类型,表示BindingContext的哪个属性为Source。本例调用的是5个参数的方法,后三个参数为默认值。

代码运行效果:

Xamarin.Forms Data Binding介绍_第2张图片

XAML方式设置Data Binding:


     

查看Label定义,BindingContext属性通过x:Reference指定,Opacity为目标属性通过Binding扩展标记的Path设置。Path不仅可以是Property也可以是SubProperty或 Indexer.如Content.Children[4].Value.

在整个视图树中子View是会继承父布局的BindingContext属性。如子View没有单独设置BindingContext属性,会查找上级视图若发现BindingContext赋值会直接继承,如果上级视图同样没有BindingContext赋值且存在上级视图会继续搜索上级视图BindingContext的赋值。本例修改XAML布局代码将Label的BindingContext删除添加到StackLayout中,同样会实现我们想要的效果。


     

同样可以使用属性节点定义方式设置Data Binding相关属性


Reference对应的C#类为ReferenceExtension,Binding对应的类为BindingExtension。两个类的定义都指定了Content Property,分别为Name和Path,所以可以简化代码:

BindingContext="{x:Reference slider}"
Opacity="{Binding Value}" 

前面是通过BindingContext指定Data Binding的Source,还可以通过Binding指定Source。对应的C#代码为SetBinding两个参数的方法:

BindingBase为abstract类,Forms提供了Binding类该类继承了BindingBase。
通过Binding指定Source,再将Binding对象作为参数传入SetBinding方法。

Xamarin.Forms Data Binding介绍_第3张图片

Binding 提供了重载的构造函数和静态方法Create来创建Binding对象,不作介绍。


构造函数示例

Create示例

同样XAML定义方式为,删除BindingContext属性赋值,修改Binding扩展标记。

Xamarin.Forms Data Binding介绍_第4张图片

根据内容属性简化XAML代码:

Opacity="{Binding Value , Source={x:Reference slider}}"

扩展标记定义在一对大括号内且大括号内不应出现双引号,指定多个属性值时通过逗号分隔。
关于内容属性定义的简化写法《Creating Mobile Apps with Xamarin.Forms》中有提到“Even though BindingExtension defines Path as its content property, the argument name can be eliminated only when that argument is the first among multiple arguments.”大概意思是要省略内容属性的参数名称必须将其放在第一个参数,但是测试发现Opacity="{Binding Source={x:Reference slider} , Value}"这种写法同样可以。

那么问题来了,如果我们给BindingContext赋值的同时也为Binding的Source赋值,应该将哪个属性对应的对象作为数据源。符合就近原则Source的优先级高于BindingContext,即指定Source时不在考虑BindingContext。且Source使用更加灵活,如一个对象的多个属性使用不同对象作为数据源只能通过Source方式指定。


Binding Mode 介绍

现在要通过Data Binding实现两个Slider的Value相互影响。滑动一个Slider的同时另一个有相同变化。

Xamarin.Forms Data Binding介绍_第5张图片

愚蠢的办法是分别将两个Slider作为另一个的Source,即同时为两个Slider设置Data Binding。上一个Slider和Label的示例可以理解为Source影响Target,最简单的办法就是可以使Source和Target相互影响。BindingMode枚举可以帮助我们定义target 和 source之间的绑定模式。
BindingMode有四个枚举值:
• Default
• OneWay — Source 的改变影响Target的值(通常是这种情况).
• OneWayToSource — Target的改变影响Source的值.
• TwoWay — Source和Target值改变会相互影响.

对于可读写的BindableProperty对象默认BindingMode为OneWay,只读的BindableProperty对象默认BindingMode为OneWayToSource。
大多数BindableProperty对象BindingMode默认值为OneWay,以下控件的Property的BindingMode方式默认是TwoWay:

Xamarin.Forms Data Binding介绍_第6张图片

由于Slider的Value默认BindingMode为TwoWay,所以实现两个Slider连动XAMlL定义为:


    
    

通过XAML明确指定BindingMode的值Value="{Binding Path=Value Mode=TwoWay}"。通过C#代码指定BindingMode的值slider.SetBinding(Slider.ValueProperty,"Value",BindingMode.TwoWay);


Binding StringFormat 介绍

再次把Slider作为Source,Label作为Target。将Slider的Value值绑定到Label的Text。Value值ToString后直接显示到Label上可能不是我们期望的,Binding类提供了StringFormat属性表示.NET格式化字符串。

Xamarin.Forms Data Binding介绍_第7张图片
StringFormat效果

XAML中StringFormat使用,因为StringFormat本身会包含一对大括号,所以StringFormat赋值时要包含一对单引号:

C#代码设置StringFormat:

label.SetBinding(Label.TextProperty, "Value", stringFormat: "Slider Value Is {0:F3}");

Binding IValueConvert 介绍

目前示例Target需要的数据为string,默认转换或StringFormat可以实现效果。但是Data Binding的Target接受数据类型为一个对象时如何处理?我们可以通过value converter类完成Source到Target的类型转换,需要实现IValueConverter接口,接口有ConvertConvertBack两个方法。

Xamarin.Forms Data Binding介绍_第8张图片
IValueConverter定义

当数据由Source转换到Target时调用Convert方法。Convert方法中value表示Source传递的值,你可以通过GetType来确定它的类型,也可以默认一种类型来处理。targetType表示Target需要的数据类型,Convert方法返回的类型应与targetType相同。parameter在Binding 中会用到,culture为CultureInfo类型需要和地域文化相关的转换时会用到。

ConvertBack方法会在数据由Target转换到Source 时调用,只有Binding Mode为TwoWay 或者 OneWayToSource时才有必要实现该方法,否则直接返回null即可。value参数表示target传递的值,targetType表示source的Type类型。

示例实现效果,一个Entry 和一个Button,当Entry中内容为空时Button不可用,点击Button清空Entry。

定义IntToBoolConverter实现IValueConverter,本示例中Entry为Source,Entry的Text.Length为Path,Button为Target,IsEnabled为绑定的属性。所以自定义的Converter应有Int转换为bool的能力(Convert方法,本例中ConvertBack可直接返回null)。

Xamarin.Forms Data Binding介绍_第9张图片
IntToBoolConverter类定义

XAML中使用Converter要先在Resources字典中定义IntToBoolConverter对象,指定key值,在Binding时通过StaticResource赋值。其中Resources相关内容在Style中介绍。

Xamarin.Forms Data Binding介绍_第10张图片
XAML使用IValueConverter

如果Converter只使用一次,不必在Resources中定义,直接在Binding中通过属性节点定义即可。

Xamarin.Forms Data Binding介绍_第11张图片

《Creating Mobile Apps with Xamarin.Forms》中提供了一个bool转泛型的Converter类,可以将bool值转换为我们想要的值。定义如下:

Xamarin.Forms Data Binding介绍_第12张图片
BoolToObjectConverter定义

在XAML定义时,通过 x:TypeArguments指定我们需要的类型,并设置TrueObject和FalseObject属性。

Xamarin.Forms Data Binding介绍_第13张图片

你可能感兴趣的:(Xamarin.Forms Data Binding介绍)