Caliburn实现MVVM模式的编程
引言:什么是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模式的编程的更多相关文章
- 前后端分手大师——MVVM 模式
之前对 MVVM 模式一直只是模模糊糊的认识,正所谓没有实践就没有发言权,通过这两年对 Vue 框架的深入学习和项目实践,终于可以装B了有了拨开云雾见月明的感觉. 简而言之 Model–View–Vi ...
- [转] 前后端分手大师——MVVM 模式
之前对 MVVM 模式一直只是模模糊糊的认识,正所谓没有实践就没有发言权,通过这两年对 Vue 框架的深入学习和项目实践,终于可以装B了有了拨开云雾见月明的感觉. Model–View–ViewMod ...
- 什么是MVVM模式
问题引入1 场景一:团队辛辛苦苦完成了一个项目,抱着激动的心情去给用户做demo,而用户给你的反馈是UI很不满意,要重新修改,否则拒绝验收.大规模修改UI,晴天霹雳!2 场景二:产品在一家客户上线运行 ...
- Prism 4 文档 ---第5章 实现MVVM模式
MVVM模式有助于清楚的区分应用程序界面的业务层和展现层.保持一个清晰的应用程序逻辑和UI分离有助于处理开发和设计过程中大量的问题,同时,使得应用程序的测试,维护,和扩展更加容易.MVVM也可 ...
- MVP模式与MVVM模式
1.mvp模式(Model层 Presenter层 View 层) Model层 :数据层(ajax请求) Presenter层:呈现层,view逻辑相关的控制层,控制层可以去调Model去发ajax ...
- WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍
WPF自学入门(十一)WPF MVVM模式Command命令 在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...
- MVVM模式的几个开源框架
原文:MVVM模式的几个开源框架 实现MVVM的框架有很多,如: • MVVM Light Toolkit: http://mvvmlight.codeplex.com • Microsoft Pri ...
- 企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(1)
前言对于WPF和Silverlight来讲,MVVM是微软设计师和业内专家高度推荐的非常棒的一种设计模式.本书会探讨MVVM设计模式的一些自身缺陷以及为什么MVVM还不能成为行业内的标准设计模式.这会 ...
- 前端笔记之微信小程序(二){{}}插值和MVVM模式&数据双向绑定&指令&API
一.双花括号{{}}插值和MVVM模式 1.1 体会{{}}插值 index.wxml的标签不是html的那些标签,这里的view就是div. {{}}这样的插值写法,叫做mustache语法.mus ...
随机推荐
- C++的隐式类型转换
C++是一种复杂的语言,其中有许多“好玩”的特性,学习C++的过程就像在海边捡一颗颗石头,只要坚持不懈,也许一颗颗小石头也能建起你自己小小的城堡. 废话完后,讲讲自己捡到的石头:隐式类型转换 学习出处 ...
- 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案
方案特点: 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案,简化软件开发流程,减少各应用系统相同模块的重复开发工作,提高系统稳定性和可靠性. 基于HTTP协议的开发接口 使用特点在网页 ...
- Laravel 学习笔记 —— 神奇的服务容器 [转]
容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器.一个容器能够装什么,全部取决于你对该容器的定义.当然,有这样一种容器,它存放的不是文本.数值,而是对象.对象的描述(类.接口)或 ...
- 高尔夫管理系统SSH
登录-----------http://localhost:8080/GOLF/Denglu 一.Action 1.处理今日消费数据逻辑的 package com.chinasofti.golf.ac ...
- DEV GridControl双击行事件
首先,需要将gridview1.OptionsBehavior.Editable设为false //双击行弹出nodeDetail信息 private void gridView1_MouseDown ...
- ApiDoc 文档使用方式
1.安装node.js 2.打开node.js 命令窗(shell)键入npm install apidoc -g 自动安装(几分钟) 3. C:\Users\user\AppData\Roaming ...
- mac系统 下 npm 安装 bower报错
在mac终端运行 sudo npm install -g bower (安装之前你要确定你已经成功安装了node 和 git) 然后会报错 like this: npm ERR! Darwin 15. ...
- n+1 < n , are you sure?
密码终于找回了,原来是我邮箱把改密链接的邮件当垃圾邮件了-- 回到正题,这是道面试题,原话大致是这样的: n+1<n成立吗?请说明. 当时我听到这个题后直觉是成立的,但是想不到怎么回事,后来别人 ...
- HttpURLConnection 文件上传限制
一. 问题 最近在Android程序里上传向.Net服务器上传大文件的时候,发现了一个问题.当上传大文件的时候会爆出OutOfMemoryError,上传小文件则没有这种情况. 二. ...
- 远程登录linux不用输入密码的方法
原创文章,欢迎阅读,未经博主允许禁止转载. ssh免密登录,使用密钥认证.执行以下命令,一路回车,就生成了密钥认证.然后,ssh登录,scp等都不用密码了. $ ssh-keygen -t rsa $ ...