zoukankan      html  css  js  c++  java
  • AvalonDock 2.0+Caliburn.Micro+MahApps.Metro实现Metro风格插件式系统(二)

      上次已经建立了可运行的基本框架,这篇就说说怎么把我们自定义的View自动加载并添加到AvalonDock里面,AvalonDock里有3种类型的UI部件,Document, DockableContent以及Floting类型,我主要说一下Document,DockableContent的添加,在AvalonDock里Document类型可参考VS,DockableContent相当于VS里的工具栏等,之后我直接在.cs文件里写注释以及解析。

    现在的项目结构:

    运行结果:

      

      可以看到里面多了一个测试的Document,该Document是由MEF自动加载并且绑定到AvalonDock里,这里我只写一个一个Document,有兴趣的可以自己动手试一试,目前的Document是写在主程序里面,其实这Document应该写在一个单独的DLL里面,这就是我们所谓的插件。 [BY Zengg]

    DockScreenManager类  

     1 namespace UICoreFramework
     2 {
     3     /*DemoApplication里面的DockViewModel实现该接口,为了使全部的Documents以及DockableContents集中管理 */
     4     public interface IDockScreenManager
     5     {
     6         //用与绑定到AvalonDock的Document类型的数据源
     7         ObservableCollection<IDocument> Documents { get; }
     8         //用与绑定到AvalonDock的Document类型的数据源
     9         ObservableCollection<IDockableContent> DockableContents { get; }
    10     }
    11     public class DockScreenManager : ViewAware, IDockScreenManager
    12     {
    13         /// <summary>
    14         /// ImportMany是MEF的知识,他的作用是把所有实现某个接口,并标记为Export的类全部倒入,
    15         /// 相当于帮我们自动实例化并添加到List集合里
    16         /// 
    17         /// </summary>
    18         [ImportMany]
    19         public ObservableCollection<IDocument> Documents { get; set; }
    20         [ImportMany]
    21         public ObservableCollection<IDockableContent> DockableContents { get; set; }
    22         public DockScreenManager()
    23         {
    24             
    25         }
    26     }
    27 }
    DockScreenManager

    DocumentBase类

     1   /// <summary>
     2     /// Document的抽象类,一些抽象操作可以在里面写,为了方便我就没写东西
     3     /// DemoApplication的DocTestViewModel就是继承与该抽象类
     4     /// </summary>
     5     public abstract class DocumentBase : IDocument
     6     {
     7 
     8 
     9         public DockType Type
    10         {
    11             get
    12             {
    13                 throw new NotImplementedException();
    14             }
    15             set
    16             {
    17                 throw new NotImplementedException();
    18             }
    19         }
    20 
    21         public DockSide Side
    22         {
    23             get
    24             {
    25                 throw new NotImplementedException();
    26             }
    27             set
    28             {
    29                 throw new NotImplementedException();
    30             }
    31         }
    32 
    33 
    34         public string DisplayName
    35         {
    36             get
    37             {
    38                 return "测试界面";
    39             }
    40             set
    41             {
    42                 throw new NotImplementedException();
    43             }
    44         }
    45 
    46         public bool IsNotifying
    47         {
    48             get
    49             {
    50                 throw new NotImplementedException();
    51             }
    52             set
    53             {
    54                 throw new NotImplementedException();
    55             }
    56         }
    57 
    58         public void NotifyOfPropertyChange(string propertyName)
    59         {
    60             throw new NotImplementedException();
    61         }
    62 
    63         public void Refresh()
    64         {
    65             throw new NotImplementedException();
    66         }
    67 
    68         public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    69     }
    DocumentBase

    IDockScreen接口

     1 namespace UICoreFramework
     2 {
     3     /// <summary>
     4     /// 只有DockableContent类型有位置的说法
     5     /// </summary>
     6     public enum DockSide
     7     {
     8         Left,
     9         Top,
    10         Right,
    11         Bottom
    12     }
    13     /// <summary>
    14     /// Dock的类型
    15     /// </summary>
    16     public enum DockType
    17     {
    18         Document,
    19         DockableContent,
    20     }
    21     /// <summary>
    22     /// 抽象出基本的Content类型,并实现属性通知接口,因为以后绑定到AvalonDock是有双向绑定的,这样我们要操作AvalonDock时
    23     /// 就可以直接操作实现该接口的属性,比如DisplayName的属性用于绑定到AvalonDock的LayoutItem的Title
    24     /// </summary>
    25     public interface IDockScreen:INotifyPropertyChangedEx
    26     {
    27         DockType Type { get; set; }
    28         DockSide Side { get; set; }
    29         string DisplayName { get; set; }
    30     }
    31 }
    IDockScreen

    IDocument接口

    1 /// <summary>
    2     /// 抽象出Document接口,暂时不写实际东西
    3     /// </summary>
    4     public interface IDocument : IDockScreen
    5     {
    6         
    7     }
    IDocument

    PanesStyleSelector类

     1  /// <summary>
     2     /// 这个很重要,这是为使AvalonDock能区别Document和DockableContent类型并返回不同的style,两个类型不同style有不同的绑定属性
     3     /// 所以要区分开来
     4     /// </summary>
     5     public class PanesStyleSelector : StyleSelector
     6     {
     7         public Style ToolStyle
     8         {
     9             get;
    10             set;
    11         }
    12 
    13         public Style DocumentStyle
    14         {
    15             get;
    16             set;
    17         }
    18         /// <summary>
    19         /// 区别逻辑在这里写
    20         /// </summary>
    21         /// <param name="item">实现了IDocument或IDockableContent接口的实例</param>
    22         /// <param name="container"></param>
    23         /// <returns></returns>
    24         public override Style SelectStyle(object item, DependencyObject container)
    25         {
    26             IDockScreen obj = (IDockScreen)item;
    27             
    28             if (item != null)
    29             {
    30                 //判定为什么类型
    31                 if (item is IDocument)
    32                 {
    33                     return DocumentStyle;
    34                 }
    35                 else
    36                 {
    37                     return ToolStyle;
    38                 }
    39             }
    40          
    41             return base.SelectStyle(item, container);
    42         }
    43     }

    较第一张更改部分:

      DockViewModel类

     1 namespace DemoApplication.Views
     2 {
     3     /// <summary>
     4     /// 字符串"DockViewModel"是为了标记唯一性,在ShellViewModel里导入时也要指定为"DockViewModel",这相当于一个key
     5     /// </summary>
     6     [Export("DockViewModel", typeof(IDockScreenManager))]
     7     public class DockViewModel : DockScreenManager
     8     {
     9         public DockViewModel()
    10             : base()
    11         {
    12 
    13         }
    14     }
    15 }

    ShellViewModel类

     1 namespace DemoApplication
     2 {
     3     [Export(typeof(IShell))]
     4     class ShellViewModel : IShell
     5     {
     6         readonly IWindowManager windowManager;
     7         [ImportingConstructor]
     8         public ShellViewModel(IWindowManager windowManager)
     9         {
    10             this.windowManager = windowManager;
    11 
    12         }
    13         /// <summary>
    14         /// DockView
    15         /// </summary>
    16         [Import("DockViewModel")]
    17         public IDockScreenManager DockContent { get; set; }
    18     }
    19 }

    MefBootstrapper类

     1  protected override void Configure()
     2         {
     3             /*CompositionContainer 对象在应用程序中有两种的主要用途。首先,它跟踪哪些部分可用于组合、它们的依赖项,并且充当任何指定组合的上下文。其次,它提供了应用程序可以启动组合的方法、获取组合部件的实例,或填充可组合部件的依存关系。
     4             部件可直接用于容器,或通过 Catalog 属性来用于容器。在此 ComposablePartCatalog 中可发现的所有部件都可以供容器来满足导入,还包括直接添加的任何部件。*/ 
     5             //container = new CompositionContainer(
     6             //    new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)))
     7             //    );
     8 
     9             
    10             var catalog = new AggregateCatalog(
    11                AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()
    12                );
    13 
    14             container = new CompositionContainer(catalog);
    15 
    16             var batch = new CompositionBatch();
    17             var dockScreenManage = new DockScreenManager();
    18             batch.AddExportedValue<IWindowManager>(new WindowManager());//將指定的导出加入至 CompositionBatch 物件
    19             batch.AddExportedValue<IEventAggregator>(new EventAggregator());
    20             batch.AddExportedValue<IDockScreenManager>(dockScreenManage);
    21             batch.AddExportedValue(container);
    22             batch.AddExportedValue(catalog);
    23             container.Compose(batch);//在容器上执行组合,包括指定的 CompositionBatch 中的更改
    24 
    25             container.ComposeParts(container.GetExportedValue<IDockScreenManager>());//由于DockScreenManager里有标记为Import的字段,所以要在MEF容器里组装把指定的部件导入
    26         }
    MefBootstrapper

    AvalonDock还支持其他几种皮肤,可以满足大众的需求:

    AeroTheme

     ExpressionLightTheme

    ExpressionDarkTheme

    VS2010Theme

       DockableContent类型的实现和Document实现是一样的,只是实现的接口不同,DockableContent实现的是IDockableContent接口,具体请参考Document实现,有疑问的可以提出来,尽量帮助解决,解释写得略简单不好意思,但是有源码参考,如果源码对大家有帮助的话,求个推荐,回复或粉的神马的都好。。。

    源码地址:

    http://pan.baidu.com/share/link?shareid=819683340&uk=554439928

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

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

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

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

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

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

  • 相关阅读:
    什么是高大上项目?
    spring事务回滚问题
    分布式ActiveMQ集群
    基于bootstarp的Dailog
    js实现的笛卡尔乘积-商品发布
    MemcachedClient 使用说明
    docker centos容器无法yum
    java Graphics2D 画图
    spring boot 访问外部http请求
    JSON 数据重复 出现$ref
  • 原文地址:https://www.cnblogs.com/01codeworld/p/3157368.html
Copyright © 2011-2022 走看看