【Windows 10 应用开发】使用x:Bind标记动态获得计算结果
UWP 在传统(WPF)的Binding标记上引入了 Bind 标记,Bind 基于编译阶段生成,因而具有较高的性能。但是,你得注意,这个性能上的优化是免去了运行阶段动态绑定的开销,这是不包括数据源的体积的。要是你的数据源本身很大的话,那是没办法优化的,只能靠你自己想办法,尽可能把加载到内存中的数据缩小,比如你只加载300条,不要一下子就读几万条数据。当然也可以使用增量加载方案。
Bind 标记还有一个特色——可以绑定事件处理方法和常规方法,可以给绑定的方法传递参数。比如有这样一个方法:
int Add ( int x, int y )
你可以这样绑定:
<obj prop= "{x:Bind Add(2,5)}" ... />
在使用过程中,你还可以进行类型强制转换。
<obj prop = "{x:Bind ((Button)parm).Content}" .../>
你必须注意的,由于bind标记是在编译阶段完成的,所以在类型强制转换时,你要保证转换是有效的。说白了就是,类型必须是能转的,比如这样在编译时会报错。
<obj prop = "{x:Bind (string)Add(2,8)}" .../>
因为 int 类型是不能直接强制转换为 string 类型的。
Bind 标记虽然逼格很高,但装逼是有极限的,就目前而言,Bind 标记与方法绑定的功能还是有限的,毕竟在语法上不是那么容易识别,将来也许会变强大一些。
就目前来说,Bind有以下局限:
a、不能绑定嵌套方法。这样绑定是会挂的。
<obj prop = "{x:Bind sys:Math.Min( sys:int.Parse(txt1.Text), sys:int.Parse(txt2.Text) )}" ... />
在调用 Min 方法时,嵌套了 Parse 方法的调用,目前这样做是不行的,编译时会报错。
b、参数与返回值的类型必须匹配。比如我们前面举过例的那个 Add 方法,它接受两个 int 类型的参数,如果我们这样写,也是有问题的。
<obj prop = "{x:Bind Add(txtBox1.Text, txtBox2.Text)}" .../>
TextBox的Text属性是字符串类型,直接传给int类型的参数是会出错的。
再比如,这样写返回。
<TextBlock Text = "{x:Bind Add(3,6)}" .../>
Add 方法返回的是 int 类型的值,而 TextBlock 类的 Text 属性是字符串类型的,此处也会报错。
在引用其他 XAML 元素时,Bind 标记不需要像 Binding 元素那样使用 ElementName 属性来指定名称。只要给相应的 XAML 元素命名,然后就可以直接引用了。比如这样。
<TextBox x:Name="txtFirst" /> <TextBlock Text = "{x:Bind txtFirst.Text}" />
要把 TextBlock 对象的 Text 属性与前面 TextBox 的 Text 属性绑定,TextBox 是数据源,只要它一个名字,然后就可以直接引用了,txtFirst.Text。
下面给大家演示一个简单的例子,一起来用 x:Bind 来装装X。
这个例子是这样的:两个文本框,分别输入数值,然后在下方动态显示两个数值中较大的一个。比如,你输入了 7 和 11,那么,就显示 11 。
这里我们得考虑到局限性,因为 TextBox 类的 Text 属性是 string 类型,所以不能直接与 Math类的 Max 方法绑定,这样很难进行类型转换,故我们最好进行一下封装。
public class Test { public static string MaxNum(string s1, string s2) { double d1, d2; if (double.TryParse(s1, out double tmp)) d1 = tmp; else d1 = 0d; if (double.TryParse(s2, out double tmp2)) d2 = tmp2; else d2 = 0d; double res = Math.Max(d1, d2); return res.ToString("N"); } }
把计算方法定义为静态的就行了,这样可以直接拿来耍。
这个方法接收的参数是字符串类型,返回值也是字符串类型,为啥呢,你看了下面的XAML就知道了。
接下来,看看界面布局。
<StackPanel Margin="16"> <TextBox x:Name="txtNum1" Header="第一个数值:"/> <TextBox x:Name="txtNum2" Header="第二个数值:"/> <TextBlock> <Run Text="其中较大的一个数是:"/> <Run Foreground="Blue" FontSize="16" Text="{x:Bind local:Test.MaxNum(txtNum1.Text,txtNum2.Text),Mode=OneWay}"/> </TextBlock> </StackPanel>
因为显示较大数值的是 Run 元素,它的 Text 属性是字符串类型,为了避免出现类型转换的错误,所以刚才的 MaxNum 方法要返回字符串类型。
这个地方,要显式地 Mode 设置 OneWay,不然它会用 OneTime 来绑定,这样就无法动态获取计算结果了。
好了,运行一下,假设输入 200.65 和 105.33,显示的结果如下图所示。
然后,我们把 200.65 改为 -300,结果如下图。
你会发现,下方显示的值是随着输入的变化实时更新的。
这样耍是不是很有逼格呢?
完整的示例代码请点击这里下载。