上一篇分析了EventAggregator,我們直到了如何使用EventAggregatir,因為示例比較簡單,所以我們沒有寫DEMO,結合EventAggregator和15示例,FilteringEvents來過濾事件,我們就可以寫一個相對復雜一點的DEMO,用于理解EventAggregator和FilterEvent,
- 從15示例繼續學習Prism下的MVVM思想
- 分析15示例FilterEvent,學習在EventAggretator中如何使用FilterEvent,
- 1、參考關系
- 2、分析UsingEventAggregator.Core工程
- 2.1、MessageSentEvent.cs
- 3、分析ModuleA工程
- 3.1、ModuleAModule.cs
- 3.2、Views下的MessageView.xaml
- 3.3、ViewModel下的MessageViewModel.cs
- 4、分析ModuleB工程
- 4.1、ModuleBModule.cs
- 4.2、Views下的MessageList.xaml
- 4.3、ViewModels下的MessageListViewModel.cs
- 5、分析主工程UsingEventAggregator
- 5.1、App.xaml
- 5.2、App.cs
- 5.3、Views下的MainWindow.xaml
- 5.4、ViewModels下的MainWindowViewModel.cs
- 分析15示例FilterEvent,學習在EventAggretator中如何使用FilterEvent,
- 我創建了一個C#相關的交流群,用于分享學習資料和討論問題,歡迎有興趣的小伙伴:QQ群:542633085
從15示例繼續學習Prism下的MVVM思想
分析15示例FilterEvent,學習在EventAggretator中如何使用FilterEvent,
1、參考關系
UsingEventAggregator.Core工程參考了Prism.Core;
ModuleA工程參考了UsingEventAggregator.Core、參考了Prism.Wpf;
ModuleB工程參考了UsingEventAggregator.Core、參考了Prism.Wpf;
UsingEventAggregator工程參考了ModuleA、ModuleB、UsingEventAggregator.Code、Prism.Unity,
2、分析UsingEventAggregator.Core工程
UsingEventAggregator.Core中參考了Prism.Core;
2.1、MessageSentEvent.cs
在MessageSentEvent.cs中創建了MessageSentEvent并繼承自PubSubEvent
3、分析ModuleA工程
ModuleA中參考了Prism.Wpf、參考了UsingEventAggregator.Core;
3.1、ModuleAModule.cs
ModuleAModule繼承自Prism.Modularity.IModule
在ModuleAModule中的OnInitialized()方法中獲取到了RegionManager物件,然后關聯顯示區域LeftRegion和視圖MessageView,
3.2、Views下的MessageView.xaml
在MessageView.xaml 中添加命名空間prism="http://prismlibrary.com/",添加prism.ViewModelLocator.AutoWireViewModel=true用于自和ViewModel關聯,
xaml中包含一個用于輸入的文本框TextBox 輸入內容系結到了Message屬性,Button是系結到了一個SendMessageCommand命令,這2個物件都是ViewModel下的,cs檔案中無額外代碼;
3.3、ViewModel下的MessageViewModel.cs
MessageViewModel繼承自Prism.Mvvm.BindableBase,創建了一個屬性Message,一個DelegateCommand型別的SendMessageCommand命令,創建欄位IEventAggregator型別的_ea,在建構式MessageViewModel()中初始化ea和SendMessageCommand,使他系結到SendMessage()方法,
SendMessage()方法使用ea欄位獲取MessageSendEvent事件,然后使用Publish的方法觸發事件,然后再訂閱該事件的地方就可以接收到訊息了,
4、分析ModuleB工程
ModuleB參考了Prism.Wpf、UsingEventAggregator.Core;
4.1、ModuleBModule.cs
ModuleBModule繼承自Prism.Modularity.IModule,再OnInitialized()方法中獲取RegionManager物件,關聯RgihtRegion顯示區域和MessageList視圖,
4.2、Views下的MessageList.xaml
MessageList.xaml 添加命名控制元件prism="http://prismlibrary.com/",添加prism:ViewModelLocator.AutoWireViewModel=true用于關聯ViewModel,
添加了一個顯示控制元件ListBox ItemsSource系結位Messages物件,cs檔案下無額外代碼
4.3、ViewModels下的MessageListViewModel.cs
MessageListViewModel繼承自Prism.Mvvm.BindableBase,創建屬性Messages,創建欄位_ea并在建構式中初始化,建構式中實體化Messages,同時使用ea訂閱MessageSentEvent事件,重點來了,這一篇主要的內容就是這一段代碼,我們再Subscribe上使用F12跳轉過去,
IEventAggregator _ea;
public MessageListViewModel(IEventAggregator ea)
{
_ea = ea;
Messages = new ObservableCollection<string>();
_ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived, ThreadOption.PublisherThread, false, (filter) => filter.Contains("Brian"));
}
//
// 摘要:
// Subscribes a delegate to an event.
// 訂閱事件的委托,
// 引數:
// action:
// The delegate that gets executed when the event is published.
// 發布事件時執行的委托,
//
// threadOption:
// Specifies on which thread to receive the delegate callback.
// 指定在哪個執行緒上接收委托回呼,
//
// keepSubscriberReferenceAlive: //保持訂閱服務器參考處于活動狀態
// When true, the Prism.Events.PubSubEvent`1 keeps a reference to the subscriber
// so it does not get garbage collected.
// 如果為true,則Prism.Events.PubSubEvent`1保留對訂閱服務器的參考,因此不會對其進行垃圾收集,
//
//
// filter:
// Filter to evaluate if the subscriber should receive the event.
// 篩選以評估訂閱服務器是否應接收事件,
//
// 回傳結果:
// A Prism.Events.SubscriptionToken that uniquely identifies the added subscription.
// 唯一標識添加訂閱的Prism.Events.SubscriptionToken,
//
// 言論:
// If keepSubscriberReferenceAlive is set to false, Prism.Events.PubSubEvent`1 will
// maintain a System.WeakReference to the Target of the supplied action delegate.
// If not using a WeakReference (keepSubscriberReferenceAlive is true), the user
// must explicitly call Unsubscribe for the event when disposing the subscriber
// in order to avoid memory leaks or unexpected behavior. The PubSubEvent collection
// is thread-safe.
//
// 如果keepSubscriberReferenceAlive設定為false,
// 則Prism.Events.PubSubEvent`1將維護對所提供操作委托的目標的System.WeakReference,
// 如果未使用WeakReference(keepSubscriberReferenceAlive為true),
// 則用戶在處理訂閱服務器時必須顯式呼叫Unsubscribe以避免記憶體泄漏或意外行為,PubSubEvent集合是執行緒安全的,
//
public virtual SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate<TPayload> filter);
我們詳細看一下這里的說明:
第一個引數Action
第二個引數是列舉型別的ThreadOption,有三個引數PublisherThread,UIThread,BackgroundThread,看名稱我們就能理解,設定代碼在什么執行緒上作業;
第三個引數是Bool型別的,看說明如果設定為true則該訂閱不會對其進行垃圾回收;
最后一個引數就是我們的過濾器,用于篩選是否符合我們要求的Event;
我們在看這段代碼
public MessageListViewModel(IEventAggregator ea)
{
_ea = ea;
Messages = new ObservableCollection<string>();
_ea.GetEvent<MessageSentEvent>().Subscribe(MessageReceived, ThreadOption.PublisherThread, false, (filter) => filter.Contains("Brian"));
}
private void MessageReceived(string message)
{
Messages.Add(message);
}
在使用Subscribe的時候,第一個引數傳入了MessageReceived作為回呼函式,ThreadOption設定為PublisherThread作業執行緒,false代表該訂閱需要GC進行垃圾回收,子厚一個引數是一個匿名函式,因為MessageSentEvent傳入的是string型別的引數,所以filter是這個string型別的形參,filter.contains("Brian")是在實際呼叫中,判斷filter中是否包含Brian字串,結合ModuleA就是判斷用戶輸入的內容中是否包含Brian,如果包含則觸發MessageReceived函式,
5、分析主工程UsingEventAggregator
UsingEventAggregator工程參考了Prism.Unity,參考了ModuleA、ModuleB、UsingEventAggregator.Core;
5.1、App.xaml
添加prism="http://prismlibrary.com/"命名空間
修改Application為prism:PrismApplication;
移除StartUpUri屬性
5.2、App.cs
修改App繼承自PrismApplication
重新CreateShell()設定啟動頁為MainWindow
重寫ConfigureModuleCatalog()用于加載ModuleA下的ModuleAModule和ModuleB下的ModuleBModule
5.3、Views下的MainWindow.xaml
添加命名空間prism="http://prismlibrary.com/"
設定prism:ViewModelLocator.AutoWireViewModel=true關聯ViewModel
通過Grid把當前Window平均左右布局分成2份,在Grid中使用ContentControl左右各放置一個,并設定附加依賴項屬性prism:ReegionManager.RegionName為LeftRegion和RightRegion,cs代碼中無新增內容
5.4、ViewModels下的MainWindowViewModel.cs
MainWindowViewModel繼承自Prism.Mvvm.BindableBase;
設定了屬性Title并初始化,用于顯示Main中的Title;
總結示例:我們分析了整個工程的代碼,通用部分的代碼通過這么多例子的講解我們基本上都了解了,這里就不說了,就說這篇最重要的部分,UsingEventAggregator.Core下的MessageSentEvent.cs繼承了PubSubEvent,引數為String,
ModuleA和ModuleB無直接關聯關系,ModuleA通過在ViewModel中接收IEventAggregator,來關聯Command和MessageSentEvent的Publish.用于發送事件,
ModuleB在ViewModel中接收IEventAggregator,通過訂閱Subscribe時傳入的匿名函式的引數filter來過濾包含Brian的訊息才會觸發前面的回呼,
就完成了EventAggregator相關的訂閱、觸發、過濾功能,
這篇也比較簡單, 先不寫DEMO了,繼續往后看,
我創建了一個C#相關的交流群,用于分享學習資料和討論問題,歡迎有興趣的小伙伴:QQ群:542633085
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/295837.html
標籤:WPF
