专栏首页张志敏的技术专栏MvvmCross 框架中的数据绑定语法

MvvmCross 框架中的数据绑定语法

MvvmCross 框架中的数据绑定语法

数据绑定一直是 MvvmCross (Mvx) 框架的核心, 随着 Mvx 版本的版本更新, 绑定语法由 Json 变化到了 Swiss 语法, 并逐渐向 Tibet 过度。 由于基于 Json 的绑定语法在 Mvx 3.0 之后的版本已经标记为过时, 不再支持, 因此不做介绍, 本文详细介绍 Swiss 和 Tibet 语法。

Mvx 实现了跨平台的数据绑定, 概念与 WPF/Silverlight/WinPhone (Xaml) 的数据绑定一致, 可以在 Android 和 iOS 平台使用, 这也正是 Mvx 框架的魅力所在。

Swiss 绑定语法

在 Xaml 平台下, 数据绑定技术是非常普遍的, 比如:

<TextBlock Text="{Binding Path=TweetText, Converter={StaticResource RemainingLength},
    ConverterParameter=140}" />

与之对应的 Swiss 绑定为:

Text TweetText, Converter=RemainingLength, ConverterParameter=140

Swiss 绑定语法看起来比 Xaml 平台下的绑定语法要简洁一些, 接下来详细介绍。

先来看一个最基本的绑定, 将视图 View 的属性 $Target$ 绑定到数据模型 ViewModel 的属性 $SourcePath$ , 如下所示:

$Target$ $SourcePath$

通常情况下 $Target$ 必须是直接是 View 的属性, 例如:

  • Text
  • IsChecked
  • Value

$SourcePath$ 则可以 ViewModel 的属性, 也可以是 ViewModel上 C# 风格的属性路径 (PropertyPath) , 例如:

  • UserId
  • RememberMe
  • Password
  • Customer.FirstName
  • Customer.Address.City
  • Customer.Orders[0].Date
  • Customer.Orders[0].Total
  • Customer.Cards["Primary"].Expiry
  • Customer.Cards["Primary"].Number

在这个最基本的绑定之上, 还可以:

如果 $SourcePath$ 被忽略, 或者直接是一个 . 则将使用整个 ViewModel 作为数据源;

如果需要使用 Converter , 则直接在后面添加:

, Converter=$ConverterName$

$ConverterName$ 标识 ValueConverter 的名称, 通常是将类名去掉 ValueConverter 后缀, 例如: Length 对应的 ValueConverter 的类名是 LengthValueConverter

如果需要 ConverterParameter , 则在后面继续添加:

, ConverterParameter=$ParameterValue$

$ParameterValue$ 允许的内容如下:

  • 单引号或双引号表示字符串;
  • 单词 null 表示 C# 的 null
  • true 或 false 标识布尔值;
  • 整数数字表示 long
  • 浮点数字标识 double

如果需要 FallbackValue , 则继续添加:

, FallbackValue=$FallbackValue$

$FallbackValue$ 允许的内容和 $ParameterValue$ 一致, 再加上 Enum 枚举类型的 ToString() 的字符串形式, 这个在绑定类似 Visibility 之类的属性时非常有用。

如果需要特定的 BindMode , 则继续添加:

, Mode=$WhichMode$

$WhichMode$ 允许的值如下:

  • OneWay
  • OneWayToSource
  • TwoWay
  • OneTime
  • Default

如果需要 CommandParameter , 则可以继续添加:

, CommandParameter=$CPValue$

$CPValue$ 允许的内容与 $ParameterValue$ 相同。

如果需要多个绑定, 则用分号 ; 分割。

下面再看几个具体的例子:

Text Customer.FirstName

Text 绑定到 ViewModel 的 Customer.FirstName 属性;

Text Title, Converter=Length

Text 绑定到 ViewModel 的 Title 属性, 并使用名称为 Length 的 ValueConverter , 而这个 ValueConverter 是 LengthValueConverter 的默认实例;

Text Order.Amount, Converter=Trim, ConverterParameter='£'

Text 属性绑定到 ViewModel 的 Order.Amount , 并应用 Trim ValueConverter , Converter 的参数是字符串 '£'

