上篇博文链接

Prism for WPF初探(构建简单的模块化开发框架)

一、简单介绍: 

 在上一篇博文中初步搭建了Prism框架的各个模块,但那只是搭建了一个空壳,里面的内容基本是空的,在这一篇我将实现各个模块间的通信,在上一篇博文的基础上改的。

      先上效果图:初步介绍下,图中虚线分割为四个模块,每个模块可向另外三个模块发消息。这里还是基于模块化开发CS端程序的思路,模块之间低耦合,如果项目做大,好处自然体现出来了。

  图中的效果已经实现了一个模块朝其他三个模块发送消息。这里我使用的事Prism框架中的PubSubEvent事件,其优点是简单易用,直接Publish和Subscribe即可。

二、基本思路

  项目结构图:

  四个模块间基础和共用的东西我放在Desktop.Infrastructure中。A、B、C、D四个模块都保持对Desktop.Infrastructure的引用,各自间无引用,相互独立,以后需要添加删除模块或者改动既有模块,都不影响其他模块的功能。

1、事件与接口,代码很简单。

接口代码:接口定义空的就行,后面Event需要Publish的Model继承自接口IBaseModel。

namespace Desktop.Infrastucture.Interface
{
public interface IBaseModel
{ }
}

事件代码:自定义事件 SendMessageEvent 继承自Prism框架的PubSubEvent。定义好Event,之后只需要在IEventAggregator的实现中Publish和Subscribe即可。

namespace Desktop.Infrastucture.Event
{
public class SendMessageEvent : PubSubEvent<IBaseModel>
{ }
}

从下图可以看到PubSubEvent的定义,其Subscribe支持过滤。

实现原理中其实是个模块都订阅了同一个事件,所以每个模块发一次消息它本身也会接收到,而第一张的效果图中发送消息的模块本身并没有显示出接收到消息,是因为我在Subscribe的时候将本身发的消息的过滤了。

2、Model的实现。

发送的数据为ModelData,所以ModelData肯定要继承自IBaseModel,由于WPF经常需要实现通功能,也就是必须继承自INotifyPropertyChanged接口(这点是WPF的内容),所以我定义了一个BaseNotificationObject来继承INotifyPropertyChanged和IBaseModel,ModelData继承自BaseNotificationObject。

namespace Desktop.Infrastucture.Model
{
[Export(typeof(ModelData))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ModelData: BaseNotificationObject
{
/// <summary>
/// 模块名称
/// </summary>
private ModuleNameEnum _ModuleName; public ModuleNameEnum ModuleName
{
get { return _ModuleName; }
set { _ModuleName = value;
}
}
/// <summary>
/// 消息内容
/// </summary>
private string _Message; public string Message
{
get { return _Message; }
set { _Message = value;
OnPropertyChanged("Message");
}
} }
}

3、ViewModel的实现。

每个模块的界面都需要ViewModel,所以我把通用的功能抽象出来单独写成一个类BaseViewModel。代码如下:

首先是BaseNotify,通过MEF的构造函数导入来注入IRegionManager 与IEventAggregator 的实现。其子类也就可以直接使用了。

namespace Desktop.Infrastucture.ViewModel
{
public class BaseNotify:BaseNotificationObject
{
public List<SubscriptionToken> SubscriptionTokens = new List<SubscriptionToken>();
public readonly IRegionManager regionManager;
public readonly IEventAggregator eventAggregator;
public BaseNotify()
{ } [ImportingConstructor]
public BaseNotify(IRegionManager regionManager,IEventAggregator eventAggregator)
{
this.regionManager = regionManager;
this.eventAggregator = eventAggregator;
}
}
}

BaseViewModel是所有模块ViewModel的父类。按钮触发的是BtnCommand收到消息后执行的是CallBack,这个CallBack定义成Virtual是为了子类可以重载从而执行自己特定的操作。模块的的View中绑定的数据是Data的Message。

namespace Desktop.Infrastucture.ViewModel
{
public class BaseViewModel:BaseNotify
{
#region 属性、字段、命令
//[Import] private Lazy<ModelData> _Data = new Lazy<ModelData>(); public Lazy<ModelData> Data
{
get { return _Data; }
set { _Data = value; }
} private ICommand _BtnCommand; public ICommand BtnCommand
{
get
{
if (null == _BtnCommand)
{
_BtnCommand = new DelegateCommand<object>((obj) =>
{
eventAggregator.GetEvent<SendMessageEvent>().Publish(Data.Value);
});
}
return _BtnCommand;
}
set { _BtnCommand = value; }
}
#endregion #region 构造
[ImportingConstructor]
public BaseViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) : base(regionManager, eventAggregator)
{
eventAggregator.GetEvent<SendMessageEvent>().Unsubscribe(CallBack);
SubscriptionTokens.Add(eventAggregator.GetEvent<SendMessageEvent>().Subscribe(CallBack, ThreadOption.PublisherThread, false, x =>
{
if (x is ModelData)
{
var modelData = x as ModelData;
if (modelData.ModuleName==Data.Value.ModuleName)
return false;
}
return true;
}));
}
#endregion #region 方法 public virtual void CallBack(IBaseModel obj)
{
if (obj is ModelData)
{
var modelData = obj as ModelData;
Data.Value.Message = "";
Data.Value.Message += "Reciced:" + modelData.Message+"\n";
}
} #endregion
}
}

4、模块的实现。

公共的东西都实现了,最后是模块改怎么来写。每个模块的写法基本一致,这里我以其中一个为例。这些东西简单,不多讲贴代码了。

ModelA的View

<Grid x:Class="ModuleA.View.GridA"
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"
>
<StackPanel>
<TextBox Foreground="Red" FontSize="20" Text="{Binding Data.Value.Message}"></TextBox>
<TextBlock Foreground="Red" FontSize="20" ></TextBlock>
<Button Height="30" Width="90" Background="LightPink" Command="{Binding BtnCommand}">ClickMe</Button>
</StackPanel>
</Grid>
using System.ComponentModel.Composition;
using System.Windows.Controls;
using ModuleA.ViewModel; namespace ModuleA.View
{
/// <summary>
/// GridA.xaml 的交互逻辑
/// </summary>
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export]
public partial class GridA : Grid
{
[Import]
public GridA_ViewModel ViewModel
{
set { this.DataContext = value; }
} public GridA()
{
InitializeComponent();
} }
}
ModelA的ViewModel
using Desktop.Infrastucture.Interface;
using Desktop.Infrastucture.Model;
using Desktop.Infrastucture.ViewModel;
using Prism.Events;
using Prism.Regions;
using System.ComponentModel.Composition; namespace ModuleA.ViewModel
{
[Export(typeof(GridA_ViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class GridA_ViewModel: BaseViewModel
{ //public new Lazy<ModelData> Data = new Lazy<ModelData>(); [ImportingConstructor]
public GridA_ViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) : base(regionManager, eventAggregator)
{
Data.Value.ModuleName = ModuleNameEnum.ModuleA; }
public override void CallBack(IBaseModel obj)
{
base.CallBack(obj); } }
}
ModuleNameEnum中定义的是ModuleA、ModuleB、ModuleC、ModuleD的枚举。Data 的定义用了懒加载,不用也一样的。如果要传更多的内容,定义ModelData就行了
讲的比较简单,代码写的也简单,这里只是作为Prism内置Event的入门,实现简单的模块间通信。真正复杂的架构设计要看个人水平了。

作者水平有限,如有不足之处还请赐教。

源码在这里!!!
												

Prism for WPF再探(基于Prism事件的模块间通信)的更多相关文章

  1. Prism之使用EventAggregation进行模块间通信

    在开发Silverlight程序的时候,经常需要在不同的组件间进行通信.比如点击一个button,可能就需要改变另一个控件的内容.比较直接的办法是使用事件,当然使用MVVM的时候也可以使用comman ...

  2. 【教程】【FLEX】#003 自定义事件、模块间通讯

    本篇笔记,主要阐明 事件是如何创建 和 如何使用自定义事件达到模块之间通讯 的效果. 句子解释: 什么叫做模块之间的通讯呢?? 简单点说,就是两个模块之间可以互相传数据. A模块 可以接收到 B模块的 ...

  3. storage事件 js页面间通信

    1.概述 https://developer.mozilla.org/en-US/docs/Web/Events/storage localStorage 或者sessionStorage存储的数据发 ...

  4. Flex事件机制学习-自定义事件实现类间通信 .

    今天,学习Flex自定义事件,可以使两个类通信,定义一个Main类. public class Main extends Sprite     {            public function ...

  5. Prism 4 文档 ---第9章 松耦合组件之间通信

    当构建一个大而负责的应用程序时,通用的做法时将功能拆分到离散的模块程序集中.将模块之间的静态引用最小化.这使得模块可以被独立的开发,测试,部署和升级,以及它迫使松散耦合的沟通. 当在模块之间通信时,你 ...

  6. 浅谈基于Prism的软件系统的架构设计

    很早就想写这么一篇文章来对近几年使用Prism框架来设计软件来做一次深入的分析了,但直到最近才开始整理,说到软件系统的设计这里面有太多的学问,只有经过大量的探索才能够设计出好的软件产品,就本人的理解, ...

  7. Prism for WPF初探(构建简单的模块化开发框架)

    先简单的介绍一下Prism框架,引用微软官方的解释: Prism provides guidance to help you more easily design and build, flexibl ...

  8. Prism for WPF

    Prism for WPF Prism for WPF初探(构建简单的模块化开发框架)   先简单的介绍一下Prism框架,引用微软官方的解释: Prism provides guidance to ...

  9. Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天、消息模块

    原文:Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天.消息模块 中秋节假期没事继续搞了搞 做了各聊天的模块,需要继续优化 第一步画页面 页面参考https://github.c ...

随机推荐

  1. windows 下更新 npm 和 node

    原文链接 公司的新项目要启动了,需要使用 Angular 4.0,并且使用 webpack 工具进行打包.所以就需要安装 node.node 的安装很简单,在 node 的官网 nodejs.org  ...

  2. CNN网络介绍与实践:王者荣耀英雄图片识别

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者介绍:高成才,腾讯Android开发工程师,2016.4月校招加入腾讯,主要负责企鹅电竞推流SDK.企鹅电竞APP的功能开发和技术优化工作 ...

  3. springMVC+commons-fileupload上传文件大小限制异常

    异常信息: 严重: Servlet.service() for servlet [suibian] in context with path [/SpringMvcDemo3] threw excep ...

  4. Linux磁盘分区(二):删除

    ***********************************************声明************************************************ 原创 ...

  5. Subquery returns more than 1 row

    Subquery returns more than 1 row表示子查询返回了多行数据 例如: select * from table1 where table1.colums=(select co ...

  6. WeChat 隐私政策

    隐私政策 本应用尊重并保护所有使用服务用户的个人隐私权.为了给您提供更准确.更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息.但本应用将以高度的勤勉.审慎义务对待这些信息.除本隐 ...

  7. windows10 使用gitblit搭建git服务器

    今天在win10上使用gitblit搭建git服务器时被坑了下,因为安装的java9出现不兼容问题,果断卸载重装了jdk8.废话不多说直接进入正题吧: 第一章 前言 使用gitblit搭建git se ...

  8. java多线程编程核心技术——第二章

    第一节synchronized同步方法目录 1.1方法内的变量为线程安全的 1.2实例变量非线程安全 1.3多个对象多个锁 1.4synchronized方法与锁对象 1.5脏读 1.6synchro ...

  9. 使用Python提取中文字符

    #功能:国际化测试,用于提取应用设计包中的中文字符,并输出report#解压---筛选---整理路径---提取中文---输出报告 ################################### ...

  10. Python爬虫(十五)_案例:使用bs4的爬虫

    本章将从Python案例讲起:所使用bs4做一个简单的爬虫案例,更多内容请参考:Python学习指南 案例:使用BeautifulSoup的爬虫 我们已腾讯社招页面来做演示:http://hr.ten ...