Caliburn.Micro 傑的入門教程1(原創翻譯)
Caliburn.Micro 傑的入門教程2 ,了解Data Binding 和 Events(原創翻譯)
Caliburn.Micro 傑的入門教程3,事件和參數
Caliburn.Micro 傑的入門教程4,事件聚合器
Caliburn.Micro 傑的入門教程5,窗口管理器
Caliburn.Micro 傑的入門教程6, Screens 和 Conductors 簡介
Caliburn Micro Part 4: The Event Aggregator
http://www.mindscapehq.com/blog/index.php/2012/2/1/caliburn-micro-part-4-the-event-aggregator/
在本周的教程中,我們將學習如何使用包含在Caliburn Micro中的”事件聚合器“。事件聚合器是很容易讓你的應用程序的多個部分發送消息給對方的服務。當你的應用程序有很多個view-models(視圖模型)需要溝通,這將非常有用。要做到這一點,需要先向事件聚合器訂閱你的對象(如view-models),並指定他們應該聽什么類型的消息。你也可以定義(接收端)對象當收到這樣的消息會做些什么。這樣,當應用程序的一端發布的消息,事件聚合器可以確保匹配的訂閱對象接受它,並執行相應的操作。在本教程中,我們將擴展我們以前做的入門示范代碼。 (你可以在這里下載。)
盡管事件聚合器是針對具有多個視圖模型較大的應用程序時會更有用,我們仍會保持我們的教程應用程序的最小化。要注意的是,本教程相比以前的教程,會更加難以消化!在本教程結束時,我們將有一個顯示兩個視圖,每個都有自己的視圖模型的應用程序。
View1視圖,將展示一些單選按鈕,分別代表不同的顏色。當單擊一個單選按鈕,我們將發布消息,包括適當的顏色。
View2視圖,將偵聽這些消息並更改矩形的顏色。
我們將經歷4個步驟:為應用程序添加另一個視圖,實現IHandle<TMessage>接口,為一個ViewModel訂閱事件聚合器,最后另一個ViewModel視圖模型發布事件。
Step 1: Adding Another View and View-Model(添加一個新的視圖和視圖模型)
為了說明該事件聚合器,我們的應用中需要至少2個視圖模型。我們已經有一個(AppViewModel),所以我們需要另外添加一個。還記得在入門教程中描述的命名約定?添加一個新類叫ColorViewModel,和一個名為ColorView用戶控件。我們也改變了ColorView的背景,使我們至少能看到點兒東西,當我們第一次將它添加到應用程序。在visual structure(視覺結構)方面,我們會獲取現有AppView以包含新ColorView。 (View視圖要使用事件聚合器並不需要進行嵌套)。一個ViewModel可以收聽從任何地方被發表在應用程序的消息)要做到這一點,AppViewModel需要類型ColorViewModel,我們設定的屬性構造函數是這樣的:
public class AppViewModel : PropertyChangedBase { public AppViewModel(ColorViewModel colorModel) { ColorModel = colorModel; } public ColorViewModel ColorModel { get; private set; } }
在AppView.xaml中,我們將Grid網格分割成2列,第一列中的顯示ColorModelView。 AppView.xaml現在看起來像這樣:
<Grid Width="300" Height="300" Background="LightBlue"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <ContentControl Name="ColorModel" Margin="10" /> </Grid>
這里的ContentControl的名稱是和我們剛剛添加到AppViewModel的名字一樣的。由此看來Caliburn Micro會很友好的為我們將ContentControl的Content屬性綁定到ColorModel屬性的。當我們運行這個了以后,Caliburn Micro將確保顯示ColorView的實例為ColorViewModel。
如果我們現在運行了該應用程序,我們會遇到一個異常說:AppViewModel的默認構造函數未發現。嗯,這是一個要點:我們已在AppViewModel的構造函數中指定了它需要一個參數 - 一個ColorViewModel對象。要解決這個問題,我們需要如下圖所示,更新我們的AppBootstrapper。 (請務必包括添加System.ComponentModel.Composition.dll到項目中。)
using Caliburn.Micro; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using System.ComponentModel.Composition.Primitives; public class AppBootstrapper : Bootstrapper<AppViewModel> { private CompositionContainer container; protected override void Configure() { container = new CompositionContainer(new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>())); CompositionBatch batch = new CompositionBatch(); batch.AddExportedValue<IWindowManager>(new WindowManager()); batch.AddExportedValue<IEventAggregator>(new EventAggregator()); batch.AddExportedValue(container); container.Compose(batch); } protected override object GetInstance(Type serviceType, string key) { string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key; var exports = container.GetExportedValues<object>(contract); if (exports.Count() > 0) { return exports.First(); } throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract)); } }
和下載Caliburn Micro時附帶的示例中使用的bootstrapper很相似。為了不使這個博客帖子太長了,我也不會深入介紹的這段代碼是干什么的(如果你需要更多的細節,可以搜索MEF或Managed Extensibility Framework)。
接下來,我們需要給我們的兩個ViewModel類的屬性,添加”Export“(輸出)特性。這將用於AppBootstrapper中的GetInstance( )方法。
[Export(typeof(AppViewModel))] public class AppViewModel : PropertyChangedBase { } [Export(typeof(ColorViewModel))] public class ColorViewModel { }
最后,在AppViewModel的構造函數前,加入”ImportingConstructor“特性。這是為了表明,該構造函數應該被使用,因為沒有默認的構造函數。當Caliburn Micro創建AppViewModel時,它也將為我們創造ColorViewModel的實例傳遞到構造器。
[ImportingConstructor] public AppViewModel(ColorViewModel colorModel) { ColorModel = colorModel; }
現在,我們可以運行應用程序,看到成功顯示在AppView內的ColorView:
讓我們添加一個矩形到第二列。當傳遞了改變顏色的消息,這個矩形會改變顏色,所以它的顏色會在AppViewModel中對應一個屬性:
加入一個矩形:
<Rectangle Grid.Column="1" Width="100" Height="100" Fill="{Binding Color}" />
矩形對應的屬性:
private SolidColorBrush _Color; public SolidColorBrush Color { get { return _Color; } set { _Color = value; NotifyOfPropertyChange(() => Color); } }
Step 2: Implementing the IHandle<TMessage> Interface(實現IHandle<TMessage>接口)
我們將要在ColorViewModel發布消息,在AppViewModel中捕獲消息。要做到這一點,我們將需要一個能容納信息的類。這個類通常是非常小的和簡單的。它主要是需要有一些屬性,來容納我們要發送的任何信息。下面是我們將要使用的消息類:
public class ColorEvent { public ColorEvent(SolidColorBrush color) { Color = color; } public SolidColorBrush Color { get; private set; } }
為了讓AppViewModel來處理相應的事件,它需要實現IHandle<TMessage>接口。在我們的例子中,我們將使用ColorEvent作為它的泛型類型。該IHandle接口有一個”Handle“方法需要我們去實現。在我們的AppViewModel的Handle方法中,我們將處理發送來的ColorEvent中的SolidColorBrush,並用它來設置Color屬性。這將輪流改變矩形的視圖中的顏色:
public void Handle(ColorEvent message) { Color = message.Color; }
Step 3: Subscribe(訂閱)
現在,我們需要向事件聚合器訂閱AppViewModel,以讓它可以真正偵聽發布的消息。為此,我們需要給AppViewModel的構造函數增加另一個參數”IEventAggregator“。當一個AppViewModel建立時,Caliburn Micro就會傳遞給我們的引導程序設定的事件聚合器。現在,在構造函數中,我們簡單地調用像這樣的訂閱方法:
[ImportingConstructor] public AppViewModel(ColorViewModel colorModel, IEventAggregator events) { ColorModel = colorModel; events.Subscribe(this); }
Step 4: Publish(發布)
ColorViewModel也需要事件聚合器,以便它可以發布消息。添加一個構造函數,它需要一個IEventAggregator參數,並將其存儲在一個字段中。請記住,還要包括ImportingConstructor特性:
private readonly IEventAggregator _events; [ImportingConstructor] public ColorViewModel(IEventAggregator events) { _events = events; }
現在我們只需要在ColorView中添加單選按鈕,傾聽他們的click事件,然后發出消息。你可能還記得在本系列的第二篇教程關於快速的方式來傾聽click事件。簡單地設置RadioButton單選的名稱,和我們想要要調用的方法簽名相同。我們當然可以使用事件參數,而不必為每個單選按鈕創建操作方法,但這里我簡單清楚的做出來,這樣你就可以清楚地看到發生了什么:
<RadioButton Name="Red" Content="Red" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" /> <RadioButton Name="Green" Content="Green" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="1" /> <RadioButton Name="Blue" Content="Blue" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="2" />
public void Red() { _events.Publish(new ColorEvent(new SolidColorBrush(Colors.Red))); } public void Green() { _events.Publish(new ColorEvent(new SolidColorBrush(Colors.Green))); } public void Blue() { _events.Publish(new ColorEvent(new SolidColorBrush(Colors.Blue))); }
就是這樣。現在運行應用程序並點擊單選按鈕。看到AppViewModel成功獲得從ColorViewModel傳遞出的messgaes,改變矩形的顏色。
有一點要注意的是,我一直在身邊掠過SolidColorBrushes在消息設置矩形的顏色。一般來說,你會通過各地的原始值,然后使用轉換器在UI解釋價值對SolidColorBrush等。
完整版Visual Studio 2010項目在本教程中也可以從這里下載。我希望你找到的事件聚合器有用編排在應用程序跨不同的視圖模式通信。退房機制的文檔獲取更多信息,包括如何做到多態事件訂閱,定制出版封送處理,並從事件聚合退訂。
有一點要注意的是,我一直傳遞的是SolidColorBrushes消息,用來設置矩形的顏色。一般來說,你要傳遞更多基元值,然后使用UI里面的converter(轉換器)對SolidColorBrush解釋值。
-----以下為其他內容,和本節教程關系不大,就不自己翻譯修改了,請大體看看,如果需要請跳轉到原文:
完整版Visual Studio 2010項目在本教程中也可以從這里下載。我希望你找到的事件聚合器有用編排在應用程序跨不同的視圖模式通信。退房機制的文檔獲取更多信息,包括如何做到多態事件訂閱,定制出版封送處理,並從事件聚合退訂。