01
—
簡介
之前也寫過好多篇CM架構相關的項目實戰文章,比如:
C# WPF架構Caliburn.Micro快速搭建
C# WPF架構Caliburn.Micro入門執行個體1
C# WPF MVVM項目實戰(進階①)
C# WPF MVVM項目實戰(進階②)
C# WPF MVVM模式下在主窗體顯示子窗體并擷取結果
C# WPF Caliburn.Micro架構下利用Mef加載其它項目界面
C# WPF mvvm模式下combobox綁定(list<enum>、Dictionary<int,string>)
C# WPF MVVM模式Caliburn.Micro架構下事件釋出與訂閱
但是可能這些都是把一個綜合性的項目分多個部分分别講述的,有些初學者沒有從前往後連續起來閱讀的話,後面的部分可能就不容易了解了。其次,因為沒有整體的構思,随着内容的增加,項目越來越顯得笨重和淩亂,是以今天我重新搞了一個項目,希望以盡量少的代碼,涵蓋盡量多的知識點,幫助大家更好的了解和使用CM架構。
02
重要知識點
- CM架構的配置和啟動;
- CM架構自帶ioc容器SimpleContainer用法;
- MVVM開發模式;
- 事件聚合器EventAggregator進行事件釋出和訂閱;
-
屬性通知:
① CM架構下基類PropertyChangedBase用法;
②PropertyChanged.Fody.3.1.3下 [AddINotifyPropertyChangedInterface]用法;
- 日志架構:Common.Logging和log4net用法;
- CM架構下命名約定以及事件關聯;
- 用第三方庫Xceed.Wpf.Toolkit.dll做等待窗體;
- CM架構下Conductor用法;
- CM架構下IWindowManager;
- 雙檢鎖單例模式用法;
-
ListBox資料綁定以及窗體切換;
如果以上知識點你都不敢興趣或者已經熟知,那這篇文章不适合你,看到這裡你就可以關閉網頁了!
03
運作結果

04
項目說明
項目主要包括的類檔案如下圖:
① MainWindowViewModel.cs類:
using PropertyChanged;
using System.Collections.ObjectModel;
namespace Caliburn.Micro.Hello
{
[AddINotifyPropertyChangedInterface]
public class MainWindowViewModel : PropertyChangedBase, IViewModel
{
private static readonly Common.Logging.ILog logger = Common.Logging.LogManager.GetLogger<MainWindowViewModel>();
public IViewModel ActiveWindowView { get; set; }
public ObservableCollection<string> ListBoxItems { get; set; }
public string SelectedItem { get; set; }
public MainWindowViewModel()
{
logger.Info($"Enter [MainWindowViewModel].");
ListBoxItems = new ObservableCollection<string>() { };
ListBoxItems.Add("ShellView");
ListBoxItems.Add("EventAggregatorView");
ListBoxItems.Add("ConductorView");
logger.Info($"Leave [MainWindowViewModel].");
}
public void ListBoxItems_SelectionChanged()
{
switch(SelectedItem)
{
case "ShellView":
ActiveWindowView = new ShellViewModel();break;
case "EventAggregatorView":
ActiveWindowView = EventAggregatorViewModel.Instance; break;
case "ConductorView":
ActiveWindowView = new ConductorViewModel(); break;
default:break;
}
}
}
}
- [AddINotifyPropertyChangedInterface]:需要引用第三方庫PropertyChanged.Fody,加上之後類裡面的屬性變更後會自動通知界面,無需再一個個單獨觸發;
- logger是定義的common logging的一個通用日志,需要在nuget上引用:Common.Logging.Log4Net1213;
-
ListBoxItems_SelectionChanged()是listbox的選擇改變事件:
需要在前台附加事件:
-
ActiveWindowView 是我的主窗體,選擇那個就激活那個<ListBox Name="ListBoxItems" Grid.Column="0" SelectedItem="{Binding SelectedItem}" Margin="2" cal:Message.Attach="[Event SelectionChanged] = [Action ListBoxItems_SelectionChanged]"/>
-
<ContentControl Name="ActiveWindowView"/>
②ShellViewModel.cs類:
從ioc容器擷取一個IWindowManager并顯示:
-
CanSayHello和SayHello,隻有CanSayHello條件滿足才會執行SayHelloSimpleContainerViewModel simpleContainerViewModel = new SimpleContainerViewModel(); IWindowManager windowManager = IoC.Get<IWindowManager>(); windowManager.ShowDialog(simpleContainerViewModel);
-
public bool CanSayHello { get { return !string.IsNullOrWhiteSpace(Name); } } public void SayHello() { }
③EventAggregatorViewModel.cs
雙檢鎖線程安全的單例模式:
-
事件訂閱:需要繼承事件接口IHandle<PersonInfoEven>private static EventAggregatorViewModel instance; private static object locker = new object(); /// <summary> /// 雙檢鎖 /// </summary> public static EventAggregatorViewModel Instance { get { if (instance == null) { lock(locker) { if (instance == null) { instance = new EventAggregatorViewModel(); } } } return instance; } }
-
事件處理方法:private readonly IEventAggregator eventAggregator; this.eventAggregator = IoC.Get<IEventAggregator>(); this.eventAggregator.Subscribe(this);
-
public void Handle(PersonInfoEven message) { PersonInfo = message.ToString(); }
④SimpleContainerViewModel.cs
方法1 同步ui釋出事件
-
方法2 開線程去釋出this.eventAggregator.PublishOnUIThread("i am a chinese");
-
this.eventAggregator.Publish(new PersonInfoEven() { Name = "ZYR", Age = 18, Sex = "man" }, action => { //方式① //Task.Factory.StartNew(action); //方式② Task.Run(action); });
等待窗體BusyIndicator ,需要引用第三方庫Xceed.Wpf.Toolkit,
并添加名稱空間:
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
-
<xctk:BusyIndicator Name="busyIndicator" BusyContent="Publish Event ..." IsBusy="{Binding IsShow}" Style="{x:Null}">
⑤ConductorViewModel.cs:此類需要繼承Conductor<object>
将需要激活的執行個體放到ActivateItem,就可以從界面綁定激活對應執行個體窗體
ActivateItem(new ShellViewModel());
05
源碼下載下傳
項目有點長,不可能每個細節都說得到位,能看到這裡的都是真愛,那麼下面給出源碼百度網盤連結:
-
網盤連結: https://pan.baidu.com/s/18LOVAIxy7WCWJisiPcOuAQ 提取碼:添加小編微信擷取 小編微信:mm1552923 公衆号:dotNet程式設計大全