界面设计模式 之 我的Tree-Client模式
界面设计模式 之 我的Tree-Client模式
平时在用C#做界面的时候,尤其是在做参数设置界面的时候,经常会遇到左边是树,右边根据树节点对应的数据类型显示不同的内容。VS2003的选项设置界面就是这种布局。那么我们自己来实现的时候,如何设计才比较好呢?
先看一下我的界面示意图:
这里我们可以看到有如下几个我们需要关注的对象:
节点(TreeNode):其中包含了我们最核心的数据,只有根据其中的数据我们才能选择我们需要的显示界面
界面容器(Site):我们的各种界面都要最终显示在这么小块显示区域里边。也许进一步分析可能会有更多的东西。
界面(Editor):随着不同数据的变化而变化。
首先可以确定的是节点中必须要包含我们想要的数据,我们设想的工作场景是这样的:在运行时,根据节点中数据的类型,我们选择不同的界面,然后把这些界面加入到界面容器中显示出来,然后把我们的数据塞到这些界面里,等我们编辑完了这些数据之后,再把数据放回到节点中去。
在这个工作场景中,接口之间的依赖性要求如下:
1。TreeNode不应该知道具体Editor的类型,因为不同的场合,同一个数据也会有不同种类的编辑方法。
2。Editor眼中只有数据,不会知道TreeNode的存在,因为同一个Editor可能要工作在多种场合之下。
3。Editor也不应该知道 Site 的存在,否则Editor就无法独立工作,复用性就达不到要求。
4。Site绝对知道Editor的存在,但是也不应该知道 TreeNode 存在,原因同2。
5。TreeNode 不应该知道 Site 的存在。
6。TreeView和MainWindow当然会知道Site的存在了,因为他们就在一个界面里边嘛,假装不知道也太过分了。
这样一来,我们差不多就可以出一个图了,如下:
解释一下,图上所示的内容其实是让 TreeView和MainWindow作为粘合剂,把TreeNode、Editor和Site三个类粘合在了一起。这三个类分别通过IEditor和IEditorNotify进行相互之间的通讯。其中各自的职责如下:
TreeNode:通过实现IEditorNotify接口来获取 Editor 的必要通知,包括Open/Close/Save等。另外实现Data属性,让TreeNode和数据的绑定松动,以便TreeView和MainWindow的操作。
Editor:通过实现 IEditor 接口来配合 IEditorNotify 的通知工作,让IEditorNotify的实现者可以获取必要的数据和编辑信息。
Site:通过预先定义“数据类型 到 Editor”的映射来实现界面的选择功能。而且作为Editor的容器,Site自己管理所有的Editor实例。只通过一个简单的SetData来完成 数据、IEditor和IEditorNotify 之间的关联。
TreeView和MainWindow:两者配合实现事件和逻辑的粘合,把 TreeNode 包含的数据和IEditorNotify接口传递给Site的SetData接口。
从最后的实现代码来看,代码的分布非常均匀,至少我自己很满意。
实际的代码在这里下载。
公众号:老翅寒暑