随着IOS7由之前UI的拟物化设计变为如今的扁平化设计,也许扁平化的时代要来了,当然我们是不是该吐槽一下,苹果什么时候也开始跟风了,自GOOGLE和微软界面扁平化过后,苹果也加入了这一队伍。

AvalonDock

  AvalonDock 是一个.NET库,用于在停靠模式布局(docking)中排列一系列WPF/WinForm控件。最新发布的版本原生支持MVVM框架、Aero Snap特效并具有更好的性能。

AvalonDock 2.0版本已经发布了,新版本是用MVVM框架重新编写,似乎也用了Command(命令)模式。2.0版的文档尚未发布,但你可以参考Avalon.TestApp 或者2.0版源码中的Avalon.MVVMTestApp文件夹来查看新的API。

这个库使用很简单——只需要用AvalonDock提供的控件包含你自己的控件,页面布局就立即变成可停靠的(dockable)。可以参考 入门 页面获取样例代码,了解不同控件的特性。当然你也可以在自己的C#代码中实例化或操作这些控件。2.0版本中,控件功能与以前一致,但控件名称已经改变,因此建议参考前述样例代码直至参考文档更新为止。

大名鼎鼎SharpEevelop也应用了AvalonDock,由于SharpEevelop的框架过于庞大,并且SharpEevelop里的AvalonDock 1.3的版本,并不支持MVVM的模式,所以就兴起了自己做一个插件式系统,当然也跟一下扁平化的风,目前框架已经做好并应用到个人项目中,本着开源的思想我会把框架搭建的过程,以及遇到的种种问题分享出来。

Caliburn.Micro  

Caliburn是Rob Eisenberg在2009年提出的一个开源框架,可以应用于WPF,Silverlight,WP7等,框架基于MVVM模式,像它的名字一样,是企业级应用的一把利器。

基于WPF的框架有很多,Prism,WAF等,每个框架都有自己侧重点,像Prism侧重于模块间的组合,WAF侧重于分层设计。通观CM的设计,它的一些想法如下: 1.ActionMessage,结合了Blend中的TriggerAction,可以把UI控件中的事件绑定到后台方法,类似于CallMethodAction。CM对ActionMessage进行了很多扩展,包括可以传入多个参数,参数支持绑定,可以通过CanExecute作执行前判断并设置控件的Enable等。

2.Conventions,协定,这个词听上去有点虚,其实就是智能匹配的意思。CM制定了一系列匹配的规则,比如说View和ViewModel之间的匹配,绑定时传入控件名可以找到控件,传入方法名可以绑定到方法等等。

3.Screen和Conductor,作为一个Presentation的框架,各个UI部件(Widget或者叫Pad)的管理是必不可少的。Screen就是用来表示UI部件的,它定义了一些列UI部件的生命期事件,比如Activated,DeActivated等。Conductor是用来管理Screen的,类似于传统的Controller,不同的Screen可以用一个Conductor来管理,Conductor也使用了策略模式允许更改对Screen的处理。

4.Coroutines,协同程序,定义了一组程序的执行,简化了异步编程。比如说在网络中下载图片并显示,通常来说需要显示BusyIndicator,后台线程去网络读取图片,读取成功后Invoke到UI线程,取消BusyIndicator,显示图片。CM提供了一个IResult接口,大大的简化了异步编程,结合ActionMessage,为AOP的扩展提供了可能。

5.配置性和扩展性,CM移除掉了原Caliburn的一些IOC实现,作为一个通用框架,最常用办法就是使用工厂模式结合配置文件提供可配置性,使用IOC来解耦组件间的依赖。CM默认是使用MEF来做IOC扩展的,你可以自定义Bootstrapper来使用你喜欢的IOC容器,如Unity等。

6.设计时支持(Design-time support),CM中的ActionMessage是继承自Blend中的TriggerAction的,也就是说可以在Blend编辑ActionMessage,大大方便了使用。 (这段摘抄了周永恒大大的部分对CM框架的解析,大家想详细了解的话可以去他的博客去学习,我就不仔细说明了,以后我会用到的地方做说明)

MahApps.Metro  

  这是一个Metro样式的开源项目,应用该项目可以使你的软件具有metro的风格,具体就不多说了。

这是测试项目第一阶段的运行结果

言归正传,我们从零开始创建项目,下面是整个测试项目的结构:

MefBootstrapper

