-事件聚合IEventAggregator和 Ihandle<T>

 

今天 说一下Caliburn.Micro的IEventAggregator和IHandle<T>分成两篇去讲这一篇写一个简单的例子

看一它的的实现和源码

下一篇用它们做一个多语言的demo

这两个是事件的订阅和广播,很强大,但用的时候要小心发生不必要的冲突。

先看一下它的实现思想

在Caliburn.Micro里EventAggregator要以单例的形式出现这样可以做到对广播做到统一的管理

对象实现IHand<T>接口后通过EventAggregator的subsribe方法把自己加入到Handler集合中这样就能接叫信息

能过EventAggregator.Publish(object obj)方法去发送广播

源码: CaliburnIHandle.rar

先看一下个小demo再去分析它的源码是怎么实现的

效果

      

先写一个消息类,这个类只是做一个IHandle<T>的类型应用没有什么实际意义

    class MyMessage
{
public string Str
{
get;
set;
}
public override string ToString()
{
return Str;
}
}

建一个窗体MainView和一个ViewModel类

<Window x:Class="CaliburnIHandle.MyViews.MyMainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MyMainView" Height="300" Width="300">
<StackPanel>
<TextBox x:Name="StrMessage" Margin="5"/>
<Button x:Name="OpenOneWin" Content="OpenOneWin" Margin="5"/>
<Button Content="Publish" x:Name="Publish" Margin="5"/>
</StackPanel>
</Window>

窗体有一个textBox显示消息。一个button打开窗体一个发布消息
再看一下ViewModel

实现 了两个IHandle<T> 一个是string 类型一个是我们自己定义的MyMessage

MainViewMode发布string类型的广播也接收string类型和MyMessage类型的消息

 [Export(typeof(IShell))]
class MyMainViewModel : PropertyChangedBase, IHandle<string>,IHandle<MyMessage>
{
readonly IEventAggregator _events;
readonly IWindowManager _windowManager;
string strMessage;
public string StrMessage
{
get
{
return strMessage;
}
set
{
strMessage = value;
NotifyOfPropertyChange(() => StrMessage);
}
} [ImportingConstructor]
public MyMainViewModel(IEventAggregator e,IWindowManager win)
{
_events = e;
_events.Subscribe(this);
_windowManager = win;
} public void Handle(string message)
{
StrMessage = message;
}
public void Handle(MyMessage message)
{
StrMessage = message.ToString();
} #region
public void Publish()
{
_events.Publish(StrMessage);
}
#endregion #region 打开窗体
public void OpenOneWin()
{
OneCViewModel _one=new OneCViewModel();
_windowManager.ShowWindow(_one);
}
#endregion

再建一个窗体做接收和广播

它只接收string类型的消息和发布MyMessage类型的消息

<UserControl x:Class="CaliburnIHandle.MyViews.OneCView"
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" Height="300" Width="300">
<StackPanel>
<TextBlock FontSize="13" HorizontalAlignment="Center">1</TextBlock>
<TextBox Margin="5" x:Name="OneMessage"></TextBox>
<Button Margin="5" x:Name="OnePublish" Content="Publish"/>
</StackPanel>
</UserControl>
using Caliburn.Micro;
using CaliburnIHandle.CommonC;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text; namespace CaliburnIHandle.MyViewModels
{
[Export(typeof(OneCViewModel))]
class OneCViewModel : PropertyChangedBase, IHandle<string>
{
readonly IEventAggregator _event;
string oneMessage;
public string OneMessage
{
get
{
return oneMessage;
}
set
{
oneMessage = value;
NotifyOfPropertyChange(() => OneMessage);
}
}
public OneCViewModel()
{
_event = IoC.Get<IEventAggregator>();
_event.Subscribe(this);
} public void OnePublish()
{
_event.Publish(new MyMessage { Str = OneMessage + " One!" });
} public void Handle(string message)
{
OneMessage = message;
}
}
}

这是一个很简单的例子我们看一下Caliburn.Micro源码它是怎么实现的

看一下IHandle<T>接口

  public interface IHandle<TMessage> : IHandle {  //don't use contravariance here
/// <summary>
/// Handles the message.
/// </summary>
/// <param name = "message">The message.</param>
void Handle(TMessage message);
}

IHandle<T>只有一个处理T事件的的方法

EventAggregator类通过

 /// <summary>
/// Subscribes an instance to all events declared through implementations of <see cref = "IHandle{T}" />
/// </summary>
/// <param name = "subscriber">The instance to subscribe for event publication.</param>
public virtual void Subscribe(object subscriber) {
if (subscriber == null) {
throw new ArgumentNullException("subscriber");
}
lock(handlers) {
if (handlers.Any(x => x.Matches(subscriber))) {
return;
} handlers.Add(new Handler(subscriber));
}
}

把订阅的类放到Handlers集合里

再通过Publish发布相应的消息

