在Windows应用程序开发中,经常需要使用树形视图控件来展示层次化的数据。然而,依赖于外部控件如MSCOMCTL.OCX可能会导致应用程序在控件更新后出现问题。为了避免这种情况,本文将介绍如何使用Access的表、表单和代码来构建一个原生的树形视图控件。
最近一次控件出现问题后,意识到最好的解决方案是编写自己的树形视图控件。此外,这里有一个非常好的解决方案可以修复这个问题。
这个控件是由一个Access表单和一个底层的本地表构建的。控件的设计允许用户通过点击复选框或使用箭头键来打开、关闭或移动树中的焦点。右侧的数字表示每个节点的子节点数量,这是可选的。
在创建Access数据库后,将Northwind Traders数据库的一些表纳入其中。数据模型如下所示:
以'z'开头的表意味着它们是本地的,通常,它们的内容是临时的。以'hqry'开头的查询意味着这通常是一个隐藏的查询。使用带有后缀数字的查询名称是为了在大型系统中将相关功能按使用顺序分组,这样就不会在尝试想出有意义的名称时迷失方向。
节点的级别意味着它在X轴上的逻辑位置。在树形视图的截图中,零级节点是客户的名字,一级节点是订单日期,二级节点是在一级日期上订购的产品。
当表单加载时,OnOpen事件触发并加载底层表;选择后,它看起来像这样:
这是一个自引用表。总是避免任何不在正规形式中的数据模型,但在这种情况下,将所有内容放在一个表中更容易显示、管理和调试。
NodeKey字段有两个功能,首先是主键,其次,因为它是文本字段,它也充当排序键。在大多数情况下,将使用相关表的主键来创建复合节点键。
NodeSelected是树形视图左侧的复选框,允许用户选择多个节点,然后采取一些集体行动。
NodeCaption是树形视图中可见的主要字段。注意,它包含指示节点是关闭还是展开的Unicode字符。还要注意用于标记每个树级别的缩进。
IsExpanded指示节点是关闭还是展开。IsGroup指示该节点是否有子节点。ChildrenCount显示该父节点的子节点数量。
树形视图表单是一个简单的Access表单,设置为连续表单模式。可以看到节点键文本框字段在标签后面,标签为用户提供了一些指示。在右侧,可以看到IsGroup复选框。IsGroup和节点键控件在表单显示时是隐藏的。节点标题和子计数文本框设置了条件格式以突出显示。当表单加载时,使用一组查询和一个Unicode字符来显示关闭符号。
Unicode符号声明为字符串,并实例化为:
Private mstrRightArrow As String
Private mstrDownArrow As String…
mstrRightArrow = ChrW(&H25BA)
mstrDownArrow = ChrW(&H25BC)
因为字符是Unicode的,所以不得不使用ChrW函数;这防止将其声明为常量。
当用户在每行的文本区域点击时,会触发鼠标按下事件。这个事件的代码是改变树的外观的主要交换板。
挑战在于确定用户想要展开或折叠节点还是只想选择它。
鼠标按下事件识别点击在X轴上的位置。这告诉哪个子树级别正在发出事件。一旦知道点击发生在Unicode符号上,IsGroup和IsExpanded值提供了接下来会发生什么的线索。
展开节点子程序使用一组查询来替换Unicode符号,然后根据节点级别添加记录。首先,确定有多少级别,然后设置适当的查询。
当用户点击展开的节点符号时,程序会识别这一点,删除子节点并更改符号。这就是使用一个好的主键发挥作用的地方,这样就可以删除子节点但保留父节点在表中。
通过点击节点,会看到,在主Access屏幕的左下角,选中行的标题。这是由节点标题的点击事件驱动的,也是VBA代码中会采取其他适当行动的地方。
这种设计有两个缺点,首先,不能将光标从I-Beam更改为箭头,因为它会经过Unicode字符;其次,没有拖放功能。
当使用一组具有自然主键的表时,可能会遇到排序顺序问题,因为节点键中留有空白。发现在这种情况下创建节点需要使用Replace函数来消除空格,然后一切都会以正确的排序顺序出现。
没有找到很多尝试创建原生Access树形视图控件的例子,但在2005年,发布了以下内容:
SmartTree:这是由Lauren Quantrell博客发布的,并由Gord Thompson和‘Bri’转换为Access 97数据库。这个解决方案使用命令按钮作为展开和折叠事件的目标区域 - 非常整洁。