现在的项目结构:
运行结果:
可以看到里面多了一个测试的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 }
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 }
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 }
IDocument接口
1 /// <summary> 2 /// 抽象出Document接口,暂时不写实际东西 3 /// </summary> 4 public interface IDocument : IDockScreen 5 { 6 7 }
PanesStyleSelector类
较第一张更改部分:
DockViewModel类
ShellViewModel类
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 }
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/