这是启动加载类,一般我们WPF程序是从APP.XAML里StartupUri=“****WINDOWS.XAML”来启动主窗体,但现在由MefBootstrapper担当了启动窗体的职责:

 public class MefBootstrapper : Bootstrapper<IShell>{private CompositionContainer container;protected override void Configure(){/*CompositionContainer 对象在应用程序中有两种的主要用途。首先,它跟踪哪些部分可用于组合、它们的依赖项,并且充当任何指定组合的上下文。其次,它提供了应用程序可以启动组合的方法、获取组合部件的实例,或填充可组合部件的依存关系。部件可直接用于容器,或通过 Catalog 属性来用于容器。在此 ComposablePartCatalog 中可发现的所有部件都可以供容器来满足导入,还包括直接添加的任何部件。*/ container = new CompositionContainer(new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x))));var batch = new CompositionBatch();var dockScreenManager = new DockScreenManager();batch.AddExportedValue<IWindowManager>(new WindowManager());//將指定的导出加入至 CompositionBatch 物件batch.AddExportedValue<IDockScreenManager>(dockScreenManager);batch.AddExportedValue<IEventAggregator>(new EventAggregator());batch.AddExportedValue(container);container.Compose(batch);//在容器上执行组合,包括指定的 CompositionBatch 中的更改}protected override object GetInstance(Type serviceType, string key){var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;//获取指定类型的规范协定名称var exports = container.GetExportedValues<object>(contract);//返回具有从指定的类型参数派生的协定名称的已导出对象。如果不是正好有一个匹配的已导出对象,则将引发异常。if (exports.Any())return exports.First();throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));}protected override IEnumerable<object> GetAllInstances(Type serviceType){return container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));}protected override void BuildUp(object instance){container.SatisfyImportsOnce(instance);//满足指定的 ComposablePart 对象的导入,而无需注册该对象以进行重新组合。}}

由上可知, MefBootstrapper继承与CM框架提供Bootstrapper<TRootModel>,当Bootstrapper加载时,CM框架便会从MEF容器里寻找出TRootModel类型的实例,并且show出来,也就是我们的主窗体,之后我会把项目源码放出来,大家可以自己跟踪OnStartup事件。

我们来看看APP.XMAL

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

IShell

  一个简单的接口,为了方便MEF导出部件

  public interface IShell{}

ShellView.xaml

<MetrolControls:MetroWindow x:Class="DemoApplication.ShellView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:MetrolControls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"Title="ShellView" Height="500" Width="800"><Window.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colours.xaml"/><ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml"/><ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml"/></ResourceDictionary.MergedDictionaries></ResourceDictionary></Window.Resources><Grid><ContentControl  x:Name="DockContent" Margin="0,2,0,0" Grid.Row="0"/></Grid>
</MetrolControls:MetroWindow>

  可以看到,这时我们引用了MahApps.Metro,MahApps.Metro自定义了一个WINDOWS,在我看来比传统的和谐那么一点,MahApps.Metro里还有10多种自定义控件,有兴趣的可以自己去研究

ShellViewModel

 [Export(typeof(IShell))]class ShellViewModel:IShell{[Import]public IScreen DockContent { get; set; }}

  一个ShellView.xaml对应一个ShellViewModel,当ShellViewModel标记为Export时,Bootstrapper会把当前程序集所有标记为Export的类导入CM框架的IOC容器里,ShellViewModel相当于ShellView的Datacontext,一个View的加载过程为,由Model找到(CM框架定义了各种查找规则)View,并把Model绑定到View的Datacontext,以后我们UI的逻辑代码就可以写在Model里面,并与UI完全分开,这就是我们所说的MVVM模式。上面也有一个典型的View绑定Model里的属性,细心的可以看到:

[Import]
  public IScreen DockContent { get; set; }

  该属性的名称和ShellView.xaml里的<ContentControl  x:Name="DockContent" Margin="0,2,0,0" Grid.Row="0"/> 的命名完全一样,奇怪的是我们并没有写任何绑定,但DockContent是怎么绑定到View里面的呢,其实绑定的过程已经由CM框架帮我们做了,CM框架会帮助我们把Model里和控件名称一样的属性绑定在一起,这就然我们省了一些事,这只是CM框架的一些小特性。

  好了,主窗体的说完了,下面我们来看看怎么把AvalonDock融合进去,上面我们说过了,一个Model对应一个View,所以我们要显示一个UserControl时得生成一对Model-View,

DockView.xaml

