基于数据库动态生成树形目录

一、 目录树的广泛应用
为了这段内容,在百度上搜了搜,内容一大通,相关的竟没有。搜什么搜嘛?用处不是明摆着吗?资源管理器文件夹的管理,论坛中多级论坛的管理,JAVA中的AWT正是缺乏包括树形目录这样的组件才用处受限......谁这么没礼貌,一点面子都不给,叫我怎么讲下去?清了清嗓子:

在我们项目中常常会出现自关联的数据表,从整体看去,整个表就呈现为一个树形数据结构。当我们对这个表进行显示、编辑时,如果不采用好的表现形式,会显得很笨拙,采用树形目录进行管理显然是一个不错的主意。

(斧子抡了一圈,感觉好极了,接着讲...)在WEB中树形目录可以用Javascript实现,但一些细节问题上例如树形目录传值(点击一个子节点,打开相关链接),多级目录以及节点的增加、删除、拖动上受各种制肘。其实采用第三方控件显然也是个不错的主意。

二、 关于智岛目录树控件

好,我们今天的主人公--轻便犀利的智岛目录树控件(下载地址:http://www.oapro.com/ostarocx/download/OTree.ocx)出场了。它采用VC++6.0开发,是标准的OCX控件,可以应用于Windows环境下VB、VC、PB、Dephi、ASP、JSP等编程语言中。它采用XML文件作为接口文件,该接口文件既可以是一个现成的文件,也可以是动态生成的XML格式文件(换句话说可以基于数据库动态生成目录树节点)。智岛目录树控件支持节点的复制、移动、重命名以及权限控件,并且没有对目录的层数进行限制。介绍了这么多,想必欲欲越试了。在ASP中小试牛刀先:

三、 注册添加控件

1. 注册智岛目录树控件

下载(下载地址:http://www.oapro.com/ostarocx/download/OTree.ocx)智岛目录树控件(其文件名为OTree.ocx)后,按照如下方法注册控件:

点击“开始”→“运行”;在运行对话框中输入以下命令:
regsvr32 < OTree.ocx文件的绝对路径>  注册智岛目录树控件控件
regsvr32 /u < OTree.ocx文件的绝对路径> 解除智岛目录树控件的注册

2. 在页面中添加智岛目录树控件

在页面中加入以下代码,即可插入智岛目录树控件:

<object classid="clsid:D835ED15-0BD0-4F24-AC76-A60175AE1137" id="OTree" width="150" height="0"
CODEBASE="http://www.oapro.com/ostarocx/download/OTree.ocx">
<param name="_Version" value="65536">
<param name="_ExtentX" value="2646">
<param name="_ExtentY" value="1323">
<param name="_StockProps" value="0">
</object>

其中:
width和height:指控件的显示宽度和高度;
id:指控件对象的名称,通过该名称实现对控件的操作;
CODEBASE:指没有安装智岛目录树控件的客户端运行该页面时自动下载安装该控件的地址。

三、 从XML文件生成树形目录

1. XML文档格式

XML是个好东东,不过也要符合一定的格式呀,不然控件可不认哦!下面是一份XML文档格式:

<?xml version="1.0" encoding="GB2312"?>
<NaviTree>
<NodeItem>
<NodeName> </NodeName><!--节点名称-->
<NodeType> </NodeType><!--节点类型-->
<NodeData> </NodeData><!--节点数据-->
<ImageIndex> </ImageIndex><!--节点图片-->
<Creator> </Creator><!--生成者-->
<RightDepartmen>|开发部|</RightDepartmen><!--对此目录有权的部门-->
<RightUser> </RightUser><!--对此目录有权的用户-->
<Lock> </Lock><!--是否锁定0/1-->
</NodeItem>
...
</NaviTree>

其中:
NodeName:指节点名称,如有上级节点,要包括上级节点名称,节点名称间以符号"\"分隔。例“我的办公桌\公告通知\电子邮件”表明根节点为“我的办公桌”,父节点为“公告通知”,本节点为“电子邮件”。如果问你包含五级的节点名称是怎样时,呵呵,不要拿西红柿扔我!
NodeType:节点类型,一般均指“href”。
ImageIndex:节点名称前显示的小图标,其中0表示文件夹状图标,4表示数据表状图标。

下面是一份xml格式文档源码:

<?xml version="1.0" encoding="GB2312"?>
<NaviTree>
<NodeItem>
<NodeName>我的办公桌</NodeName><!--节点名称-->
<NodeType>href</NodeType><!--节点类型-->
<NodeData>MyDesk.aps</NodeData><!--节点数据-->
<Lock>0</Lock><!--是否锁定0/1-->
<ImageIndex>0</ImageIndex>
</NodeItem>
<NodeItem>
<NodeName>我的办公桌\公告通知</NodeName><!--节点名称-->
<NodeType>href</NodeType><!--节点类型-->
<NodeData>公告通知.aps</NodeData><!--节点数据-->
<Lock>0</Lock><!--是否锁定0/1-->
<ImageIndex>0</ImageIndex>
</NodeItem>
<NodeItem>
<NodeName>我的办公桌\公告通知\电子邮件</NodeName><!--节点名称-->
<ImageIndex>0</ImageIndex>
</NodeItem>
<NodeItem>
<NodeName>我的办公桌\公告通知\电子邮件\收件箱</NodeName><!--节点名称-->
<ImageIndex>4</ImageIndex>
</NodeItem>
<NodeItem>
<NodeName>我的办公桌\公告通知\电子邮件\发件箱</NodeName><!--节点名称-->
<ImageIndex>4</ImageIndex>
</NodeItem>
<NodeItem>
<NodeName>我的办公桌\公告通知\电子邮件\已发邮件</NodeName><!--节点名称-->
</NodeItem>
<NodeItem>
<NodeName>我的办公桌\日程安排</NodeName><!--节点名称-->
<ImageIndex>0</ImageIndex>
</NodeItem>
<NodeItem>
<NodeName>我的办公桌\日程安排\日历</NodeName><!--节点名称-->
</NodeItem>
</NaviTree>

2. 代码实现

通过以下语句通知智岛目录树控件打开XML文档:

OTree.OpenXMLFile("")

其中引号内XML文档的绝对路径,例如:
OTree.OpenXMLFile("C:\OTree.xml")

运行效果见下图:



已看见你频频点头的样子,但又喃喃自语:如果要根据数据库中内容生成树形目录该...?呵呵,下面我们就进入正题(敢情前面这么多文字是骗稿费的啊?谁?嘘...,小声点,千万别让小编听见):

四、 基于数据库生成树形目录

1. XML文档格式

将树形目录的节点存入数据库,为我们动态形成树形目录打下良好的基础。当然,也有些目录树是表现一个数据库中的数据结构(父节点是数据库名,子节点是数据表)。不管如何,有了前面的基础,现在我们所需做的只是将数据库的内容形成上面格式的XML文档。下面有一份ASP源码,将数据库中结构形成XML文档,其中变量datasource存储传递过来的数据库名称。

<?xml version="1.0" encoding="GB2312"?>
<NaviTree>
<%
dim datasource
datasource=request("datasource")
%>
<NodeItem>
<NodeName><%=datasource%>
<NodeType></NodeType>
<NodeData></NodeData>
<ImageIndex>0</ImageIndex>
<Creator></Creator>
<RightDepartmen>|开发部|市场部|</RightDepartmen>
<RightUser></RightUser>
<Lock>0</Lock>
</NodeItem>
<%
strConn="DBQ="+server.mappath("db\"&datasource)+";DefaultDir=;DRIVER={Microsoft Access Driver (*.mdb)};"
set objConn=server.createobject("Adodb.connection")
objConn.open strConn
set rsSchema=objConn.openSchema(20)
rsSchema.movefirst
Do Until rsSchema.EOF
if rsSchema("TABLE_TYPE")="TABLE" then
%>
<NodeItem>
<NodeName><%=datasource%>\<%=rsSchema("Table_Name")%></NodeName>
<NodeType>href</NodeType>
<NodeData><%=rsSchema("Table_Name")%></NodeData>
<ImageIndex>4</ImageIndex>
<Creator></Creator>
<RightDepartmen>|开发部|市场部|</RightDepartmen>
<RightUser></RightUser>
<Lock>0</Lock>
</NodeItem>
<%
end if
rsSchema.movenext
Loop
set objConn=nothing
%>

</NaviTree>

2. 代码实现

这时候的接口方法跟直接打开XML文档的不一样了:

OTree.SetNodeXML(OTree.HttpGet("http://www.oapro.com/ostarocx/sample/Dataman/OTree.asp","datasource=OTree.mdb"))

其中方法HttpGet有二个参数,第一个参数为我们上面介绍的实现数据库转换XML格式的网页地址,一定要为网址格式,不能用相对或绝对路径
(因为目前该方法尚不支持),第二个参数为传递到该文件的参数,这里我们传递的是数据库名称。

按照上面的介绍你很快的实现了一个树形目录,点根节点,展开,点父节点,展开,再点...,咦,怎么没反应?你希望有什么反应?噢,不好意思,差点忘介绍了:

五、 响应节点事件

智岛树形目录控件提供了一个接口方法用以响应节点事件:

EventTreeSelchanged(strItemName, strItemData,strItemType)

其中:
strItemName 节点名称
strItemData 节点数据
strItemType 节点类型
这三个参数由智岛树形目录控件提供给我们开发者,供我们调用。

我们可通过脚本实现对事件的触发,以下是一范例代码:

<SCRIPT FOR="OTree" EVENT="EventTreeSelchanged(strItemName, strItemData, strItemType)" LANGUAGE="JavaScript" >
alert(strItemName);
</SCRIPT>

以上代码实现了点击节点时,弹出一对话框显示该节点的名称。

六、 范例

嗯,好累呀!用敲键盘敲得差点变形的小手揉揉看屏幕看得发酸的大眼睛,又闪过一个念头,再给出一个范例吧:http://www.oapro.com/ostarocx/sample/ogrid_f 。在这个范例中,从下拉框中选择数据库名称后树形目录的内容会发生变化,点击节点会显示该节点所代表的数据表中的数据内容。整个范例充分展示了上面文章内容的技术细节。下面是范例截图: