您的位置:首页 > 移动开发

AvalonDock 2.0+Caliburn.Micro+MahApps.Metro实现Metro风格插件式系统(二)

2015-11-19 19:28 525 查看
上次已经建立了可运行的基本框架,这篇就说说怎么把我们自定义的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 }

[/code]

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     }

[/code]

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 }

[/code]

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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: