WP7有约(六):AppBarUtils使用指南
WP7有约(六):AppBarUtils使用指南
Written by Allen Lee
没有你的生活,我开始写小说,好多画面好多灵感,我要把稿费都给你。
– 周杰伦, Mine Mine
这节课的任务
我们知道,Windows Phone的Application Bar并不支持数据绑定,这意味着我们无法像Silverlight的Button控件那样把Application Bar上的按钮或者菜单项直接绑到视图模型的命令属性。
为了解决这个问题,我们可以借助一些第三方工具包,比如今天我给大家介绍的AppBarUtils,它提供了一组Expression Blend行为,可以实现Application Bar上的按钮和菜单项的绑定。接下来,我们将会具体看看如何使用这个工具包实现相关的功能。
首先,假设我们的应用包含了图1-1所示的Application Bar。
图 11 Application Bar
其中,add按钮和clear菜单项分别绑到视图模型的两个命令属性,它们分别负责把数据添加到页面的ListBox控件里和清空ListBox控件里的内容;sync按钮将会执行视图模型的Sync方法;而statistic菜单项将会打开统计结果页面。
在开始之前,你需要到http://appbarutils.codeplex.com/下载AppBarUtils的dll,并在项目里引用它。
按钮和菜单的命令绑定
在Expression Blend里单击左边工具栏上的Assets按钮打开Assets窗口,选择Behaviors类别,然后从右边把AppBarItemCommand拖到Objects and Timeline面板的[PhoneApplicationPage]上,如图2-1所示。
图 21 添加AppBarItemCommand
看到这里,你可能会问,为什么是拖到[PhoneApplicationPage]上呢?因为Application Bar上的按钮和菜单项并非依赖对象,Expression Blend的行为无法和它们关联,而在Windows Phone的应用程序唯一能够访问Application Bar的地方就是页面,所以我们需要把AppBarItemCommand拖到[PhoneApplicationPage]上。
重复上述步骤添加一个AppBarItemCommand。现在我们有两个AppBarItemCommand,分别用于add按钮和clear菜单项。
在Objects and Timeline面板上选中第一个AppBarItemCommand,然后在Properties面板上把Id属性设为add,如图2-2所示。
图 22 设置Id属性
因为AppBarItemCommand是根据Text属性的值查找Application Bar上的按钮的,所以Id属性的值必须匹配Text属性的值。
接着,切换到XAML模式,把AppBarItemCommand的Command属性绑到视图模型的对应的命令属性,如代码2-1所示。
代码 21 设置Command属性的绑定
<AppBarUtils:AppBarItemCommand Id="add" Command="{Binding AddCommand}"/>
看到这里,你可能会问,为什么不直接在Properties面板上设置Command属性的绑定呢?这是因为Expression Blend对Behavior的ICommand类型的属性做了特殊处理,如上面的图2-2所示,这使得Command属性看起来不像普通属性,右边也没有Advanced options按钮,所以无法打开数据绑定对话框。
至于clear菜单项,我们需要在Properties面板上把Id和Type两个属性的值分别设为clear和MenuItem,如图2-3所示。
图 23 设置Id和Type两个属性
需要说明的是,Type属性是用来区分Application Bar上的按钮和菜单项这两种类型的,它的默认值是Button,因此,当你在按钮上使用AppBarItemCommand时,你不需要设置这个属性的值。
最后是Command属性的绑定,和前面一样,我们需要切换到XAML模式设置绑定表达式,如代码2-2所示。
代码 22 设置Command属性的绑定
<AppBarUtils:AppBarItemCommand Type="MenuItem" Id="clear" Command="{Binding ClearCommand}"/>
使用Expression Blend SDK的行为
你知道吗,Expression Blend SDK提供了许多有用的行为,其中一个是CallMethodAction,它可以用来执行指定对象的指定方法,显然非常适合我们的sync按钮,不过,它需要和Trigger一起工作,而Expression Blend SDK并未提供适用于Application Bar的Trigger,怎么办?这个时候就轮到AppBarItemTrigger出场了。
打开Assets窗口,选择Behaviors类别,然后从右边把CallMethodAction拖到Objects and Timeline面板的[PhoneApplicationPage]上,如图3-1所示。
图 31 添加CallMethodAction
确保CallMethodAction处于选中状态,在Properties面板上TriggerType右边的New按钮,如图3-2所示。
图 32 单击New按钮
在弹出的Select Object对话框里选择AppBarItemTrigger,如图3-3所示,然后单击OK按钮关闭对话框。
图 33 选择AppBarItemTrigger
此时,Trigger的相关属性将会换成AppBarItemTrigger的,把Id属性的值设为sync,如图3-4所示。
图 34 AppBarItemTrigger的属性
至于CallMethodAction本身的属性,我们只需把TargetObject属性绑到指定对象,然后把MethodName属性的值设为指定方法的名字就行了。
页面导航行为
有了AppBarItemTrigger,我们就可以使用Expression Blend SDK的NavigateToPageAction为Application Bar实现打开页面的操作了,当然,更简单的办法是直接使用AppBarItemNavigation,它的用法和AppBarItemCommand类似,只是Command属性换成了TargetPage属性。
如果你希望在URI里包含查询字符串,而参数的值又是绑到视图模型的属性的,那么,你可以试试NavigateWithQueryStringAction。
打开Assets窗口,选择Behaviors类别,然后从右边把NavigateWithQueryStringAction拖到Objects and Timeline面板的[PhoneApplicationPage]上,如图4-1所示。
图 41 添加NavigateWithQueryStringAction
确保NavigateWithQueryStringAction处于选中状态,在Properties面板上Trigger改为AppBarItemTrigger,然后把Id、Type和TargetPage三个属性的值分别改为statistic、MenuItem和/StatisticPage.xaml,如图4-2所示。
图 42 设置相关属性
假设我们希望包含的查询字符串是"hitcount=XX&timecount=YY",其中,XX和YY分别来自视图模型的HitCount和TimeCount两个属性,那么,我们可以通过NavigateWithQueryStringAction的Parameters属性进行设置。
在Properties面板上单击Parameters属性右边的Edit items in this collection按钮,在弹出的Parameter Collection Editor对话框里单击Add another item按钮添加一个参数,把Field属性的值设为hitcount,把Value属性绑到视图模型的HitCount属性,如图4-3所示。
图 43 添加参数
用同样的办法添加一个timecount参数,并把它的Value属性绑到视图模型的TimeCount属性。
根据上述设置,NavigateWithQueryStringAction将会为我们创建一个这样的URI:/StatisticPage.xaml?hitcount=9&timecount=13(假设用户单击statistic菜单项时,HitCount和TimeCount两个属性的值分别为9和13)。
由于NavigateWithQueryStringAction是一个TriggerAction,这意味着它的用途并不限于Application Bar,你可以通过Expression Blend SDK的EventTrigger把它用到Silverlight的Button控件(或者其它控件)上。
最后,如果你需要的只是一个简单的后退,你可以使用GoBackAction。和NavigateWithQueryStringAction一样,你可以通过AppbarItemTrigger把它用到Application Bar上,也可以通过EventTrigger把它用到Silverlight的Button控件(或者其它控件)上。
绑定启用状态和显示文字
有些时候,你可能希望Application Bar上的按钮和菜单项可以根据某些条件自动调整启用状态,比如说,当页面的ListBox控件里有内容时,sync按钮才可用,否则,它应该处于禁用状态。
AppBarItemTrigger提供了一个IsEnabled依赖属性,当我们把它绑到视图模型的某个bool类型的属性时,前者会监听后者的更改,然后把修改后的值反映到Application Bar上的按钮或者菜单项的IsEnabled属性。
如果你使用的是AppBarItemCommand,你可以通过ICommand.CanExecute方法的返回值指定启用/禁用状态,并在状态发生更改的时候触发CanExecuteChanged事件,剩下的事情AppBarItemCommand会帮你处理好的。
至于Application Bar上的按钮和菜单项的显示文字,你也可能希望实现绑定,这种需求通常出现在多语言支持的应用里,这个时候,你可以把AppBarItemTrigger的Text依赖属性绑到资源对象的某个属性,前者会监听后者的更改,然后把修改后的值反映到Application Bar上的按钮或者菜单项的Text属性。如果你使用的是AppBarItemCommand或者AppBarItemNavigation,你也可以通过它们的Text依赖属性实现同样的效果。
看到这里,有些同学可能会担心Id和Text两个属性打起架来,放心吧,它们不会的。虽然它们最终都是关联到Application Bar上的按钮或者菜单项的Text属性,但它们发生作用的时间是不同的。Id属性只在行为初始化的时候用来查找Application Bar上的按钮或者菜单项,一旦找到,Id属性就会功成身退了,从此刻开始,Text属性将会派上用场,它会密切关注绑定源,并把更新反映到Application Bar上的按钮或者菜单项的Text属性。
下课了……