对于客户端应用程序而言,单页应用程序(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 3D Framework Designing(5)——ViewModel之间如何共享数据的更多相关文章

  1. Unity应用架构设计(5)——ViewModel之间如何共享数据

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

  2. Unity 3D Framework Designing(3)——构建View和ViewModel的生命周期

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

  3. Unity 3D Framework Designing(2)——使用中介者模式解耦ViewModel之间通信

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

  4. Unity 3D Framework Designing(1)—— MVVM 模式的设计和实施(Part 2)

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

  5. Unity 3D Framework Designing(1)—— MVVM 模式的设计和实施(Part 1)

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

  6. Unity 3D Framework Designing(4)——设计可复用的SubView和SubViewModel(Part 1)

    『可复用』这个词相信大家都熟悉,通过『可复用』的组件,可以大大提高软件开发效率. 值得注意的事,当我们设计一个可复用的面向对象组件时,需要保证其独立性,也就是我们熟知的『高内聚,低耦合』原则. 组件化 ...

  7. Unity 3D Framework Designing(6)——设计动态数据集合ObservableList

    什么是 『动态数据集合』 ?简而言之,就是当集合添加.删除项目或者重置时,能提供一种通知机制,告诉UI动态更新界面.有经验的程序员脑海里迸出的第一个词就是 ObservableCollection.没 ...

  8. Unity 3D Framework Designing(7)——IoC工厂理念先行

    一谈到 『IoC』,有经验的程序员马上会联想到控制反转,将创建对象的责任反转给工厂.IoC是依赖注入 『DI』 的核心,大名鼎鼎的Spring框架就是一个非常卓越的的控制反转.依赖注入框架.遗憾的是, ...

  9. Unity 3D Framework Designing(9)——构建统一的 Repository

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

随机推荐

  1. 理解volatile

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  2. sessionstorage,localstorage和cookie之间的区别以及各自的用法

    由于年前辞了自己的工作,年后又开始重新找工作,参加了好几次面试,居然都遇到了同样的面试题:sessionstorage,localstorage和cookie之间的是区别? 当然,在面试的时候答的也不 ...

  3. GitHub 上下载代码运行报错 :'The sandbox is not sync with the Podfile.lock\'

    问题描述: github下载的Demo,很多时候使用到CocoaPods,有的时候因为依赖关系或者版本问题不能编译运行.出现例如The sandbox is not sync with the Pod ...

  4. Java IO流学习总结八:Commons IO 2.5-IOUtils

    Java IO流学习总结八:Commons IO 2.5-IOUtils 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/550519 ...

  5. Javascript—①你好,世界!

    新手Perfect教程之Javascript教程①-你好,世界! 前言:不知道Javascript是什么东东的自行度娘或google一下 Javascript在html<head>和< ...

  6. Mybatis实战之TypeHandler高级进阶

    上篇文章分享了在项目实战中自定义Mybatis的TypeHandler来处理枚举类型.文章结尾也指出了美中不足之处,那就是每次都需要指定我们自定义的枚举TypeHandler. 随着项目枚举类型的增多 ...

  7. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  8. Spring-mvc介绍

    Spring-mvc介绍 1.1市面上流行的框架 Struts2(比较多) Springmvc(比较多而且属于上升的趋势) Struts1(即将被淘汰) 其他 1.2   spring-mvc结构 1 ...

  9. iOS 用Swipe手势和动画实现循环播放图片

    主要想法 添加3个ImageView展示图片,实现图片的无限循环. 使用Swipe手势识别用户向右或向左滑动图片. 使用CATransition给ImageView.layer添加动画,展示图片更换的 ...

  10. Lightbox 图片展示插件

    html <a href="<?php echo RESOURCES_BASE_FOLDER;?>image/default_pic.jpg" target=&q ...