Caliburn Micro Part 4: The Event Aggregator をやってみる。
Mindscape Blog » Blog Archive » Caliburn Micro Part 4: The Event Aggregator manbou404.hatenablog.com
要は、Event Aggregator の使い方。
以下は、前回のソリューションをつかう。
ShellViewとShellViewModelを空にしておく。
Step 1: Adding Another View and View-Model
- AppBootstrapperを、コンテナにMEFを使うように修正する。
参照の追加で、System.ComponentModel.Compositionを追加する。
// <AppBootstrapper.cs> using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using Caliburn.Micro; using System.ComponentModel.Composition.Primitives; namespace Tutorial { public class AppBootstrapper : BootstrapperBase { 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)); } public AppBootstrapper() { Initialize(); } protected override void OnStartup(object sender, StartupEventArgs e) { DisplayRootViewFor<IShell>(); } } }
- ColorViewとColorViewModelを追加する。
<!--ColorView.xaml> <UserControl x:Class="Tutorial.ColorView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid Background="CornflowerBlue"> </Grid> </UserControl>
// <ColorViewModel.cs> using System.ComponentModel.Composition; namespace Tutorial { [Export(typeof(ColorViewModel))] public class ColorViewModel { } }
- ColorViewをShellViewとShellViewModelに追加する。
先ほどのColorViewを、注入してもらいバインドする。
Rectangleの背景色は、ViewのColorにバインドする。
<!--ShellView.xaml> <UserControl x:Class="Tutorial.ShellView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:cal="http://www.caliburnproject.org"> <Grid Width="300" Height="300" Background="LightBlue"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <ContentControl Name="ColorModel" Margin="10" /> <Rectangle Grid.Column="1" Width="100" Height="100" Fill="{Binding Color}" /> </Grid> </UserControl>
// <ShellViewModel.cs> using System.ComponentModel.Composition; using System.Windows.Media; using Caliburn.Micro; namespace Tutorial { [Export(typeof(IShell))] public class ShellViewModel : PropertyChangedBase, IShell { [ImportingConstructor] public ShellViewModel(ColorViewModel colorModel) { ColorModel = colorModel; } public ColorViewModel ColorModel { get; private set; } private SolidColorBrush _Color = new SolidColorBrush(Colors.Black); public SolidColorBrush Color { get { return _Color; } set { _Color = value; NotifyOfPropertyChange(() => Color); } } } }
ここまでで、こんな感じ。
オリジナルと違うところ
- AppBootstrapperのコンストラクタで、Initializeを呼んでいる。
- AppBootstrapperのOnStartupで、DisplayRootViewForを呼んでいる。
- ShellViewModelの_Colorに、初期値:黒を入れている。
Step 2: Implementing the IHandle Interface
- ColorEventクラスを追加する。
// <ColorEvent.cs> using System.Windows.Media; namespace Tutorial { public class ColorEvent { public ColorEvent(SolidColorBrush color) { Color = color; } public SolidColorBrush Color { get; private set; } } }
- ShellViewModelに、購読するためのメソッドを追加
(まだ呼ばれないよ!)
// <ShellViewModel.cs> public void Handle(ColorEvent message) { Color = message.Color; }
Step 3: Subscribe
クラス宣言に、IHandle<>を追加 コンストラクタインジェクションで、IEventAggregator をもらう。
// <ShellViewModel.cs> [Export(typeof(IShell))] public class ShellViewModel : PropertyChangedBase, IShell, IHandle<ColorEvent> { [ImportingConstructor] public ShellViewModel(ColorViewModel colorModel, IEventAggregator events) { ColorModel = colorModel; events.Subscribe(this); } // 以下略
Step 4: Publish
- ColorViewにラジオボタン追加
<Grid Background="CornflowerBlue"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <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" /> </Grid>
// <ColorViewModel.cs> [Export(typeof(ColorViewModel))] public class ColorViewModel { private readonly IEventAggregator _events; [ImportingConstructor] public ColorViewModel(IEventAggregator events) { _events = events; } public void Red() { _events.Publish(new ColorEvent(new SolidColorBrush(Colors.Red)), x => x()); } public void Green() { _events.Publish(new ColorEvent(new SolidColorBrush(Colors.Green)), x => x()); } public void Blue() { _events.Publish(new ColorEvent(new SolidColorBrush(Colors.Blue)), x => x()); } }
こんな感じになった
オリジナルと違うところ
+ ShellViewModelで購読するために、IHandle