Caliburn.Micro 杰的入门教程4,Event Aggregator 事件聚合器

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项目在本教程中也可以从这里下载。我希望你找到的事件聚合器有用编排在应用程序跨不同的视图模式通信。退房机制的文档获取更多信息,包括如何做到多态事件订阅,定制出版封送处理,并从事件聚合退订。

posted @ 2013-12-21 15:59  三台  阅读(6649)  评论(0编辑  收藏  举报