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/

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM