Caliburn.Micro tips

最近玩WP7发现了一个很好玩的框架:Caliburn.Micro。玩了几天,遇到了一些问题,总结备忘一下。关于Caliburn.Micro(简称CM),它官方网站有详细的介绍:http://caliburnmicro.codeplex.com/主要是一个轻量级的MVVM,MVP和MVC框架,可用于WPF,silverlight和WP7
在这里我以CM包里面一个简单的例子(Caliburn.Micro.HelloWP7)来介绍遇到过的问题。


1. 在这里 http://caliburnmicro.codeplex.com/releases/view/67451 下载CM包,解压


2. 打开samples目录下的Caliburn.Micro.HelloWP7项目   


3. 首先需要注意的引用程序集,对于wp,

需要引用下面程序集:   

Caliburn.Micro   

Caliburn.Micro.Extension   

System.Windows.Interactivity   

这三个dll,在\bin\WP7\Release 都可以找到


4. 我们发现HelloWP7有一个类:HelloWP7Bootstrapper 

 这个类是用于引导或初始化windows phone项目,初始化Caliburn配置信息,例如协约,ViewModel等


5. 有了HelloWP7Bootstrapper后,还必须在App.xaml中应用程序资源中添加HelloWP7Bootstrapper

<Application.Resources>
<local:HelloWP7Bootstrapper x:Key="bootstrapper"/>
</Application.Resources>


6. 上面我们知道HelloWP7Bootstapper用于初始化WP,   因此,我们要清空App.xaml.cs里面的其它初始化代码,只剩下如下代码:

namespace Caliburn.Micro.HelloWP7 {
using System.Windows;

publicpartialclass App : Application {
public App() {
InitializeComponent();
}
}
}

对于什么要清掉这段代码,官方网站做了这样的解释:Important Note About App.xaml.cs
If you create your WP7 application using a standard Visual Studio template, the generated App.xaml.cs file will have a lot of code in it. The purpose of this code is to set up the root frame for the application and make sure everything gets initialized properly. Of course, that's what the bootstrapper's job is too (and in fact it does a few things better than the out-of-the-box code in addition to configuring CM). So, you don't need both. When using CM's PhoneBootstrapper, be sure to clear out all the code from the App.xaml.cs file except for the call to InitializeComponent in the constructor.


7. 以上几个步骤基本就已经搭建好一个CM环境了,那么CM是如何将界面xaml代码和业务逻辑分开呢?   在HelloWP7项目我们可以看到MainPage还有另外一个类文件 MainPageViewModel.cs,而这个文件正是用于处理MainPage业务逻辑的   那他是怎么跟MainPage关联起来的呢?   我们再看回HelloWP7Bootstrapper类的config函数,我们可以看到以下代码:

container =new PhoneContainer(RootFrame);
container.RegisterPhoneServices();
container.PerRequest
<MainPageViewModel>();

这里第一二行代码是必须的,一定不能删!!container.PerRequest<MainPageViewModel>() 则是讲MianPage注册为一个服务处理每个请求。是否这样MainPage和MainPageViewModel就能联系起来呢?还差一点点


8. 命名规则   要在ViewModel处理业务逻辑不当是要在Bootstrapper中注册ViewModel,还需要特定的命名规则。   对于MainPage的命名规则是 MainPage+ViewModel 也就是MainPageViewModel   但是,对于其它新增的页面就有所区别,新增的必须是以View结尾,比如 LoginView.xaml,RegistView.xaml   而VM的类名必须是LoginViewModel.cs, RegistViewModel.cs。   这里需要注意是MainPage跟其它页面的区别,否则navigate的时候会有NullReference异常。


9. 使用ViewModel处理页面事件   CM使用元素的Name属性来关联前台和ViewModel的关系。   例如:xaml有个x:Name="btnLogin"的按钮,那么ViewModel添加一个btnLogin的共有函数,你就可以在btnLogin函数中处理这个按钮的逻辑      对于SelectedChange事件则必须使用CM中的message机制,比如我们需要将View中ListBox的SelectedChanged交给ViewModel处理   我们必须为ListBox添加以下属性:   cal:Message.Attach="[Event SelectionChanged] = [Action SelectionChanged($source)]"   这里很好理解,Event制定要绑定的事件,Action指定ViewModel处理的事件。即:

ItemTemplate="{StaticResource NewsListItemTemplate}"
ItemsSource
="{Binding Items}"
cal:Message.Attach
="[Event SelectionChanged] = [Action SelectionChanged($source)]"
ItemContainerStyle
="{StaticResource ListBoxItemStyle}"
HorizontalContentAlignment
="Stretch"
ScrollViewer.VerticalScrollBarVisibility
="Disabled"/>

而ViewModel只要添加一个公用的函数SelectionChanged方法就可以了:

publicvoid SelectionChanged(object sender)
{
var listBox
= (ListBox) sender;
if (listBox.SelectedIndex ==-1)
return;
//do whatever you want...
}


10. 通过ViewModel绑定ListBox数据    CM提供了一个用于自动绑定UI线程元素的类BindableCollection    具体用法是在ViewModel声明一个公有成员变量   

public BindableCollection<News> Items { get; private set; }   

这个变量用于保存你的所有数据,在构造函数初始化它,并在特定地方为它添加数据

那么页面ListBox如果使用Items中的值呢,方法很简单,只需要指定ListBox的ItemSource为Items就可以了

<ListBox Height="auto" Name="listBox1" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>


11. CM的navigation    在HelloWP的MainPageViewModel中我们可以看到它的构造函数是这样的:        

public MainPageViewModel(INavigationService navigationService)
{
this.navigationService = navigationService;
}

 这里INavigationService就是CM提供用于navigation的接口。 CM 1.1 支持通过ViewModel来跳转页面,所以用起来很方便,具体代码可以参考HelloWP中的GotoPageTwo()方法。


12. 如何在ViewModel中获取界面控件?   

CM提供了一个类Screen,用于获取当前的界面。因此,我们只要在ViewModel中继承Screen,通过GetView()方法就可以获取view实例。   

MainPage view = (MainPage)GetView(null);    通过view就可以获取页面控件啦。

好了,先总结到这了,enjoy it  :-)

posted @ 2011-06-23 16:07  Chris Cheung  阅读(3101)  评论(3编辑  收藏  举报