The event aggregator is a service that makes it easy for multiple parts of your application to send messages to each other.
要做到这一点,你订阅的事件聚合的对象(如视图模型),并指定他们应该听什么类型的消息。
现在做一个Colorviewmodel,在Appviewmodel中实现下列代码
public class Appviewmodel : PropertyChangedBase { public Appviewmodel(Colorviewmodel colorModel) { ColorModel = colorModel; } public Colorviewmodel ColorModel { get; private set; } }
<Grid Width="300" Height="300" Background="LightBlue"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <ContentControl Name="ColorModel" Margin="10" /> </Grid>
Make sure to include a reference to System.ComponentModel.Composition.dll to the application
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)); } }
Next,we need to include an Export attribute on both our view-model classes. This is for the GetInstance method in the AppBootstrapper to work.
[Export(typeof(Appviewmodel))] public class Appviewmodel : PropertyChangedBase { ... } [Export(typeof(Colorviewmodel))] public class Colorviewmodel { }
And finally,include the ImportingConstructor attribute on the Appviewmodel constructor.
This is to indicate that this constructor should be used since there is no default constructor. When Caliburn Micro creates the Appviewmodel,it will also create an instance of the Colorviewmodel to pass into the constructor for us.
[ImportingConstructor] public Appviewmodel(Colorviewmodel colorModel) { ColorModel = colorModel; }
add a Rectangle into the second column
private SolidColorBrush _Color; public SolidColorBrush Color { get { return _Color; } set { _Color = value; NotifyOfPropertyChange(() => Color); } }
<Rectangle Grid.Column="1" Width="100" Height="100" Fill="{Binding Color}" />
第2步:实施IHandle <TMessage>接口
We are going to be publishing messages from the Colorviewmodel to be picked up by the Appviewmodel.
添加一个消息类
public class ColorEvent { public ColorEvent(SolidColorBrush color) { Color = color; } public SolidColorBrush Color { get; private set; } }
In order for the Appviewmodel to handle the appropriate events,it will need to implement the IHandle<TMessage> interface.
Appviewmodel中添加事件
public void Handle(ColorEvent message) { Color = message.Color; }
订阅事件Now we need to subscribe the Appviewmodel to an event aggregator so that it can actually listen to published messages.
[ImportingConstructor] public Appviewmodel(Colorviewmodel colorModel,IEventAggregator events) { ColorModel = colorModel; events.Subscribe(this); }
步骤4:发布
The Colorviewmodel is also going to need the event aggregator so that it can publish messages
private readonly IEventAggregator _events; [ImportingConstructor] public Colorviewmodel(IEventAggregator events) { _events = events; }
ColorView
<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" />
Colorviewmodel
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))); }
http://www.mindscapehq.com/blog/index.php/2012/2/1/caliburn-micro-part-4-the-event-aggregator/
附MEF
1.CompositionContainer
CompositionContainer对象在应用程序中有两种的主要用途。 首先,它跟踪哪些部分可用于组合、它们的依赖项,并且执行可用部分设置的更改组合。其次,它提供了应用程序可以启动组合的方法、获取组合部件的实例,或填充可组合部件的依存关系。
部件可直接用于容器,或通过 Catalog 属性来用于容器。在此 ComposablePartCatalog 中可发现的所有部件都可以供容器来满足导入,还包括直接添加的任何部件。
Compose方法允许实例化的部件添加到现有的容器。 假定组合成功,这些部分会在导入中填充从容器检索的部分,导出将可用于其他部分。标记为可重新组合的导入将注册,以进行重新组合。
SatisfyImportsOnce方法允许在不将部件添加到容器的情况下填充该部件的导入部分。 如果组合成功,将填充该部分的导入,但该部分的导出将不能用于其他部分,并且将不为重新组合注册任何导入。
CompositionContainer对象应始终处于释放状态。 当调用 Dispose 方法时,CompositionContainer 对象也会释放其创建的所有部件。
使用 CompositionContainer(ComposablePartCatalog,Boolean,ExportProvider[]) 构造函数,可以从多个线程访问的CompositionContainer 对象必须由设置为 true 的isThreadSafe 参数构造。 当 isThreadSafe 为 true 时性能会稍微变慢,所以我们建议您在单线程的情况下将此参数设置为false。 默认值为 false。
警告 |
---|
CompositionContainer永远不导入自身,或导入对其引用的部分。 这种引用可能允许不受信任的一部分获得容器中的所有部分的访问权限。 |