UE3的数据绑定笔记
http://blog.csdn.net/noslopforever/article/details/7413283
这篇文章介绍了一下WPF的数据绑定,这是一种做法。
回顾一下,数据绑定主要的几个组成部分:
源数据池和源属性。
目标数据池和目标属性。
Binding:配置哪些源的改变,会使得哪些目标发生改变。
前面也大概介绍了数据绑定基本需要解决的工作:
源数据必须发布通知,这个通知应该由Binding来获取。
Binding获取到通知后,根据配置,决定哪些目标属性将要发生更改,并修改目标属性。
不同的实现,注意的主要问题,源数据和目标数据是一般没有什么问题的,最多就是Collection如何处理,这个没有任何麻烦应该。
接下来的主要的麻烦应该是在Binding该放到哪儿。有侵入式和非侵入式两种,侵入式的话,就是绑定融合在界面库本身来做,要求重写一套自己的界面库。非侵入式则可以允许在第三方库的基础上来开发。侵入式有侵入式的优势,非侵入式有非侵入式的优势,这就需要根据情况来灵活选择了。
WPF的实现基本上可以理解为侵入式的,如果一个模块本身是这么做的,最大的好处就是可以把绑定的复杂度降到最低,对使用者而言很简单,同时绑定本身可以跟UI树很好的整合到一起,对于Relative等的描述的处理会变的非常简单,也更加灵活。非侵入式则可能对于开发者更容易理解,但是对使用者的要求相对来说就高一些,因为使用者必须更加明白绑定的概念和意义,同时非侵入式一般都会面临着源既可以是某个UI元素,也可以不是,这样绑定一般来说必须实现多套。但两者除了这些细枝末节的之外,基本上概念上还是统一的。
言归正传,我们来看UE3的数据绑定做法:
UE3的数据绑定实现了两份,GFX融合进来前有一部分,GFX融合进来后又不一样了。之前的那个本来还想提一下,不过实在是有点麻烦,GFX融合进来后改动的简单很多,也很方便理解,是一个非常标准的非侵入式的做法,所以就顺着这个思路说下去好了。
基本上UE3的数据绑定就是按照后面这个提炼出来的公式来做的,这应该也是最简单不过的数据绑定了。
1 IDataStore负责捕获数据的更改,并将其发送到Subscriber。
2 所有的Binding都记录在某个UI系统中,一个UI系统包含一到多个页面,这些页面由第三方UI库来提供,UI System负责这些UI库的一些维护和逻辑工作。
3 UI系统实现了一个Subscriber,监听数据更改,一旦数据更改,Subscriber将根据修改了谁来决定触发哪些个Binding来修改目标。
4 Binding里记录了目标元素的路径,接收到修改指令后,真正地向目标flash元素设置新值。
很简单的实现。其实跟的深了,有很多外延的处理,不过大体的思路和原理就是这样的了。
但这样的更改只能发生在Data Store和UI 元素之间,像WPF那样,元素与元素间呢?
还有一个WidgetBindings来处理这个功能,这个跟前面的没有太大的不同,一个Binding,两种实现,就不展开了,有兴趣自己看看就行了。
UE3这种实现方式的几个特点:
非侵入式地与第三方库进行交互(Gfx)。
需要在这些第三方库外面包装一个“UI系统”这样的东西,用它来管理所有的绑定。
第三方库本身的绑定,也是基本上非侵入式的进行修改。
这样,即便不再使用Gfx,换做CEGUI,这套系统稍微修改就能投入新的界面库中。甚至可能连Binding的数据本身也不需要大的修改,做一个版本兼容就可以直接用到新的体系里面。
首先,任何一个界面库肯定都有设置某个UI元素的方法,从Data Store到UI元素这条路是绝对没有任何问题的。唯一有麻烦的是从UI界面库回到Data Store,以及UI界面库元素之间的绑定。只要界面库敢给Value改变的通知、那么后面这个就也不是任何问题。接下来更多的麻烦就在于很多细节问题了:如何使之可编辑,如果第三方库本身提供了编辑器,如何融合Binding的编辑进入这个编辑器等等。
采用这种非侵入式的方式,对于开发者而言,比起WPF容易理解多了。
最后再列举一下数据绑定的几个优势:
1 业务和界面完全分开,使得界面使用多人铺量成为可能。毕竟界面元素之间的逻辑,诸如按了哪个按钮使得页面本身关闭这样的,以及关闭的动画如何播放这样的,占整个UI系统逻辑工作的大部分。而且这部分东西根本就应该是让美术参与的,美术才知道一个UI元素怎么移动是美的,怎么Fade是美的,让程序来弄……绝大多数人实现出来的应该就是Windows3.0风格的界面了——不能怪程序,毕竟程序是一个功能至上的工种,像元素采用2次方曲线还是指数曲线来Fade是美的这样的问题,应该由美学大师们来处理。工种不同,职责不同。
2 绑定使得Style、Template这样的东西变得很方便。界面元素的Background、Foreground均来自不同的绑定,这样很方便就能实现style了。
3 绑定使得不同元素间的通信变得简单,数值的更改可能直接影响到进度条元素,而进度条元素的更改又有可能使得另外一个元素被启用。例如,血量降低了,显示血量数字的Textbox会自动更新、显示血条百分比的Image也会自动更新,如果有心,甚至可以设定在低于30%后,“界面边缘发红”这个界面元素得以开始它的动画。而在MFC里,这个东西要么得手写,要么得求助Doc-View,都显得太麻烦。
4 绑定的编辑,使得开发者不得不把精力花在工具的提供上,而不再是功能完了就了事儿。……好吧,我承认这条是充数的,一个优秀的程序员本身就应该考虑功能之外的那些东西,系统如何使用,如何投放,如何编辑……
不过无论如何,只要有了数据绑定这个思路,根据自己所面对的情况,就可以灵活地运用和安排这些组件,完成自己的目的了。
更重要的是——实现一套这个东西,真的很容易很容易。
后记:
其实之前对UE3绑定的印象多来自于之前旧版的数据绑定系统,GFX融合后一直对新的绑定这块儿的修改没有怎么看,今天一看,算了,旧版的别再写了,新版的又清晰有强大,何苦再自找麻烦呢。
本来还准备再写写自己的那套东西的,还是算了,因为采用的跟GFX这套差不了多少。所想达到的目的也是一样,就是绑定本身与具体的界面库脱离。
见到以及听说现在还有不少项目是通过堆程序员,用类似于MFC和WXWidget那样的方式去完成自己的UI界面,再好一点的无非也就是用代理代替了继承,黑箱代替了白箱,但从根本上没有解决问题。而这样的开发模式实在太累,而且速度太慢,随着游戏竞争压力的增加,传统方式引发的问题实在太多太多。
对于已经可以通过自己完成的编辑器来铺界面量的人们来说,数据绑定的优势也是很明显的:界面的使用者所需关注的只是界面本身的逻辑,一个优秀的界面库直接可以通过编辑器来完成这点。程序员只需要安排好所有的绑定就可以投入到别的工作,界面本身完全可以独立于任何程序员而完成。
真心希望数据绑定能够帮着大家优化自己的界面制作流程。