注册 登录
编程论坛 VFP论坛

请教TreeView遍历选中节点及其子节点

hyf8285 发布于 2022-07-12 19:51, 3510 次点击
请教:版主和各位大佬,想通过遍历节点及子节点枚举得到节点的路径,比如:我点击“南京大学”,则它的路径为“笔记分类\南京大学”,然后会遍历他的每个子节点,遍历到“经济学”时,则它的路径为“笔记分类\南京大学\经济学”,以此类推,在网上抄了一段遍历子节点的代码,其中注释部分是我写的,但是不对,麻烦大佬帮忙看下。(我知道TreeView控件有FullPath属性得到路径的,但是我使用的场景是加载数据之前),只有46分了
只有本站会员才能查看附件,请 登录
只有本站会员才能查看附件,请 登录
37 回复
#2
hyf82852022-07-12 20:36
请大佬帮忙看下!
#3
csyx2022-07-13 09:13
如果只是遍历子节点,几行代码就够了
1. 新建一个表单方法: 遍历子节点,代码如下
程序代码:
Lparameters oNode

? oNode.FullPath

Local oo

If oNode.Children > 0
    oo = oNode.Child
    Do while !IsNull(oo)
        This.遍历子节点(oo)
        oo = oo.Next
    EndDo
EndIf


2. 遍历子节点按钮.Click 调用它:
Thisform.遍历子节点(Thisform.treeView1.SelectedItem)
#4
hyf82852022-07-13 10:30
回复 3楼 csyx
谢谢!确实好用!还想请教:我如何更新子节点的路径?(我想要移动节点来更新路径),比如“经济学”原来的路径是“笔记分类\南京大学\经济学”,现在我将“经济学”节点移动到“南京理工大学”下面,则路径要变为“笔记分类\南京理工大学\经济学”,他的子节点也要同时更新,请问如何操作?
#5
csyx2022-07-13 11:10
节点移动后,被移动节点及所有子节点的 fullpath 属性自动就变了,要更新啥

[此贴子已经被作者于2022-7-13 11:27编辑过]

#6
hyf82852022-07-13 11:27
回复 5楼 csyx
移完以后,TreeView控件要重新加载数据,我是根据表的数据来加载的,通过父对象和层数的顺序来加载,移完后数据表的父对象和层数都要相应的改变,才能顺利加载,否则会出现找不到对象,我通过算路径的层数来决定加载的顺序

[此贴子已经被作者于2022-7-13 11:30编辑过]

#7
csyx2022-07-13 11:35
没明白,发个示例上来,要根据你是如何移动节点的,然后要更新啥,才知道
#8
hyf82852022-07-13 12:05
回复 7楼 csyx
好的,感谢!我下午做个例子发给你看下
#9
hyf82852022-07-13 14:44
回复 7楼 csyx
请大佬帮忙看下!谢谢!
只有本站会员才能查看附件,请 登录
#10
csyx2022-07-13 17:34
简单修改了一下,详见 treeview1.init 开头注释
只有本站会员才能查看附件,请 登录
#11
hyf82852022-07-13 17:49
回复 10楼 csyx
好的,谢谢!我学习下!
#12
csyx2022-07-13 18:00
还有些需要写代码限制的拖放操作,例如:父节点拖放到自己的子节点上
#13
hyf82852022-07-13 18:22
回复 12楼 csyx
是的,正在学习!那这样我原来程序里的大部分代码都要修改了,你是用递归来加载数据的吧?那我原来表里的nLayer字段(层级)还需要了吗?
#14
csyx2022-07-13 18:44
如果 nLayer 没有其他用途是可以不要,cfullpath 好像也用不到
改成递归加载方式,是为了保障先加载父节点,再由父节点去加载自己的子节点,避免出现父节点还没加载就先加载子节点的情况
#15
hyf82852022-07-13 18:55
回复 14楼 csyx
nLayer字段就是为了动态加载数据而设的,按照“父对象+nLayer”升序排列,一层一层的加载,也是为了避免父对象还未加载而出现错误,所以,我本来的想法是,拖动节点后,先算出新节点的层数,然后加载,这样也不会错。问题就是不会算拖动后节点的层数,现在按照你的方法,nLayer可以不要了,cFullPath是在我的程序里用到的。
非常感谢您的帮助!我还在学习领悟你的方法!

[此贴子已经被作者于2022-7-13 18:57编辑过]

#16
csyx2022-07-13 18:55
先说要做的限制也很容易判断, OLEDragDrop 开始部分改一下
c0 = This.Nodes(srcKey)
c1 = This.Nodes(tagKey)
if c0 $ c1 then 不允许 else 允许

如同儿子可以过继给大伯叔叔做儿子,但绝对不允许老爸变成儿子的儿子
#17
hyf82852022-07-13 18:59
限制条件我会写的,包括不能移到子节点的子节点...
#18
csyx2022-07-13 19:00
算层数应该简单吧,Occurs('\', oNode.FullPath) 就是这个节点的层数(如果节点文本中不会出现 \ 符号的话)
#19
hyf82852022-07-13 19:02
算层数简单,是这个路径不好算,你拖动后,路径就变了,包括子节点的路径,因为你还没有加载,所以FullPath得到的是原来的路径,所以我一开始的问题就是问你们如何算出拖动后节点的路径
#20
csyx2022-07-13 19:04
也是,一个节点好算,关键是可能拖一大串葡萄过来
#21
hyf82852022-07-13 19:05
回复 20楼 csyx
哈哈!是的,这个比喻好形象
#22
hyf82852022-07-14 18:22
以下是引用csyx在2022-7-13 09:13:34的发言:

如果只是遍历子节点,几行代码就够了
1. 新建一个表单方法: 遍历子节点,代码如下
Lparameters oNode

? oNode.FullPath

Local oo

If oNode.Children > 0
    oo = oNode.Child
    Do while !IsNull(oo)
        This.遍历子节点(oo)
        oo = oo.Next
    EndDo
EndIf


2. 遍历子节点按钮.Click 调用它:
Thisform.遍历子节点(Thisform.treeView1.SelectedItem)

大佬!再请教:用你的递归遍历子节点,现在当我用这个查找子节点时,如果找到结果,则立即退出递归!请问:当满足条件时如何退出递归?谢谢!

Lparameters oNode,tcSelectKey
Local oCurNode,ChildKey,isIndetical
isIdentical = .F.
*ChildKey = oNode.Key
a = Alltrim(oNode.Key)
Messagebox(a+tcSelectKey,0,"")
If a == Alltrim(tcSelectKey)
    isIndetical = .T.
    Messagebox("相同了,找到啦!",0,"")
    Return                            &&这里应该退出了,并返回.T.,但是还是会继续下去,直至最后
Else
    isIndetical = .F.
Endif
If oNode.Children > 0
    oCurNode = oNode.Child
    Do While !Isnull(oCurNode)        
        This.findTreeNode(oCurNode,tcSelectKey)
        oCurNode = oCurNode.Next        
    Enddo
Endif
Return isIndetical

[此贴子已经被作者于2022-7-14 18:42编辑过]

#23
csyx2022-07-14 19:41
这样呢?
程序代码:
Lparameters oNode,tcSelectKey

Local oCurNode,ChildKey

a = Alltrim(oNode.Key)
Messagebox(a+tcSelectKey,0,"")

If a == Alltrim(tcSelectKey)
    Messagebox("相同了,找到啦!",0,"")
    Return .F.                            &&这里应该退出了,并返回.T.,但是还是会继续下去,直至最后
Endif

If oNode.Children > 0
    oCurNode = oNode.Child
    Do While !Isnull(oCurNode) and This.findTreeNode(oCurNode,tcSelectKey)
        oCurNode = oCurNode.Next     
    Enddo
Endif
#24
hyf82852022-07-14 20:07
回复 23楼 csyx
好像不是立即退出的,还要再递归一次才退出,而且退出后都返回T

[此贴子已经被作者于2022-7-14 20:18编辑过]

#25
csyx2022-07-14 20:25
messagebox(a+tcSelectKey) 显示的是不是你需要的退出条件?

[此贴子已经被作者于2022-7-14 20:27编辑过]

#26
hyf82852022-07-14 20:38
回复 25楼 csyx
那个是我看的输出结果,我条件是 a = tcSelectKey 现在解决了,我在外面加个变量,初始为.F.,然后找到后变为.T.,这样判断这个为.T.时就退出递归了,但是返回值都是.F.啊?
#27
hyf82852022-07-14 20:41
程序代码:
Lparameters oNode,tcSelectKey
Local oCurNode,ChildKey,isIndetical
isIdentical = .F.
*ChildKey = oNode.Key
a = Alltrim(oNode.Key)
Messagebox(a+tcSelectKey,0,"")
If a == Alltrim(tcSelectKey)
    isIndetical = .T.   
    Messagebox("相同了,找到啦!",0,"")
    isCheck = .T.  &&加了这个
    Return isIndetical                        
Endif
If oNode.Children > 0
    oCurNode = oNode.Child
    Do While !Isnull(oCurNode)
        If isCheck = .t.  &&判断
           Exit
        Else
        This.findTreeNode(oCurNode,tcSelectKey)            
        oCurNode = oCurNode.Next
        EndIf         
    Enddo
Endif
Return isIndetical


[此贴子已经被作者于2022-7-14 20:42编辑过]

#28
csyx2022-07-14 20:51
代码看上去怪怪的,逻辑不怎么对
#29
csyx2022-07-14 20:54
应该是调用 findTreeNode 的地方或者传入的 oNode 不对
#30
hyf82852022-07-14 21:06
好的,我在研究研究,谢谢你!
#31
hyf82852022-07-15 15:52
回复 23楼 csyx
大佬,烦请您再帮我看下昨晚的问题!好像我做的不对!我第一次用递归,不懂原理!要求在文件里,谢谢!
只有本站会员才能查看附件,请 登录
#32
csyx2022-07-15 23:34
下来看了一下,需求确定你的需求
只有本站会员才能查看附件,请 登录

为何要传入这个参数?是仅搜索选中节点及其子节点,还是全树搜索东南大学?
#33
hyf82852022-07-16 07:03
回复 32楼 csyx
早上好!这个参数是从你点击的节点开始搜索,后面的东南大学,是随便指定的一个节点,主要用来测试,后面用在程序里时,东南大学也会指定一个参数
#34
hyf82852022-07-16 07:04
是从选中节点开始搜索
#35
csyx2022-07-16 09:17
只有本站会员才能查看附件,请 登录
#36
hyf82852022-07-16 10:02
回复 35楼 csyx
感谢!是不是重新写过函数啦?不是之前的那个函数了?
#37
csyx2022-07-16 11:25
以下是引用hyf8285在2022-7-16 10:02:54的发言:

是不是重新写过函数啦?不是之前的那个函数了?

查看 找节点并返回.click

这句删掉:
只有本站会员才能查看附件,请 登录


[此贴子已经被作者于2022-7-16 11:32编辑过]

#38
hyf82852022-07-16 11:52
回复 37楼 csyx
好的,感谢!测试完全符合要求!
1