对于客户端应用程序而言,单页应用程序(Single Page Application)是最常见的表现形式。有经验的开发人员往往会把一个View分解多个SubView。那么,如何在多个SubView之间 『共享数据』 是一个很棘手的事情。又因为ViewModel才是真正为View提供数据来源,所以本质上『共享数据』指的是多个ViewModel之间共享同一块数据控件。

JavaScript中的原型链

谈到『共享』两字,脑海里跳出第一个印象就是『继承』。对吧,因为你是父母的孩子,所以理所当然你可以和父母共享家中的一切。所以『共享』的前提,就是构建一个『继承链』,也就是JavaScript中的『原型链』。

那么JavaScript是怎样实现原型链呢?有经验的JavaScript程序员想必早就记的滚瓜烂熟了——通过内置属性 __proto__ 来实现。

所以ViewModel之间『共享数据』的核心就是如何去实现一个继承链,如下所示:

为ViewModel构建继承关系

有了上述的分析之后,只要仿照JavaScript的 __proto__ 的实现,我们对所有ViewModel的基类ViewModelBase添加一个ParentViewModel 属性,它代表当前ViewModel的父亲对象。

public class ViewModelBase
{
public ViewModelBase ParentViewModel { get; set; }
//...
}

接着我参考了WPF中是怎样获取父ViewModel当中的数据:

 Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=DataContext.ParentViewModelProperty}

可以看到通过 FindAncestor 方法,去指定 AncestorType 类型的上层对象中获取数据。

所以,我为ViewModelBase 增加一个扩展方法,可以通过继承链实现从指定的祖先对象获取数据。

    public static IEnumerable<T> Ancestors<T>(this ViewModelBase origin) where T : ViewModelBase
{
if (origin==null)
{
yield break;
}
var parentViewModel = origin.ParentViewModel;
while (parentViewModel!=null)
{
var castedViewModel = parentViewModel as T;
if (castedViewModel != null)
{
yield return castedViewModel;
}
parentViewModel = parentViewModel.ParentViewModel;
} }

对应在ViewModel中,可以通过 Ancestors扩展方法获取上层对象的数据

var ancestors = this.Ancestors<FaceBoxViewModel>();

最后,以图示的形式会更加直观,下图所示,SubViewModel依靠继承链可以轻松访问到ParentViewModel的共享数据:

小结

本篇文章介绍了怎样在ViewModel之间共享数据,实际上解决方案是非常简单的,人为的构造了一个继承链并随着继承链往上找,总是能找到希望获取到的数据。类似与JavaScript中的原型链,维护了一种至上而下的父子关系。

源代码托管在Github上,点击此了解

Unity应用架构设计(5)——ViewModel之间如何共享数据的更多相关文章

  1. Unity 3D Framework Designing(5)——ViewModel之间如何共享数据

    对于客户端应用程序而言,单页应用程序(Single Page Application)是最常见的表现形式.有经验的开发人员往往会把一个View分解多个SubView.那么,如何在多个SubView之间 ...

  2. Unity应用架构设计(2)——使用中介者模式解耦ViewModel之间通信

    当你开发一个客户端应用程序的时候,往往一个单页会包含很多子模块,在不同的平台下,这些子模块又被叫成子View(视图),或者子Component(组件).越是复杂的页面,被切割出来的子模块就越多,子模块 ...

  3. Unity应用架构设计(1)—— MVVM 模式的设计和实施(Part 2)

    MVVM回顾 经过上一篇文章的介绍,相信你对MVVM的设计思想有所了解.MVVM的核心思想就是解耦,View与ViewModel应该感受不到彼此的存在. View只关心怎样渲染,而ViewModel只 ...

  4. Unity应用架构设计(10)——绕不开的协程和多线程(Part 2)

    在上一回合谈到,客户端应用程序的所有操作都在主线程上进行,所以一些比较耗时的操作可以在异步线程上去进行,充分利用CPU的性能来达到程序的最佳性能.对于Unity而言,又提供了另外一种『异步』的概念,就 ...

  5. Unity应用架构设计(3)——构建View和ViewModel的生命周期

    对于一个View而言,本质上是一个MonoBehaviour.它本身就具备生命周期这个概念,比如,Awake,Start,Update,OnDestory等.这些是非常好的方法,可以让开发者在各个阶段 ...

  6. Unity应用架构设计(11)——一个网络层的构建

    对于客户端应用程序,免不了和远程服务打交道.设计一个良好的『服务层』能帮我们规范和分离业务代码,提高生产效率.服务层最核心的模块一定是怎样发送请求,虽然Mono提供了很多C#网络请求类,诸如WebCl ...

  7. Unity应用架构设计(1)—— MVVM 模式的设计和实施(Part 1)

    初识 MVVM 谈起 MVVM 设计模式,可能第一映像你会想到 WPF/Sliverlight,他们提供了的数据绑定(Data Binding),命令(Command)等功能,这让 MVVM 模式得到 ...

  8. Unity应用架构设计(13)——日志组件的实施

    对于应用程序而言,日志是非常重要的功能,通过日志,我们可以跟踪应用程序的数据状态,记录Crash的日志可以帮助我们分析应用程序崩溃的原因,我们甚至可以通过日志来进行性能的监控.总之,日志的好处很多,特 ...

  9. Unity应用架构设计(9)——构建统一的 Repository

    谈到 『Repository』 仓储模式,第一映像就是封装了对数据的访问和持久化.Repository 模式的理念核心是定义了一个规范,即接口『Interface』,在这个规范里面定义了访问以及持久化 ...

随机推荐

  1. Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

  2. HDU 3829 Cat VS Dog (最大独立集)【二分图匹配】

    <题目链接> 题目大意: 动物园有n条狗.m头猫.p个小孩,每一个小孩有一个喜欢的动物和讨厌的动物.如今动物园要转移一些动物.假设一个小孩喜欢的动物在,不喜欢的动物不在,他就会happy. ...

  3. java接口签名(Signature)实现方案

    预祝大家国庆节快乐,赶快迎接美丽而快乐的假期吧!!! 一.前言 在为第三方系统提供接口的时候,肯定要考虑接口数据的安全问题,比如数据是否被篡改,数据是否已经过时,数据是否可以重复提交等问题.其中我认为 ...

  4. 项目部署相关命令(pm2)

    普通方式启动后台服务: nohup npm start & 关闭服务,需要找到进程号: lsof -i :3000 kill -9 进程号 通过pm2启动项目,可实现关闭自启动: 安装pm2: ...

  5. 在windows上安装redis并设置密码

    在windows上安装redis Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的Web应用程序的完美解决方案. Redis从它的许多竞争继承来的三个主要特点: Redi ...

  6. POJ 1230 Pass-Muraille

    #include<iostream> #include<cstring> using namespace std; ; //(x,y) (x1,y1)墙的两个端点,所有墙最大列 ...

  7. 潭州课堂25班:Ph201805201 爬虫高级 第八课 AP抓包 SCRAPY 的图片处理 (课堂笔记)

    装好模拟器设置代理到 Fiddler  中, 代理 IP 是本机 IP, 端口是 8888, 抓包 APP斗鱼 用 format 设置翻页

  8. servlet模板的修改

    找到myeclipse的安装目录: 找到此目录下的这个jar包 右键以压缩包的方式打开然后找到templates文件夹并打开它: 在打开的templates文件夹找到并以高级记事本打开Servlet. ...

  9. UE4入门(二)建立和打开项目

    1.双击电脑桌面上的Unreal Engine 2.见下图 建立c++或者蓝图项目: 蓝图是什么? 蓝图种类: 接口:

  10. input的一些使用方法