Text Order.Amount, Converter=Trim, ConverterParameter='£', FallbackValue='N/A'

Bind the Text property to Order.Amount on the ViewModel, but apply the Trim value converter, passing it the string “£”. If no Order is available, or if the Order object doesn’t have an Amount value, then display “N/A”

Text 属性绑定到 ViewModel 的 Order.Amount , 并应用 Trim ValueConverter , Converter 的参数是字符串 '£' , 如果不能成功获取 Order.Amount 的值, 则显示 "N/A"

Value Count, BindingMode=TwoWay

Value 属性绑定到 ViewModel 的 Count 属性, 并指明是双向绑定;

Click DayCommand, CommandParameter='Thursday'

Bind the Click event to the DayCommand property on the ViewModel (which should implement ICommand). When invoked, ensure that Execute is passeda parameter value of “Thursday” 将 Click 事件绑定到 ViewModel 的 DayCommand 属性 ( ICommand 的实现), 当事件被激发时, 传递 "Thursday" 参数。

Fluent 绑定 API

Mvx 还为数据绑定提供了 Fluent API , 可以很方便的使用 C# 代码进行绑定, 通常使用 CreateBindingSet<TView, TViewModel> 扩展方法来完成, 包括:

Bind($ViewObject$) 

其中 $ViewObject$ 是要进行绑定的视图对象;

For(v => v.$ViewProperty$) 

$ViewProperty$ 是视图上的属性, 如果没有提供 For, 将使用默认的属性, 例如: 对于 UILabel 默认的属性是 Text

To(vm => vm.$ViewModelPath$)

$ViewModelPath$ 是 ViewModel 上的属性路径, 数据源;

OneWay()
TwoWay()
OneWayToSource()
OneTime()

指定绑定模式, OneWay, TwoWay, OneWayToSource 还是 OneTime ;

WithConversion($name$, $parameter$)

$name$ 是 ValueConverter 的名称, $parameter$ 是参数;

一些具体的绑定示例如下所示:

var set = this.CreateBindingSet<MyView, MyViewModel>();
set.Bind(nameLabel)
   .For(v => v.Text)
   .To(vm => vm.Customer.FirstName);
set.Bind(creditLabel)
   .For(v => v.Text)
   .To(vm => vm.Customer.Total)
   .WithConversion("CurrencyFormat", "$");
set.Bind(cardLabel)
   .For(v => v.Text)
   .To(vm => vm.Customer.Cards["Primary"].Number)
   .WithConversion("LastFour")
   .OneWay()
   .FallbackValue("N/A");
set.Bind(warningView)
   .For(v => v.Hidden)
   .To(vm => vm.Customer.Alert)
   .WithConversion("Not")
   .FallbackValue(true);
set.Apply(); 

除了上面的基于 lambda 表达式的 Fluent 绑定, 还可以使用基于字符串的 fluent 绑定, 在绑定视图的事件或者视图的属性没有被暴露成 c# 属性时非常有用。 比如, UIButton 并没有暴露 C# 的 Title 属性, 但是依然可以这样进行绑定:

set.Bind(okButton)
   .For("Title")
   .To(vm => vm.Caption);

注意: 当使用 fluent 进行绑定时, 别忘记在最后加上 .Apply() , 否则整个绑定不会起作用。

Tibet 绑定语法

Tibet 是 Swiss 的扩展, 经过精心的设计, 即保持了与现有的 Swiss 绑定的兼容行, 又添加了几个新的特性, 它们是:

多属性属性

如果一个 ViewModel 有两个属性 FirstnameLastname , 而需要在界面上显示完整的名称 Fullname , 通常需要在 ViewModel 上再创建一个额外的属性, 比如:

private string _firstName, _lastName;

public string FirstName {
   get { return _firstName; }
   set { 
      _firstName = value;
      RaisePropertyChanged(() => FirstName);
      RaisePropertyChanged(() => FullName);
   }
}

public string LastName {
   get { return _lastName; }
   set { 
      _lastName = value;
      RaisePropertyChanged(() => LastName);
      RaisePropertyChanged(() => FullName);
   }
}

public string FullName { get { return _firstName + " " + _lastName; } }

在 Swiss 绑定中, 绑定的写法是:

Text Fullname