       /// <summary>
/// Publishes a message.
/// </summary>
/// <param name = "message">The message instance.</param>
/// <remarks>
/// Does not marshall the the publication to any special thread by default.
/// </remarks>
public virtual void Publish(object message) {
if (message == null) {
throw new ArgumentNullException("message");
}
Publish(message, PublicationThreadMarshaller);
} /// <summary>
/// Publishes a message.
/// </summary>
/// <param name = "message">The message instance.</param>
/// <param name = "marshal">Allows the publisher to provide a custom thread marshaller for the message publication.</param>
public virtual void Publish(object message, Action<System.Action> marshal) {
if (message == null){
throw new ArgumentNullException("message");
}
if (marshal == null) {
throw new ArgumentNullException("marshal");
} Handler[] toNotify;
lock (handlers) {
toNotify = handlers.ToArray();
} marshal(() => {
var messageType = message.GetType(); var dead = toNotify
.Where(handler => !handler.Handle(messageType, message))
.ToList(); if(dead.Any()) {
lock(handlers) {
dead.Apply(x => handlers.Remove(x));
}
}
});
}
作者:李鹏

事件聚合IEventAggregator和 Ihandle<T>的更多相关文章

  1. Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T>

    Caliburn.Micro学习笔记目录 今天 说一下Caliburn.Micro的IEventAggregator和IHandle<T>分成两篇去讲这一篇写一个简单的例子 看一它的的实现 ...

  2. Prism的IEventAggregator事件聚合器, 事件订阅发布, ViewModel之间的通讯

    WPF中时常会遇到ViewModel之间的通讯,ViewModel并不知道自己的View,但是一个View发生的更改需要通知另外一个View. 举一个例子,软件界面上有个人信息,打开一个界面更改用户的 ...

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

    Caliburn.Micro 杰的入门教程1(原创翻译)Caliburn.Micro 杰的入门教程2 ,了解Data Binding 和 Events(原创翻译)Caliburn.Micro 杰的入门 ...

  4. 【DDD-Apwork框架】事件总线和事件聚合器

    第一步:事件总线和事件聚合器 [1]事件总线 IEventBus IUnitOfWork.cs using System; using System.Collections.Generic; usin ...

  5. 从PRISM开始学WPF(六)MVVM(三)事件聚合器EventAggregator?

    从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WPF(三)Prism-Region? 从PRISM开始学WPF(四)Prism-Module? ...

  6. C#事件の事件聚合器(二)

    WPF中时常会遇到ViewModel之间的通讯,ViewModel并不知道自己的View,但是一个View发生的更改需要通知另外一个View. 举一个例子,软件界面上有个人信息,打开一个界面更改用户的 ...

  7. C#事件の事件聚合器

    事件聚合器用于集中管理事件的订阅(Subscribe)和处理(Handle),要使用事件聚合器,首先要理解:事件(event)本质上是一个类. 传统的+=和-=不足: 1.管理很麻烦:2.不方便扩展. ...

  8. 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator-更新至Prism7.1

    原文:从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator-更新至Prism7.1 事件聚合器EventAggregator [7.1updated]除了app部分,没 ...

  9. 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator?

    原文:从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator? 从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WP ...

随机推荐

  1. 第1章 单例模式(Single Pattern)

    原文 第1章 单例模式(Single Pattern) 单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点. 一.常用模式: 1 ...

  2. Android简单的聊天室开发(client与server沟通)

    请尊重他人的劳动成果.转载请注明出处:Android开发之简单的聊天室(client与server进行通信) 1. 预备知识:Tcp/IP协议与Socket TCP/IP 是Transmission ...

  3. 各大oj题目分类(转)

    POJ题目分类 | POJ题目分类 | HDU题目分类 | ZOJ题目分类 | SOJ题目分类 | HOJ题目分类 | FOJ题目分类 | 模拟题: POJ1006POJ1008POJ1013POJ1 ...

  4. Java Web整合开发(12) -- JDBC

    JDBC访问数据库的一般步骤: 注册驱动,获取连接,获取Statement,执行SQL并返回结果集,遍历结果集显示数据,释放连接. Connection conn = null; Statement ...

  5. 欧拉计划&#183;Q8

    题目8:找出这个1000位数字中连续13个数字乘积的最大值. 找出下面这个1000位的整数中连续13个数字的最大乘积. 7316717653133062491922511967442657474235 ...

  6. ArcEngine载入中SDE问题栅格数据

    当直接加载矢量数据到IFeatureWorkspace接口可,但是,在装载门格当要传送的数据IRasterWorkspaceEx接口. 效果如下面的,对可以被添加到双击Globe在. watermar ...

  7. The Swift Programming Language-官方教程精译Swift(4)字符串和字符

    String 是一个有序的字符集合,例如 "hello, world", "albatross".Swift 字符串通过 String 类型来表示,也可以表示为 ...

  8. Swift入门教程:基本运算符

    基本运算符 Swift所支持的基本运算符 赋值运算符:= 复合赋值运算符:+=.-= 算数运算符:+.-.*./ 求余运算符:% 自增.自减运算符:++.-- 比较运算符:==.!=.>.< ...

  9. Delta3D 2.8版本号 预习

    http://blog.csdn.net/zhuyingqingfen/article/details/38581453 看到官网今天的更新.发现即将公布的delta3d 2.8 版本号 做了非常大的 ...

  10. mysql更改数据文件夹步骤与错误(ERROR 2002 (HY000))处理方法

    1,关闭mysql服务: service mysqld stop 2,创建新建的文件夹 mkdir -p data 3,把曾经的文件夹转移到新的数据文件夹 mv /var/lib/mysql/ /da ...