引言:什么是Caliburn ?

一个夜晚,一处教堂,人们忏悔结束后抬头看到一把宝剑插在一块石头上。石上字述“英格兰人,凡能从石头上拔出剑者,为王者!”,Caliburn就是英格兰人心中的石中剑,这把剑的主人是亚瑟王,但是在一次格斗中,这把剑被伯林诺王斩断。

Caliburn用于一个MVVM产品的名称,其用意明显,作者是想借助于Caliburn的“锋利”来描述这个产品。

Caliburn是一个功能全面的MVVM产品,全面的同时带来了代码量的庞大,作者在这个基础上做了一个精简版,名为 Caliburn.Micro,简写为CM。

一:Caliburn环境搭建

1,Caliburn.Micro的下载地址:https://caliburnmicro.codeplex.com/releases/view/108277,下载完成后可以看一个名为Caliburn.Micro v1.5.2 Snapshot.zip的压缩包。

随时间推移,版本有可能更新,导致名字的变化,此版本下载于2014-10-28 08:07。

2,解压过后可以看到如下目录,每个目录我做了一个简单的备注,如果做应用型开发,我们只需关注samples就够了。

点开bin目录,我们可以看到Caliburn.Micro可用于silverlight,wpf,wp的开发应用。这篇博客重点以WPF的应用来表述MVVM的用法。

二:WPF下的Caliburn.Micro理论

1:双向绑定

在做WPF下的MVVM编码时,我们先普及一个WPF的常识,在WPF中一般有双向绑定的机制,我们看到很多WPF程序的model,viewmodel都继承自INotifyPropertyChanged接口,其实这是在为双向绑定作铺垫。

PropertyChangedBase 继承自 INotifyPropertyChanged ,当我们向UI传递属性变化并且更新客户端UI时会用到INotifyPropertyChanged。

当一个集合项改变时我们则需要使用ObservableCollection<T>。

一般情况下,MVVM的ViewModel都会继承PropertyChangedBase类,以便实现双向绑定机制。

2:Action的处理

ActionMessage,利用TriggerAction的EventTrigger,可以把UI控件中的事件对应到后台方法,类似于CallMethodAction。Caliburn.Micro对ActionMessage进行了扩展,可以传入多个参数,参数支持绑定等功能。

3:Conventions的约定

Conventions,约定,只要View与ViewModel都遵守约定,就会有意想不到的效果,比如神奇的智能匹配。CM制定了一系列匹配的规则,View和ViewModel之间的匹配,控件名与属性,方法的匹配。

4:Screen

在Caliburn中,Screen用来表示UI部件,并且定义UI部件的生命周期(Activated,DeActivated等)。Conductor用来管理Screen,一个Conductor可以管理一组Screen。

三:Caliburn.Micro的引导模式

1:标准WPF程序的引导

标准的WPF的启动程序都是从设置Application结点的StartupUri属性开始的。如下代码:

<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">

2:Caliburn.Micro程序的引导

Caliburn.Micro有自己的引导类,引导类主要通过Configure方法,采用MEF技术组合应用程序部件。

引导类的GetInstance,GetAllInstances,BuildUp,OnStartup方法写法比较固定。除非有特殊的需求,基本不用修改。不过要注意silverlight,wpf,wp写法上略有差异。

比如在实例化CompositionContainer容器时,silverlight用CompositionHost.Initialize方法,WPF用CompositionContainer构造函数。

在用SimpleContainer容器代替CompositionContainer容器时,应在OnStartup方法中加上DisplayRootViewFor<IShell>();这句代码。还有若干的细节问题我们可以在samples例子中慢慢品味。

public class AppBootstrapper : Bootstrapper<IShell>
{
private CompositionContainer _container;
//用MEF组合部件
protected override void Configure()
{
_container = new CompositionContainer(
new AggregateCatalog(
AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()
)
);
//Silverlight版本
//C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client\System.ComponentModel.Composition.Initialization.dll
//container = CompositionHost.Initialize(
// new AggregateCatalog(
// AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()
// )
// ); ///如果还有自己的部件都加在这个地方
CompositionBatch _batch = new CompositionBatch();
_batch.AddExportedValue<IWindowManager>(new WindowManager());
_batch.AddExportedValue<IEventAggregator>(new EventAggregator());
_batch.AddExportedValue(_container);
_container.Compose(_batch);
} //根据传过来的类型和名称获取实例
protected override object GetInstance(Type service, string key)
{
string _contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(service) : key;
var _exports = _container.GetExportedValues<object>(_contract);
if (_exports.Any())
{
return _exports.First();
}
throw new Exception(string.Format("找不到{0}实例", _contract));
} //获取某一特定类型的所有实例
protected override IEnumerable<object> GetAllInstances(Type service)
{
return _container.GetExportedValues<object>(AttributedModelServices.GetContractName(service));
} //将实例传递给 Ioc 容器,使依赖关系注入
protected override void BuildUp(object instance)
{
_container.SatisfyImportsOnce(instance);
} protected override void OnStartup(object sender, StartupEventArgs e)
{
base.OnStartup(sender, e);
//Silverlight
//Application.Current.RootVisual = new ShellView();
//SimpleContainer
//DisplayRootViewFor<IShell>();
}
}