<UserControl x:Class="DemoApplication.Views.DockView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" xmlns:avalonDock="http://avalondock.codeplex.com"d:DesignHeight="300" d:DesignWidth="800"><UserControl.Resources><avalonDock:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/></UserControl.Resources><Grid><Grid x:Name="layoutRoot"><avalonDock:DockingManager  Grid.Row="1" x:Name="dockManager"  AllowMixedOrientation="True"  ><avalonDock:DockingManager.Theme><avalonDock:MetroTheme/></avalonDock:DockingManager.Theme><avalonDock:DockingManager.LayoutItemTemplate><DataTemplate><ContentControl IsTabStop="False" /></DataTemplate></avalonDock:DockingManager.LayoutItemTemplate><avalonDock:LayoutRoot><avalonDock:LayoutPanel  Orientation="Horizontal"  ><avalonDock:LayoutAnchorablePaneGroup DockWidth="200"    Orientation="Vertical"  ><avalonDock:LayoutAnchorablePane  ><avalonDock:LayoutAnchorable Title="left" ></avalonDock:LayoutAnchorable></avalonDock:LayoutAnchorablePane></avalonDock:LayoutAnchorablePaneGroup><avalonDock:LayoutPanel  Orientation="Vertical"  ><avalonDock:LayoutDocumentPaneGroup Orientation="Horizontal"><avalonDock:LayoutDocumentPane   ><avalonDock:LayoutDocument Title="main"></avalonDock:LayoutDocument></avalonDock:LayoutDocumentPane></avalonDock:LayoutDocumentPaneGroup><avalonDock:LayoutAnchorablePaneGroup DockHeight="100"   Orientation="Horizontal"  ><avalonDock:LayoutAnchorablePane  ><avalonDock:LayoutAnchorable Title="bottom" ></avalonDock:LayoutAnchorable></avalonDock:LayoutAnchorablePane></avalonDock:LayoutAnchorablePaneGroup></avalonDock:LayoutPanel><avalonDock:LayoutAnchorablePaneGroup DockWidth="200"    Orientation="Horizontal"  ><avalonDock:LayoutAnchorablePane ><avalonDock:LayoutAnchorable Title="Right" ></avalonDock:LayoutAnchorable></avalonDock:LayoutAnchorablePane></avalonDock:LayoutAnchorablePaneGroup></avalonDock:LayoutPanel></avalonDock:LayoutRoot></avalonDock:DockingManager></Grid></Grid>
</UserControl>

这是VS2012设计器的显示


这些东西的学习周期还是有的,我就不一一去说。有些东西只可意会不可言传。

DockViewModel

    [Export(typeof(IScreen))]public class DockViewModel : Screen{}

  我们可以看到ShellViewModel里的DockContent就是IScreen类型的,由于标记为Import,所以程序会自动帮我们把MEF容器里IScreen类型注入,所以其实DockContent就是DockView,我这里为了方便直接用了CM框架的IScreen,如果有两个类标记为[Export(typeof(IScreen))],就会导致程序异常,因为有两个实例。程序不知道该导出哪个,所以我们之后会定义另一个接口,该接口只有唯一一个类即唯一的DockViewModel标记为导出,因为我们DockView就是唯一的,导入和导出部件这是MEF的知识,MEF是什么大家可以百度学习,CM框架默认是MEF作为容器。

MEF

  Managed Extensibility Framework(MEF)是.NET平台下的一个扩展性管理框架,它是一系列特性的集合,包括依赖注入(DI)以及Duck Typing等。MEF为开发人员提供了一个工具,让我们可以轻松的对应用程序进行扩展并且对已有的代码产生最小的影响,开发人员在开发过程中根据功能要求定义一些扩展点,之后扩展人员就可以使用这些扩展点与应用程序交互;同时MEF让应用程序与扩展程序之间不产生直接的依赖,这样也允许在多个具有同样的扩展需求之间共享扩展程序

第一阶段就先这样,以后我会慢慢更新,直道整个插件系统的完成

如果您看了本篇博客,觉得对您有所收获,请点击右下角的 [推荐]

如果您想转载本博客,请注明出处

如果您对本文有意见或者建议,欢迎留言

感谢您的阅读,请关注我的后续博客

作者:Zengg 出处:http://www.cnblogs.com/01codeworld/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载于:https://www.cnblogs.com/magic-xxj/p/10723880.html