而在 Tibet 绑定中, 可以这样写:

Text Firstname + ' ' + Lastname

这样就不再需要创建那个额外的属性了。

属性合成

Tibet 提供了属性合成技术, 将数据源上的多个值合成为一个, 比如上面的多值绑定, 就使用了两个 Add 属性合成器将三个值合成为一个。 目前, tibet 只提供了为数不多的几个属性合成器, 它们是:

  • If(test, if_true, if_false) 类似于 C# 中的 ? : 算符;
  • Format(format, args…) 类似于 string.Format 函数;
  • Add(one,two) 将两个值相加, 可以在绑定中使用直接使用 + 代替;
  • GreaterThan(one, two) 判断两个值的大小, 可以在绑定中使用 > 代替;

重要提示: 属性合成还处于开发中, 只是基本可以工作的原型, 在未来的版本中随时都可能变化。

语义绑定

在多值绑定与属性合成中已经见到了, Tibet 支持语义绑定, 比如:

Value 100 * Ratio

Ratio 乘以 100 以转换成百分比, 再比如:

Value Format('Hello {1} - today is {0:ddd MMM yyyy}', TheDate, Name)

使用字符串将 Hello {1} - today is {0:ddd MMM yyyy}TheDataName 进行格式化。

绑定宏

绑定宏尚未实现, 准备支持的特性如下:

  • 访问 parent , global 和 指定名称的绑定上下文;
  • 访问静态变量、 全局字符串、数字、 颜色等,类似提供全局主题样式等;
  • 访问本地化资源, 更容易的实现多语言绑定。

可能的想法是采用特定的字符前缀来实现, 例如: $, #@ 等。

针对 ValueConverters 和 ValueCombiners 的函数式语法

使用 Tibet 绑定, 可以将在 Swiss 绑定:

Text TweetText, Converter=RemainingLength, ConverterParameter=140

用下面的方式重写:

Text RemainingLength(TweetText,140)

注意: ValueCombiner 和 ValueConverter 的名字是共享的, 在运行时 Mvx 会首先查找 Combiner 找不到再查找 Converter 。

嵌套转换

Tibet 还支持嵌套, 比如可以将上面的 Trim 和 Length 一起使用, 如下所示:

Text Length(Trim(FirstName + ' ' + LastName))

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用 mono 编译 .NET Standard 应用

    微软发布 .NET Standard 2.0 已经有一段时间了, 根据 .NET Standard 2.0 支持版本的文档, Mono 5.4 是支持 .NET...

    beginor
  • 使用 Castle Windsor 实现 Web API 依赖注入

    Web API 定义了依赖注入的接口 IDependencyResolver , 定义如下:

    beginor
  • 调用新浪微博显示用户信息

    最近需要在开发的安卓项目中添加新浪微博一件关注的功能, 本来是一个很简单的功能, 就是调用新浪微博客户端显示用户信息的 Activity , 然后用户就点击关注...

    beginor
  • SpringMVC:数据绑定入门(-)

    1.数据类型,可以绑定基本数据类型,如int age,或者包装类型如:Integer age;

    Dar_Alpha
  • Mac开发之 Cocoa 绑定 入门

    从iOS开发转为Mac OSX应用开发的过程中,cocoa 绑定算是比较大的一个差异,也是OSX上比较实用的技术,cocoa 绑定让开发者节省了大量的代码,可以...

    代码行者
  • WCF系统内置绑定列表与系统绑定所支持的功能

    莫问今朝
  • 2019-2-13-wcf入门(15)

    绑定是用于配置wcf如何进行endpoint的对象,其包括协议配置(如2019-2-12-wcf入门(14) - huangtengxiao用到的可靠会话配置)...

    黄腾霄
  • WPF 笔刷绑定不上可能的原因

    在 WPF 中如背景色等都是使用笔刷,在使用绑定的时候可能绑定不上,本文告诉大家绑定不上可能的原因和调试方法

    林德熙
  • day24

    py3study
  • jquery on绑定click事件执行多次

    用$(document).on('click','#XX',function(){...})为元素添加点击事件 结果导致事件会执行多次 。 出现这种情况是因为每...

    似水的流年

扫码关注云+社区

领取腾讯云代金券