3:设置引导类的启动

在silverlight中,启动一个引导类

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Caliburn.Micro.Hello"
x:Class="Caliburn.Micro.Hello.App">
<Application.Resources>
<local:HelloBootstrapper x:Key="bootstrapper" />
</Application.Resources>
</Application>

在wpf中启动一个引导类为

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local ="clr-namespace:Calib.DWpfApp1"
x:Class="Calib.DWpfApp1.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:AppBootstrapper x:Key="bootstrapper" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

四:代码实践

在xaml编程中,一般都会借助于Blend的两个类库 System.Windows.Interactivity.dll和Microsoft.Expression.Interactions.dll来进行编程。具体引用如下:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
<!--或者-->
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

此处只引用了System.Windows.Interactivity.dll类库。

<Window x:Class="Calib.DWpfApp1.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cm="http://www.caliburnproject.org"
Title="MainView" Height="500" Width="500">

a,Caliburn.Micro根据UI元素名称匹配ViewModel的方法(无参数)

<Button x:Name="OpenOneChild1" Content="打开窗口(无参)" Width="240" Height="30"/>

b,Caliburn.Micro使用Message.Attach匹配ViewModel方法(无参数)

<Button Content="打开窗口(无参)" Width="240" Height="30" cm:Message.Attach="OpenOneChild1" />

c,Caliburn.Micro借助于TriggerAction实现ViewModel方法的调用(有参数)

<Button  Content="打开窗口(有参)" Width="240" Height="30">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cm:ActionMessage MethodName="OpenOneChild2">
<cm:Parameter Value="hello..."></cm:Parameter>
</cm:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>

d,Caliburn.Micro使用Message.Attach匹配ViewModel方法(有参数)

<Button Content="打开窗口(有参,简写)" Width="240" Height="30" cm:Message.Attach="[Event Click] = [Action OpenOneChild2('woo~')]" />

e,Caliburn.Micro使用Message.Attach匹配多个ViewModel方法(有参数)

<Button Content="打开窗口(有参,简写,两个事件)" Width="240" Height="30" cm:Message.Attach="[Event MouseEnter] = [Action Show('Enter')];[Event MouseLeave] = [Action Show('Leave')]" />

f,cm:Action.Target 用法

<ListBox Height="100"  Name="listBox1" SelectionMode="Multiple" >
<ListBoxItem>这是第一项</ListBoxItem>
<ListBoxItem>这是第二项</ListBoxItem>
<ListBoxItem>这是第三项</ListBoxItem>
</ListBox>
<Button Content="全选" HorizontalAlignment="Left" Focusable="False" Name="button1"
cm:Action.Target="{Binding ElementName=listBox1}"
cm:Message.Attach="[Event Click] = [Action SelectAll]"/>

ViewModel的源码参考

[Export(typeof(IShell))]
public class MainViewModel : PropertyChangedBase
{
readonly IWindowManager windowManager;
public string MainTitle
{
get;
private set;
}
[ImportingConstructor]
public MainViewModel(IWindowManager wmanager)
{
MainTitle = "主窗体-MainView";
windowManager = wmanager;
} public void OpenOneChild1()
{
ChildWindowViewModel childViewModel = new ChildWindowViewModel();
windowManager.ShowDialog(childViewModel);
} public void OpenOneChild2(String para1)
{
ChildWindowViewModel childViewModel = new ChildWindowViewModel();
windowManager.ShowDialog(childViewModel);
} public void Show(String para1)
{
System.Windows.MessageBox.Show(para1);
}
}

 五:总结

近段时间接手惠普给我们公司开发的一个项目,我负责WPF程序部份,以前也断断续续的做过wpf的项目,但是用的是MVVMLight,这个项目用的是Caliburn.Micro。

所以在Caliburn.Micro上下了几天功夫。学习来源于网络,也发表一篇与大家共勉。

帮忙右下角“赞”一下,“赞”的高尿的远!

Caliburn实现MVVM模式的编程的更多相关文章

  1. 前后端分手大师——MVVM 模式

    之前对 MVVM 模式一直只是模模糊糊的认识,正所谓没有实践就没有发言权,通过这两年对 Vue 框架的深入学习和项目实践,终于可以装B了有了拨开云雾见月明的感觉. 简而言之 Model–View–Vi ...

  2. [转] 前后端分手大师——MVVM 模式

    之前对 MVVM 模式一直只是模模糊糊的认识,正所谓没有实践就没有发言权,通过这两年对 Vue 框架的深入学习和项目实践,终于可以装B了有了拨开云雾见月明的感觉. Model–View–ViewMod ...

  3. 什么是MVVM模式

    问题引入1 场景一:团队辛辛苦苦完成了一个项目,抱着激动的心情去给用户做demo,而用户给你的反馈是UI很不满意,要重新修改,否则拒绝验收.大规模修改UI,晴天霹雳!2 场景二:产品在一家客户上线运行 ...

  4. Prism 4 文档 ---第5章 实现MVVM模式

        MVVM模式有助于清楚的区分应用程序界面的业务层和展现层.保持一个清晰的应用程序逻辑和UI分离有助于处理开发和设计过程中大量的问题,同时,使得应用程序的测试,维护,和扩展更加容易.MVVM也可 ...

  5. MVP模式与MVVM模式

    1.mvp模式(Model层 Presenter层 View 层) Model层 :数据层(ajax请求) Presenter层:呈现层,view逻辑相关的控制层,控制层可以去调Model去发ajax ...

  6. WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍

    WPF自学入门(十一)WPF MVVM模式Command命令   在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...

  7. MVVM模式的几个开源框架

    原文:MVVM模式的几个开源框架 实现MVVM的框架有很多,如: • MVVM Light Toolkit: http://mvvmlight.codeplex.com • Microsoft Pri ...

  8. 企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(1)

    前言对于WPF和Silverlight来讲,MVVM是微软设计师和业内专家高度推荐的非常棒的一种设计模式.本书会探讨MVVM设计模式的一些自身缺陷以及为什么MVVM还不能成为行业内的标准设计模式.这会 ...

  9. 前端笔记之微信小程序(二){{}}插值和MVVM模式&数据双向绑定&指令&API

    一.双花括号{{}}插值和MVVM模式 1.1 体会{{}}插值 index.wxml的标签不是html的那些标签,这里的view就是div. {{}}这样的插值写法,叫做mustache语法.mus ...

随机推荐

  1. CSS里常见的块级元素和行内元素

    根据CSS规范的规定,每一个网页元素都有一个display属性,用于确定该元素的类型,每一个元素都有默认的display属性值,比如div元素,它的默认display属性值为“block”,成为“块级 ...

  2. 菜单的隐藏&显示

    //还是先上万一老师的原代码 //隐藏与显示菜单Self.Menu := nil; {隐藏菜单} Self.Menu := MainMenu1; {显示菜单} //初一看到代码,我有点抓不到感觉的意思 ...

  3. System.Security.SecurityException The source was not found, but some or all event logs could not be searched.Inaccessible logs Security.

    An exception occurred during the Install phase. System.Security.SecurityException The source was not ...

  4. 简单的dp

    有趣的数:(动态规划,状态转移) #include<stdio.h> ][]; int main() { int n,i; ; i<; i++) dp[i][]=; while(~s ...

  5. 用eclipse搭建SSH(struts+spring+hibernate)框架

    声明: 本文是个人对ssh框架的学习.理解而编辑出来的,可能有不足之处,请大家谅解,但希望能帮助到大家,一起探讨,一起学习! Struts + Spring + Hibernate三者各自的特点都是什 ...

  6. java学习:ArrayList的实现及原理

    1. ArrayList概述: ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素.除了实现 List 接口外,此类还提供一些方法来操作内部 ...

  7. 分离式模型separation model

    1.关键字export 在头文件中定义模板,并且在模板的定义以及声明前添加关键字export. exported 模板可以直接使用,不需要看到该模板定义.模板的使用和定义可以分割于两个不同的编译单元. ...

  8. Cobbler学习之一--Fedora17下配置Cobbler安装环境

    1:Cobbler是什么 Cobbler是一大Linux装机利器,可以快速的建立网络安装环境. 2:安装Cobbler需要的组件 createrepo httpd (apache2 for Debia ...

  9. <Oracle Database>后台进程

    进程监视器进程(PMON)  这个进程负责在出现异常中止的连接之后完成清理.PMON会回滚未提交的工作,并释放为失败进程分配的SGA资源.PMON还负责监视其他的Oracle后台进程,并在必要时(如果 ...

  10. iOS进阶_地图定位

    一.定位步骤 1.Xcode自带地图,直接先引入头文件 #import <CoreLocation/CoreLocation.h> 2.CLLocation框架中的CLLocationMa ...