请教VB中TreeView控件的节点添加问题,谢谢

ha791228 2004-01-03 10:35:28
我想问一下,我现在在做一个产品树管理系统,是用 VB6.0做的。我是从数据库中做好的表读取数据,然后将其显示在一个TreeView控件中,这个数据库中的表的结构如下所示:(parent是当前节点的父节点的id,child是当前节点的id,child_type是当前节点的类型:1为产品,2为组件,3为零件,index_id是当前节点在数据库中自动生成的)
PARENT CHILD CHILD_TYPE CHILD_NAME INDEX_ID
0 88 1 双输入伺服阀 1
88 89 2 衔铁组件 2
88 91 2 油滤组件 4
89 90 3 弹簧管 3
91 90 3 弹簧管 5
我的问题就是,此表中的第四行与第五行都是同一个零件(其节点id相同,都是90),它属于两个不同的组件,也就是说这两个组件都拥有同一个零件。但是我要读取此表,想把其中的内容显示在一个TreeView控件中,这就用到了TreeView控件的TreeView1.Nodes.Add方法,此方法的完整参数表示形式为Function Add([Relative], [Relationship], [Key], [Text], [Image], [SelectedImage]) As Node,这个方法中最重要的是第三个key参数,在每添加一个节点时,它都不能和前后任何一个节点的key参数重复,这个key代表的是本节点的id,即child字段代表的
id,而且这个key参数的值不能只是数字。但是现在有两个零件的child字段值都是相同的(都是90),所以在使用TreeView1.Nodes.Add方法时,解决的办法是给这两个节点每个的key参数加一个字母,比如属于组件节点89的零件的key参数为CStr(rs("child") & "a"),属于节点91的零件的key参数为CStr(rs("child") & "b"),这样就不仅解决了每个节点的key参数不能重复的问题,而且解决了key参数不能仅仅为数字的问题。
但是我现在遇到的最大障碍是,数据库的表中有大量的属于不同节点的相同零件(即其属于的父节点的id不同,但是这个子节点的id值都是相同的),如果都用我上面所用的方法,那么代码量就相当的大了,操作起来相当困难。主要的问题就是集中在这个TreeView1.Nodes.Add方法的key参数上,唉,它的限制太多了。我想问一下,在VB6.0中,还有没有其他方法来读取一个数据库中的表,从而把它中的内容按节点之间的关系添加到TreeView控件中呢?或者有没有其他方法,可以避开add方法中的种种限制呢?
希望大家给小弟以指点,我现在有2000多分,我愿意把分全部给大家,谢谢!!!
...全文
427 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
qyii 2004-04-13
  • 打赏
  • 举报
回复
既然KEY值不能重复,那么就不能用它来你这样应用的标识了!

用动态数组,通过index来寻找存贮吧!

关于KEY值,可以这样生成~
转:
  每一个节点必须有一个键——字符串形式的标识符。对于新添加的或编辑过的节点,我们在编辑操作结束时生成一个1到10000000之间的随机数字,加上前缀“K”,以此作为节点的键。由于Rnd()函数不保证随机数字的唯一性,所以我们使用了一个循环,如果第一次生成的键已经被使用,VB会触发一个错误,这时我们继续循环,寻找另外的键。

Dim Repeat As Boolean
Repeat = True
While Repeat
 On Error Resume Next
 SmartTreeView.SelectedItem.Key = "K" & 1 + Int(Rnd() * 10000000)
 If Err.Number = 0 Then Repeat = False
Wend
flyingZFX 2004-04-12
  • 打赏
  • 举报
回复
没有好办法,你可以为子结点设置包含父接点名称的KEY值,从而达到唯一性。如:
Private Sub Command1_Click()
Do While Not rs.EOF
TreeView1.Nodes.Add , , "a" & rs("parent"), rs("parent") ' add parent nodes
TreeView1.Nodes.Add "a" & rs("parent"), 4, "a" & rs("parent") & "," & rs("child"), rs("child") 'add child nodes
rs.movenext
Loop
End Sub
tangxiaosan001 2004-04-12
  • 打赏
  • 举报
回复
给你一个无限树来参考吧.
Private Sub cmdADDP_Click()
Dim txtSQL As String
Dim MsgText As String
Dim mrc As ADODB.Recordset
If Trim(parText) <> "" Then
'cmdADDC_Click
'If TreeView1.Nodes(parText).Parent Is Nothing Then
Set nodX = TreeView1.Nodes.Add(parText, tvwChild)
nodX.Key = "n" & zlbh.Text
nodX.Text = zlmc.Text
nodX.EnsureVisible
txtSQL = "insert dm_wzlb(lbcode,lb,lbcode1,lb1)values('" & Trim(TreeView1.Nodes(parText).Key) & "','" & Trim(TreeView1.Nodes(parText).Text) & "','" & nodX.Key & "','" & nodX.Text & "')"
Set mrc = ExecuteSQL(txtSQL, MsgText)

Else
Set nodX = TreeView1.Nodes.Add(, tvwChild)
nodX.Key = "n" & zlbh.Text
nodX.Text = zlmc.Text
txtSQL = "insert dm_wzlb (lbcode,lb,lbcode1,lb1) values ('r','root','" & nodX.Key & "','" & zlmc.Text & "')"
Set mrc = ExecuteSQL(txtSQL, MsgText)
End If
zlbh.Text = ""
zlmc.Text = ""

End Sub
tfafei 2004-04-11
  • 打赏
  • 举报
回复
up
qinyonlhm 2004-01-16
  • 打赏
  • 举报
回复
不知道你的INDEX_ID是不是唯一的,如果是的话,可以用它来做KEY值上树啊
qinyonlhm 2004-01-16
  • 打赏
  • 举报
回复
如果有问题的话。
找我吧。晚上一般都在:
29211485
qinyonlhm@163.com
qinyonlhm 2004-01-16
  • 打赏
  • 举报
回复
参考一下我的这个吧:
''''keyname添加的健值,relationship 所属关系,image,添加的图标。
Public Sub Add_Tree(Tree As TreeView, xh As Variant, Relation As String, _
keyname As String, Txt As String, image As Integer)
Dim nodT As Node
On Error GoTo QYhander

Select Case Relation
Case "tvwChild"
Set nodT = Tree.Nodes.Add(xh, tvwChild, keyname, Txt, image)
Case "tvwNext"
Set nodT = Tree.Nodes.Add(xh, tvwNext, keyname, Txt, image)
Case "tvwLast"
Set nodT = Tree.Nodes.Add(xh, tvwLast, keyname, Txt, image)
End Select

Exit Sub

QYhander:
If Err.Number = 0 Then
Else
MsgBox "对不起!" & Err.Description & " " & Err.Number, vbCritical, "错误"
End If
End Sub
华芸智森 2004-01-15
  • 打赏
  • 举报
回复
我是用递归的方法实现的,具体代码如下(已有注释):

'/树操作基本参数列表.
Type BaseParameter
Cnn As ADODB.Connection 'ADODB 连接
TrvName As Object '树名称.
TabName As String '树对应的数据表名
ParFld As String '数据表中父节点的字段名.
ChildFld As String '数据表中子节点的字段名.
TextFld As String '数据表中节点文本名称的字段名.
RootIco As String '树中根目录的图标号.
Parico As String '树中父节点的图标号.
ExpParIco As String '树中展表一个节点时的图标号.
ChildIco As String '树中子节点的图标号.
RootText As String '树中根节点的文件.
End Type

Dim TrvBasePar As BaseParameter

'
'单表填充TREEVIEW
'函数:FillTreeView
'参数:SelectSql 一条没有WHERE条件表达式的SELECT语句.
'返回值:
'说明:SELECT语句中必须包括三项:父节点的字段名,子节点的字段名.节点的标签字段名
' 所有节点的KEY值是:G + 节点的ID号.Text值是:节点的标签名.
Public Function FillTreeView(SelectSql As String)
If TrvBasePar.TrvName Is Nothing Then
Exit Function
End If
Call FillTree("", "", SelectSql)
End Function

'/用递归法填充树视图
Private Function FillTree(ParFldValue As String, _
ParKey As String, _
SelectSql As String)
Dim N As Long
Dim NodeX As Node
Dim StrSql As String
Dim Rs As New ADODB.Recordset
Dim RsB As New ADODB.Recordset
Dim ParentArr() As String '记录有子节点的节点
Dim AddId As Long
Dim ChildKey As String, ChileStr As String
Dim Pid As String, PKey As String
Dim TagStr As String

AddId = 0
If Len(ParFldValue) = 0 Then
Set NodeX = TrvBasePar.TrvName.Nodes.Add(, , "G0000", TrvBasePar.RootText, "ROOT")
NodeX.Expanded = True
Call FillTree("0000", "G0000", SelectSql)
Else
StrSql = SelectSql & " Where " & TrvBasePar.ParFld & "='" & ParFldValue & "'"
Set Rs = M_DbCtrl.RsOpen(TrvBasePar.Cnn, StrSql)
If Not (Rs.EOF And Rs.BOF) Then
Rs.MoveFirst
While Not Rs.EOF
ChildKey = "G" & CStr("" & Rs.Fields(TrvBasePar.ChildFld))
Set NodeX = TrvBasePar.TrvName.Nodes.Add(ParKey, tvwChild, ChildKey, _
CStr("" & Rs.Fields(TrvBasePar.TextFld)), TrvBasePar.ChildIco)

StrSql = "Select Top 1 " & TrvBasePar.TabName & "." & TrvBasePar.ChildFld & " From " & TrvBasePar.TabName & _
" Where " & TrvBasePar.ParFld & "='" & CStr("" & Rs.Fields(TrvBasePar.ChildFld)) & "'"
Set RsB = M_DbCtrl.RsOpen(TrvBasePar.Cnn, StrSql)
If Not (RsB.EOF And RsB.BOF) Then
NodeX.Image = TrvBasePar.Parico
AddId = AddId + 1
ReDim Preserve ParentArr(1, AddId)
ParentArr(0, AddId - 1) = CStr("" & Rs.Fields(TrvBasePar.ChildFld))
ParentArr(1, AddId - 1) = CStr("G" & CStr("" & Rs.Fields(TrvBasePar.ChildFld)))
End If
Rs.MoveNext
Wend
Set Rs = Nothing
If AddId > 0 Then
For N = 0 To AddId - 1
Pid = ParentArr(0, N)
PKey = ParentArr(1, N)
Call FillTree(Pid, PKey, SelectSql)
Next
End If
End If
End If
End Function

rinco 2004-01-14
  • 打赏
  • 举报
回复
楼主的这种表设计,用递归来完成可以

不过象这样的情况,最好不要用一张表完成
用一张表表示树形关系
另外用N张表说明各种类型节点信息(一种节类型一张表)
为了能一次上树,节点ID最好不用parent模式,直接在节点ID里包含父节点ID,如
CHILD CHILD_TYPE CHILD_NAME INDEX_ID
88 1 双输入伺服阀 1
88_89 2 衔铁组件 2
88_89_01 2 衔铁组件 3
AresChen 2004-01-14
  • 打赏
  • 举报
回复
是哦,是哦,对于你这种两层的结构,只要将key设置为pid和id的合集就行了,就算对于多层的结构,也只需在上一层的后面加上本node的id就可以了。
davidlv 2004-01-14
  • 打赏
  • 举报
回复
key值使用str(treeview.nodes.count+1) & ItemCode

装的时候是一层层的装,即只先装第一层,当点中一个节点时再去数据表里找它的子阶,装上去。这样就行了。
yk84 2004-01-13
  • 打赏
  • 举报
回复
UP!!!!!!!!!!!!!
davidlv 2004-01-13
  • 打赏
  • 举报
回复
我知道你的需求了,让我想一下。需要的话找我吧

msn:yongliang_lv@msn.com
davidlv 2004-01-13
  • 打赏
  • 举报
回复
你把你想列出的树状写出来,我帮你想一个办法,我的表结构基本与你相同
rainstormmaster 2004-01-03
  • 打赏
  • 举报
回复
呵呵,你可以这样指定key:CStr(rs("child") +“index "+cstr(i)
i为你在循环中使用的记数器
northwolves 2004-01-03
  • 打赏
  • 举报
回复
没有好办法,你可以为子结点设置包含父接点名称的KEY值,从而达到唯一性。如:
Private Sub Command1_Click()
Do While Not rs.EOF
TreeView1.Nodes.Add , , "a" & rs("parent"), rs("parent") ' add parent nodes
TreeView1.Nodes.Add "a" & rs("parent"), 4, "a" & rs("parent") & "," & rs("child"), rs("child") 'add child nodes
rs.movenext
Loop
End Sub

1,451

社区成员

发帖
与我相关
我的任务
社区描述
VB 控件
社区管理员
  • 控件
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