【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,结果如下图。

你会发现,下方显示的值是随着输入的变化实时更新的。

这样耍是不是很有逼格呢?

 

完整的示例代码请点击这里下载

 

posted @ 2017-08-30 12:05  东邪独孤  阅读(563)  评论(0编辑  收藏  举报