AvalonDock 2.0+Caliburn.Micro+MahApps.Metro实现Metro风格插件式系统(一)相关推荐

  1. WPF框架教程 | 从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器

    之前时间一直在使用Caliburn.Micro这种应用了MVVM模式的WPF框架做开发,是时候总结一下了. Caliburn.Micro(https://blog.csdn.net/lzuacm/ar ...

  2. 从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器

    从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器 这段时间一直在使用Caliburn.Micro这种应用了MVVM模式的WPF框架做开发,是时候总结一下了. Calibu ...

  3. C# WPF MVVM开发框架Caliburn.Micro 自定义Conventions⑩

    处理自定义约定 虽然ViewLocator和ViewModelLocator类通过提供对每个类的NameTransformer实例的公共访问来支持非标准约定,但对于那些不熟悉正则表达式语法的人来说,添 ...

  4. C# WPF MVVM开发框架Caliburn.Micro 关于Conventions⑧

    01 - 关于Conventions Caliburn.Micro的一个主要特性是,它能够通过一系列约定消除对锅炉铭牌代码的需求.有些人喜欢习俗,有些人讨厌习俗.这就是为什么CM的约定是完全可定制的, ...

  5. C# WPF MVVM开发框架Caliburn.Micro Screens, Conductors 和 Composition⑦

    01 - Screens, Conductors and Composition Actions, Coroutines and Conventions往往最能吸引Caliburn.Micro的注意力 ...

  6. C# WPF MVVM开发框架Caliburn.Micro快速搭建③

    01 - 启动项目 打开Visual Studio 创建一个名为"Caliburn.Micro.Hello"的新WPF应用程序 添加对Caliburn.Micro Nuget包的引 ...

  7. C# WPF MVVM开发框架Caliburn.Micro自定义引导程序④

    01 - 自定义引导程序 在上一部分中,我们讨论了Caliburn.Micro WPF应用程序的最基本配置,并演示了与操作和约定相关的两个简单功能.在这一部分中,我想进一步探讨Bootstrapper ...

  8. C# WPF Caliburn.Micro框架下利用Mef加载其它项目界面

    01 - 前言 MEF是微软自家的托管可扩展框架,在这里我把它用成了ioc容器.在Caliburn.Micro框架下,view和viewmodel被注入到CompositionContainer容器中 ...

  9. 【整理总结】代码沉淀 - Caliburn.Micro - MV*模式短小精悍的框架

    Caliburn.Micro - Xaml made easy. web: https://github.com/Caliburn-Micro/Caliburn.Micro document: htt ...

  10. 【愚公系列】2023年02月 .NET CORE工具案例-Caliburn.Micro的使用基于WPF的改造的MVVM案例

    文章目录 前言 1.Caliburn.Micro是什么 2.Caliburn.Micro的主要功能 一.Caliburn.Micro的使用基于WPF的改造 1.项目介绍 2.安装软件包 3.改造App ...

最新文章

  1. mysql校对集_mysql之字符集与校对集
  2. python访问文件下载地址_用Python脚本去获得skydrive上文件的真实地址链接 + 提供脚本下载v2012-01-18...
  3. python钉钉扫码登录程序_使用python+django集成钉钉三方扫码登陆
  4. 深度卷积生成对抗网络(DCGAN)原理与实现(采用Tensorflow2.x)
  5. H5 可堆叠的圆环进度条,支持任意数量子进度条
  6. 比亚迪王传福评价小米造车
  7. UNIX环境高级编程之第9章:进程关系
  8. 使用u盘安装linux操作系统原理
  9. Cmake入门(1)cmake安装,创建第一个工程,引入头文件
  10. distpicker
  11. 两台计算机远程桌面连接不上去,远程桌面连接不上怎么办
  12. fxp连接失败_用FLASHFXP连接站点,总显示连接失败(连接丢失),该怎么办呢
  13. Win7+U盘安装Ubuntu 双系统超级详细教程
  14. 基于JSP+SSH的在线租车汽车租赁系统
  15. 用python 读取excel 指定列
  16. Machine Learning Algorithms Study Notes
  17. 云服务器和普通服务器主要区别有三点
  18. js eventbus
  19. android国外网站
  20. 高通打开内核阶段串口log

热门文章

  1. lldp协议代码阅读_LLDPD协议验证过程记录
  2. 逼疯UE设计师,不可不知的提升产品用户体验的10个测试方法
  3. [RS] 地理空间数据云 使用ftp批量下载影像(以批量下载Landsat8数据为例)
  4. 阿里互联互通再下一城,开放生态缔造新的产业蓝海?
  5. volatile详解
  6. 学习时间序列法ARIMA模型与LSTM很好的文章
  7. 偏执的iOS逆向研究员:收集全版本的macOS iOS+越狱+内核调试
  8. 最佳实践 | 联通数科基于 DolphinScheduler 的二次开发
  9. 斑马Revit:“BIM等级考试证书”究竟要不要考?
  10. 破解获取微信小程序源代码