AnnaTree类是对TreeView控件类的封装,设计这个类的目的是为了扩展treeview的功能,让它形成我想要的一些行为习惯。比如,生成的时候知道到指定表去生成树节点、删节点的时候知道怎么到节点表和节点细节表去删记录等等。
程序员只要在含树窗体的open过程把annatree对象的treeview控件指向该窗体的树控件,该树控件之后的一切举动就都会自动按照annatree里规定的行为规则去行事了。具体的实现机制在这篇文章。
AnnaTrees类是AnnaTree类的集合类。构造这样一个集合类的目的是为了解决多树之间的联动问题,这个问题是由多挂节点引起的。由于有些基础节点挂在多棵树下,所以当一棵树上的节点变动时,其他相关东家的节点也应该做相应变动。我们不妨简称这个问题为多树联动问题。解决多树联动问题的基本思路是:在树的相关事件过程里,树首先处理完自己的业务,然后轮询其他相关的树通知相应的变动。这就需要每个树能访问到所有其他树,这也正是我要维护一个树的集合的原因。
维护树集合不一定非要自己生成一个集合类,可以用系统自带的collection类。我没这么做的原因是希望能够对这个集合类有更多的控制,比如控制它的某些属性的存取、为它添加若干方法和事件等等。
最后,一个困扰我的问题是,如何存放这个树集合变量。这个树集合应该在MDB存在的整个过程中都存活,很显然,它应该是个全局变量,每个带树窗体模块应该都能访问它,从而可以把自己窗体上的树控件添加到它的集合中。而AnnaTree类显然也需要能访问它,因为在解决多树联动问题时,AnnaTree类需要通过它访问到所有其他的AnnaTree。
从功能上说,一个作为全局变量存在的AnnaTrees集合类对象是完全能满足上述要求的;不过,我觉得不爽和不安的是,要在AnnaTree类对象的方法中直接地、频繁地使用位于外部的全局变量。这很不符合OOP的思想。其实,我最希望的框架是,AnnaTrees类对象作为AnnaTree类的一个静态成员对象存在,所有的AnnaTree类共有这么一个AnnaTrees类集合。让人无奈的是,VBA作为VB的子集,不支持类的静态成员(据说,在VB.NET中可以用shared关键字来声明静态成员)。
最后,我想出一个有点笨的办法。就是在每个AnnaTree类的对象中设置一个AnnaTrees类对象指针,它们都指向同一个全局变量。这样,在AnnaTree类的方法中,它们只对自己的成员对象操作,而屏蔽了直接操作外部全局变量的现象。
这样做貌似有点掩耳盗铃,因为实际上还是在操纵全局变量;还有点像画蛇添足,因为多加了一道工序,AnnaTree类还得在它的构建函数中处理它的AnnaTrees类成员对象的初始化工作,析构时也要增加相应的释放资源工作。但是它让我的潜意识安宁了。它维护了OOP自己做自己的事、不干涉别国内政的原则,我猜它会给日后的代码维护和扩展工作带来潜在的好处。不过具体是啥好处,我也一时说不上来……
所以,最后AnnaTree类里有两个对象型的成员变量:
- PrivateWithEventsm_treeAsMSComctlLib.TreeView
- PrivateWithEventsm_treesAsAnnaTrees