WP7应用开发笔记(14) 使用Caliburn Micro简化MVVM
续上一篇对MVVM模式的简单介绍,可以了解到MVVM需要编写许多的自定义Command和Action之类的,而且每个类都需要设置DataContext。操作和代码比较重复,为了减少代码量并统一标准,需要引入MVVM框架提高效率。
开源的MVVM框架有:
PRISM:由微软提供,和 MEF/Unity 一起用于依赖注入,支持组合命令,可以扩展。MSDN 上有详细的教程和演练。
MVVM Light Toolkit:有 visual Studio 和 Expression Blend 的项目和项的模板。更多信息请看这里,另外可以参考 VS 和 Expression Blend 的使用教程。
Caliburn Micro:小巧但功能强大框架,支持简化绑定,注入等,实现多种 UI 模式解决实际问题.
Simple MVVM Toolkit:提供 VS 项目和项的模板,依赖注入,支持深拷贝以及模型和视图模型之间的属性关联。
Catel:包含项目和项的模板,用户控件和企业类库。支持动态视图模型注入,视图模型的延迟加载和验证。还支持 WP7 专用的视图模型服务。
这里我准备使用Caliburn.Micro,它很好的支持WP7.1还特别包含了专门为WP设计的Caliburn.Micro.Extensions
开源项目地址:
http://caliburnmicro.codeplex.com/
Caliburn.Micro框架的一些特点
Caliburn.Micro里面使用了很多名称约定来实现和简化代码,而且提供了很多机制减少开发工作。
1. 简化绑定
Caliburn.Micro设计了一个Binding Conventions 绑定公约,能够简化绑定代码:
直接设置与绑定相同名称的(区分大小写)x:Name 就可以自动被绑定了
1) 简化数据绑定:
<TextBox Text="{Binding Path=CustomerName}" />
在Caliburn.Micro中可以写成:
<TextBox x:Name=”CustomerName” />
达到同样的数据绑定效果,而且默认为双向绑定。
2)简化命令绑定:
而且同样支持命令绑定而且更加简化:
原来实现命令绑定的主要代码:
public ICommand HelloCommand{ get; set; }
HelloCommand = new InvokeCommand(OnHello);
public void OnHello(){
MessageBox.Show(“Hello world”)
}
<Button Command="{Binding HelloCommand}" />
在Caliburn.Micro中可以写成,直接与方法名相同就可以了,其余的Command可以一概不用。
<Button x:Name=”OnHello” />
3)简化动作绑定(事件绑定):
动作绑定在Caliburn.Micro中实现了自己的ActionMessage,将原来的绑定方式:
<Button Content="Button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<local:InvokeAction Command="{Binding HelloCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
写为下面的方式,并设置MethodName为对应的方法名字就可以了。
<Button Content="Button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="OnHello" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
此外还可以设置方法的参数Parameter ,使用$eventArgs可以将eventArg对象自动传入进去。
<cal:Parameter Value="$eventArgs" />
2 自动View-ViewModel映射
不需要写DataContext = new MainPageViewModel();之类的代码,Caliburn.Micro可以自动完成这个映射,
只需要按照名称约定来实现:
View全部为: {CustomName}View
ViewModel 对于的名称: {CustomName}ViewModel
如:HelloView 就会自动映射并绑定到HelloViewModel 。
需要注意的是命名空间也是有要求的:
有2种命名空间方式可以被正确识别:
- View和ViewModel在同一名称空间下.
- View 在Views名称空间下,ViewModel在ViewModels名称空间下。
3 依赖注入
因为Caliburn.Micro内部使用了IoC容器,依赖注入也是很容易的功能,这里就不详细介绍了。
需要提示的是Caliburn.Micro在WP里面使用的是一个轻量级的PhoneContainer容器。
4 辅助接口
MVVM模式比较复杂的地方就是ViewModel之间的交互。Caliburn.Micro提供了非常多的可供注入的接口提供给
ViewModel使用。
1)INavigationService 导航服务接口:
页面导航是WP开发的重要功能,INavigationService接口实现了封装导航功能,并能在ViewModel里被注入使用。
首先是构造函数注入:
public MainPageViewModel(INavigationService navigationService…)
{
this.navigationService = navigationService;
}
然后直接可以导航到ViewModel,不需要知道View的相对地址:
navigationService.UriFor<ConfigViewModel>().Navigate();
当然也可以后退:
navigationService.GoBack();
2)墓碑机制和ViewModel状态存储和中断恢复
我先称赞一下,这个功能很强大!
墓碑机制是微软Windows Phone 7手机操作系统中的一个程序运行规则。说简单点,就是手机上一个任务被迫中断时(如有电话打入),系统记录下当前应用程序的状态后,(像把事件记录在墓碑上一样),然后中止程序。当需要恢复时,根据“墓碑”上的内容,将程序恢复到中断之前的状态。这样的一种机制就是“墓碑机制”。
不过恢复中断状态需要手动编写非常麻烦,Caliburn.Micro提供了更简单的实现,大大提高了效率。
IStorageHandler和抽象类StorageHandler<T> 可以保存和恢复ViewModel状态,支持存储在State或者IsolatedStorageSettings中,
使用非常方便而且能自动工作。
首先看看一个简单ViewModel例子:
public class MainPageViewModel:Screen
{
private string hello;
public string Hello
{
get { return hello; }
set
{
hello = value;
NotifyOfPropertyChange(() => Hello);
}
}
}
根据MainPageViewModel 定义MainPageViewModelStorage类,继承StorageHandler<MainPageViewModel>
定义完成后不用引用,Caliburn.Micro会自动工作。
public class MainPageViewModelStorage : StorageHandler<MainPageViewModel>
{
public override void Configure()
{
Id(p => p.DisplayName);
Property(model => model.Hello)
.InPhoneState()
.RestoreAfterActivation();
}
}
首先需要指定Id为ViewModel的唯一标识,这里使用Id(p => p.DisplayName)。
然后设置各个Property的存储方式和恢复事件。
存储方式有InPhoneState和InAppSettings。
恢复事件有RestoreAfterActivation、RestoreAfterViewLoad、RestoreAfterViewReady。
这个设置方式是不是有点像NHibernate的Map映射。
3)IWindowManager 窗体管理
可以打开自定义的Dialog或者Popup
同样只需要知道ViewModel不需要知道View,例如:
windowManager.ShowDialog(new ConfigViewModel);
4)IEventAggregator 窗体间消息通知
实现观察者模式和中介者模式,IEventAggregator 作为中介者从一个ViewModel向另一个订阅消息的ViewModel发送消息对象。
在WP里面用得比较少,不过IEventAggregator 内部实现了UI线程切换有时候还是比较方便。
具体可以参考文档:
如果需要继续深入的学习请参考:
请学习 Caliburn.Micro v1.3 RTW\samples\ 提供的示例代码:
特别是:
Caliburn.Micro.HelloWP71
Caliburn.Micro.HelloWindowManagerWP71
阅读文档:
Documentation: 详细文档:
http://caliburnmicro.codeplex.com/documentation
Working with Windows Phone 7 v1.1:(里面在WP项目中引入Caliburn.Micro)
园子里的一些Caliburn.Micro教程: