Notifications
Clear all

[Closed] Building a Directory Struct for dotNet TreeView

updated example with expanded top node and an optional ignoreList parameter:

try(destroyDialog theRollout)catch()
 rollout theRollout "The Rollout" width:300
 (
 	local TreeNodeClass = dotnetclass "System.Windows.Forms.TreeNode"
 	
 	dotNetControl tv "system.windows.forms.treeView" height:200
 	
 	fn IsMatch str patternArr =
 	(
 		noMatch = true
 		for p in patternArr while noMatch where matchpattern str pattern:p do noMatch = false
 		NOT noMatch
 	)
 	
 	fn GetDirectoryTree dir ignoreList:undefined =
 	(
 		flt = filterstring dir "\\"
 		dirName = flt[flt.count]
 		
 		if ignoreList == undefined OR NOT IsMatch dirName ignoreList then
 		(
 			t = dotnetobject TreeNodeClass dirName
 			t.Tag = dir -- assign the full path to the tag property
 			
 			subDirs = GetDirectories (dir+@"/*")
 			subNodes = #()
 			for d in subDirs do
 			(
 				sub = GetDirectoryTree d ignoreList:ignoreList
 				if sub != undefined do append subNodes sub
 			)
 			t.Nodes.AddRange subNodes
 			
 			t
 		)
 		else
 			undefined
 	)
 	
 	on theRollout open do
 	(
 		n = GetDirectoryTree (getDir #maxroot) ignoreList:#("*maps*")
 		tv.Nodes.Add n
 		n.Expand()	-- expand the top node
 	)
 )
 createDialog theRollout

I owe you a beer Gravey, thanks, hopefully this will be useful for anyone else wanting to do a similar thing.

 JHN
treeview.Nodes.Clear()

If you really want to know more about dotnet it’s a great investment to spend some time learning how to navigate through the msdn docs!

http://msdn.microsoft.com/en-us/library/system.windows.forms.treenodecollection_methods.aspx

-Johan

Perfect Thanks.

I am using Kameleon’s KClasses which really simplifies building the directory tree.

If I have a treeview generated from a directory tree, can I set a specific node to be selected on open?

I would like to write out a user’s last selection to an ini and then retrieve it on open so they can jump back to it when they open the tool again.

I’ve looked at Expand and EnsureVisible methods on MSDN. But these don’t set the node selection. The directory tree may change over time, adding directories mostly. So I assume an index would fail after the structure of the tree changes.

Can I identify a node by its path string? “\server hisFolder hatFolder”


  on tvFolders NodeMouseClick sender eb do
   (
    setINISetting (getdir #userScripts + "\AssetTools.ini") "Browser" "TreeViewDefaultLocation" eb.node.dirName
    )
  
 PEN

When you are recursing through and building the nodes then just set the one that you want selected as you go.

tv=dotNetObject "treeView"
showProperties tv
tv.SelectedNode=someTreeViewNode

Thanks Paul,

I’m not generating the treeview… Kameleon is doing it for me!


dotnet.loadAssembly "KClasses.dll"
  dotnetcontrol tvFolders "KClasses.dnFolders"
  tvFolders.ProcessTree(@"\\server\pathToRootFolder")

I don’t think it generates names when it does this. He has added the dirName property but I’m not sure I can use that to set the current node…

I do need to learn the long way around (recursing the folder tree) from your examples. Maybe that is what I need to do after work tonight…

This is what I understood you meant, but I must not have it right.

If you select a node, it saves the node.name to the ini. It just doesn't work to load that string as a node name in tv.SelectedNode  
try(destroyDialog theRollout)catch()
     rollout theRollout "The Rollout" width:300
     (
    	 local TreeNodeClass = dotnetclass "System.Windows.Forms.TreeNode"
    	 
    	 dotNetControl tv "system.windows.forms.treeView" height:200
    	 
    	 fn IsMatch str patternArr =
    	 (
    		 noMatch = true
    		 for p in patternArr while noMatch where matchpattern str pattern:p do noMatch = false
    		 NOT noMatch
    	 )
    	 
    	 fn GetDirectoryTree dir ignoreList:undefined =
    	 (
    		 flt = filterstring dir "\\"
    		 dirName = flt[flt.count]
    		 
    		 if ignoreList == undefined OR NOT IsMatch dirName ignoreList then
    		 (
    			 t = dotnetobject TreeNodeClass dirName
    			 t.Tag = dir -- assign the full path to the tag property
    			 t.Name = dir
    			
    			 subDirs = GetDirectories (dir+@"\*")
    			 subNodes = #()
    			 for d in subDirs do
    			 (
    				 sub = GetDirectoryTree d ignoreList:ignoreList
    				 if sub != undefined do append subNodes sub
    			 )
    			 t.Nodes.AddRange subNodes
    			 
    			 t
    		 )
    		 else
    			 undefined
    	 )
    	 
    	 on theRollout open do
    	 (
    		 n = GetDirectoryTree (getdir #maxroot) ignoreList:#("*cloth*","*drivers*","*pre*")
    		 tv.Nodes.Add n
    		 n.Expand()	-- expand the top node
    	    if (hasINISetting (getdir #userScripts + "\TV_Test.ini") "Browser" "TreeViewDefaultLocation") do
    		(
    			tv.SelectedNode= (getINISetting (getdir #userScripts + "\TV_Test.ini") "Browser" "TreeViewDefaultLocation")
    	    )
    	 )
    	
    	on tv NodeMouseClick sender args do
    	(
    		setINISetting (getdir #userScripts + "\TV_Test.ini") "Browser" "TreeViewDefaultLocation"args.node.name
    		clearlistener()
    		print args.node.name
 
       	)
    	
     )
     createDialog theRollout
    

setting the tv.SelectedNode to a string is not possible, you need to get the node from the node collection that contains it. Unfortunatly its not enough to just say tv.nodes.Item[“key”] because that will only search the root level TreeNodeCollection. In the code below I am saving the selected node’s FullPath property to the ini file instead of its name and using the GetTreeNodeByFullPath function to search the tree and get the previously selected node. The function returns undefined if any node does not exist along the path which would happen if you changed the root path.

try(destroyDialog theRollout)catch()
 rollout theRollout "The Rollout" width:300
 (
 	local TreeNodeClass = dotnetclass "System.Windows.Forms.TreeNode"
 
 	dotNetControl tv "system.windows.forms.treeView" height:200
 
 	fn IsMatch str patternArr =
 	(
 		noMatch = true
 		for p in patternArr while noMatch where matchpattern str pattern:p do noMatch = false
 		NOT noMatch
 	)
 
 	fn GetDirectoryTree dir ignoreList:undefined =
 	(
 		flt = filterstring dir "\\"
 		dirName = flt[flt.count]
 
 		if ignoreList == undefined OR NOT IsMatch dirName ignoreList then
 		(
 			t = dotnetobject TreeNodeClass dirName
 			t.Tag = dir -- assign the full path to the tag property
 
 			subDirs = GetDirectories (dir+@"\*")
 			subNodes = #()
 			for d in subDirs do
 			(
 				sub = GetDirectoryTree d ignoreList:ignoreList
 				if sub != undefined do append subNodes sub
 			)
 			t.Nodes.AddRange subNodes
 
 			t
 		)
 		else undefined
 	)
    
 	fn GetTreeNodeByFullPath fullPath =
 	(
 		dirNames = filterString fullPath tv.PathSeparator
 		n = tv
 		for dirName in dirNames while n != undefined do n = n.Nodes.Item[dirName]
 	   
 		n
 	)
 
 	on theRollout open do
 	(
 		tv.HideSelection = false
 	   
 		n = GetDirectoryTree (getdir #maxroot) ignoreList:#("*cloth*","*drivers*","*pre*")
 		tv.Nodes.Add n
 		n.Expand()	-- expand the top node
 	   
 		fullPath = getINISetting (getdir #userScripts + "\TV_Test.ini") "Browser" "TreeViewDefaultLocation"
 		if fullPath != undefined do
 		(
 			n = GetTreeNodeByFullPath fullPath
 			if n != undefined do tv.SelectedNode = n
 		)
 	)
 
 	on tv NodeMouseClick sender args do
 	(
 		fullPath = args.node.FullPath
 		setINISetting (getdir #userScripts + "\TV_Test.ini") "Browser" "TreeViewDefaultLocation" fullPath
 	)
 
 )
 createDialog theRollout

“TreeNodeCollection” has method “Find”
.<System.Windows.Forms.TreeNode[]>Find <System.String>key <System.Boolean>searchAllChildren

to find all nodes in the tree view by key is:


 nodes = tv.nodes.Find key on
 

…and there is no reason to store the full (dir) path in tree node’s name. You always can get it reading tree node’s “FullPath” property. It’s better to store full path’s Hash Value as string.


node.name = (getHashValue <fullpath> 0) as string -- (see mxs help for details)

using the hash value makes all search operations much faster.

also I recommend to convert the full path name to Lower Case and with only Forward Slashes:


	str = pathConfig.convertPathToLowerCase str
	str = substituteString str "\\" "/"


Page 2 / 3