Treeview

B

Bob Hollness

Hi.

I have a text file containing a list of files and their path. I.e.

c:\MyDocs\File1.txt
c:\MyDocs\File2.txt
c:\MyDocs\File3.txt
c:\MyDocs\File4.txt
C:\MyDocs\Folder\File1.txt

etc.

What I want to do is create a treeview that makes this look like a directory
listing (i.e. Windows Explorer). The problem I have is getting VB to
realise that "C:\MyDocs\Folder\File1.txt" should be a child of "c:\MyDocs\"
and add it as a child node. So far, all i get is each item listed
individually in the treeview.

Any ideas/help? Thanks.
 
B

Bob Hollness

I was actually hoping of breaking the string up into sections and then
trying to add each folder. then when it raised an error saying that the
node already existed, to trap it so i could use it as a subfolder node.

i.e. the code adds C:\
then it adds MyDocs to C:\ because when it tries to add C:\ it find that it
already exists, thus using it as a parent.

etc.

I am kinda stuck on the actual code though!!!

--

Bob

--------------------------------------
I'll have a B please Bob.

Nick Stansbury said:
Bob,

You are, I presume, doing the binding code yourself. To make this work
you'll need to a recursive binding methodology. My best guess would be
that
you'll need
to parse the text file in such a way that you do the work of marking up
parents and children, and then add them to the tree recursively. Doing
this
by hand is actually quite a complex problem - you might want to look at
how
the text file is populated - outputting it as XML would make the whole
process a lot easier.

Regards,

Nick Stansbury
 
N

Nick Stansbury

Bob,

You are, I presume, doing the binding code yourself. To make this work
you'll need to a recursive binding methodology. My best guess would be that
you'll need
to parse the text file in such a way that you do the work of marking up
parents and children, and then add them to the tree recursively. Doing this
by hand is actually quite a complex problem - you might want to look at how
the text file is populated - outputting it as XML would make the whole
process a lot easier.

Regards,

Nick Stansbury
 
B

Bob Hollness

do you know of anyone of telling VB that each entry in the treeview must be
unique?

--

Bob

--------------------------------------
I'll have a B please Bob.

Nick Stansbury said:
Bob,

You are, I presume, doing the binding code yourself. To make this work
you'll need to a recursive binding methodology. My best guess would be
that
you'll need
to parse the text file in such a way that you do the work of marking up
parents and children, and then add them to the tree recursively. Doing
this
by hand is actually quite a complex problem - you might want to look at
how
the text file is populated - outputting it as XML would make the whole
process a lot easier.

Regards,

Nick Stansbury
 
N

Nick Stansbury

Not that I know of. Here's some kind of pseudo code - you'll have to fill in
the blanks

Class FilePath
Public ChildCollection as Collection
Public Address as string
Public DirectoryPath as string
Public FileName as string
ParentAddress as string
End Class

Dim TempCollection as new Collection
Dim BaseFilePath as FilePath 'the root object
'open a stream from the file and read each line into a local variable.
Return EOF = true when finished with the last line
dim StrTmp as stirng
Dim CountOfSlashes as long
Dim StringIndex as long
dim LastSlash as boolean
dim CurrentPath as filePath

Do until EOF
CurrentPath = new FilePath
StringIndex = 0
strTmp = readLine()
CurrentPath.Address = StrTmp
if instr(StrTmp, ".") > 0 then
'this is a file, so we have to grab the directory path
stripping off the filename
StringIndex = StrTmp.LastIndexOf("\")
CurrentPath.DirectoryPath = Left(StrTmp, StringIndex + 1)
'should get the C:\MyFolder\ section of C:\MyFolder\MyFile.txt
FileName = Mid(StrTmp, StringIndex + 1) ' should get
MyFile.txt part of the above sample string
else
CurrentPath.DirectoryPath = StrTmp
FileName = "" 'set to ZLS for testing purposes
end if
'now get the parent address which should be the same for every line
if instr(StrTmp, "\", 3) > 0 then 'start at the 4th character in the
string (i.e. start just after the first slash in C:\MyFolder\MyFile.txt) and
see if there are any following slashes
StringIndex = StrTmp.LastIndexOf("\")
'now add the whole string up to this point as the parent
address
currentPath.ParentAddress = left(StrTmp, StringIndex)
'should add the whole of strtmp up to the last "\" as the parent address
end if
TempCollection.add(CurrentPath)
Loop

'now it should simple be a case of iterating through the collection and
adding the object in a structured way to the base object.


Hope this helps - basically the idea is that you parse the strings to break
them up into the parent section, the filename and the current address. You
then should compare the currentAddress to the parentAddress and be able to
group them into a single recursive set of objects. Once you have them in a
nice useable structure you should be able to draw the tree view very easily.
You could also persist the object tree into memory for later use

Nick





Bob Hollness said:
do you know of anyone of telling VB that each entry in the treeview must be
unique?
 
B

Bob Hollness

Thanks. I have so far thrown together this code (with a lot of assistance
from a webpage i found). It does the trick great. My only problem now is
that I would like to somehow differenciate between files and folders by
putting the appropriate icons in their places. This has me kinda stumped at
the moment. I guess the only way to do this is to look for a file extension
and the change the icon. As you can see in the code, there is a rather
dodgy IF statement which tries to do this. The problem I have is that VB
seems to only apply this rule for the first file in a directory (child node)
and then all the others have the folder icon.

Any ideas / improvements?



Private Function BuildNodeList(ByVal currentPath As String, ByVal NodeTree
As TreeNodeCollection) As Boolean

Dim NodeText As String
Dim nNode As TreeNode
Dim strPath() As String

If currentPath.Chars(0) = "\" Then currentPath =
currentPath.Substring(1)

strPath = currentPath.Split("\")

For Each NodeText In strPath

For Each nNode In NodeTree

If nNode.Text = NodeText Then

If PathData = "" Then Exit Function

PathData = PathData.Substring(strPath(0).Length)
Add2Node2(PathData, nNode.Nodes)

Exit Function
End If
Next

If NodeText <> "" Then

If Mid(NodeText, Len(NodeText) - 3, 1) = "." Then
'file
NodeTree.Add(NodeText)
NodeTree.Item(NodeTree.GetEnumerator.Current).ImageIndex
= 2
NodeTree.Item(NodeTree.GetEnumerator.Current).SelectedImageIndex
= 2
Else
'folder
NodeTree.Add(NodeText)
NodeTree.Item(NodeTree.GetEnumerator.Current).ImageIndex
= 1
NodeTree.Item(NodeTree.GetEnumerator.Current).SelectedImageIndex
= 1
End If

Add2Node2 = True

End If
Next

End Function
 
N

Nick Stansbury

Firstly I'd check using an instr(string, ".") > 0 to do the check. It's a
bit less dodgy. Again the key is to use recursing like so:

Private Sub SetImage(nNode as TreeNode0
if instr(nNode.text, ".") > 0 then
'set the image on the node to be a file
else
'set the image on the node to be a folder
end if

for each ChildNode as TreeNode in nNode.Nodes
SetImage (ChildNode)
next
End sub

This help?

Nick
 
N

Nick Stansbury

Bob - It's quitting time in the UK now. If you need further help then email
me and I'd be happy to answer in the morning, and we can post a solution
back here after.

Nick
 
B

Bob Hollness

Is it? I wish. As a Brit myself I don't get the luxury of finishing this
early!!!!! Thanks for the last post, i'm gonna play some more with this and
any results I post!
 
J

Jay B. Harlow [MVP - Outlook]

Bob,
Rather then hard code the path separator I would use System.IO.Path.

Also your NodeTree.GetEnumerator.Current is probably not doing what you
think it is, it will always return the first child node, I suspect you want
the node you just added.

I would use something like:

Private Sub BuildNodeList(ByVal currentPath As String, ByVal children As
TreeNodeCollection)

If currentPath.StartsWith(System.IO.Path.DirectorySeparatorChar) _
OrElse
currentPath.StartsWith(System.IO.Path.AltDirectorySeparatorChar) Then
currentPath = currentPath.Substring(1)
End If

Dim paths() As String

paths = currentPath.Split(System.IO.Path.DirectorySeparatorChar,
System.IO.Path.AltDirectorySeparatorChar)

For Each path As String In paths
Dim child As TreeNode = Nothing

For Each child In children
If child.Text = path Then
Exit For
End If
Next

If child Is Nothing OrElse child.Text <> path Then
child = children.Add(path)
If System.IO.Path.HasExtension(path) Then
'file
child.ImageIndex = 2
child.SelectedImageIndex = 2
Else
'folder
child.ImageIndex = 1
child.SelectedImageIndex = 1
End If
End If
children = child.Nodes
Next

End Sub

Note: Using an extension to determine if you have a file or folder is
probably not a good idea, It might be better to check for the last element
in the array instead, for example assume its a folder, then just after the
For Each set for file...

Hope this helps
Jay
 
B

Bob Hollness

Jay, this is excellent! It now recognises every file correctly! One tiny
problem. It is still ignoring the image changes. Everything comes out with
an index of 2........?

--

Bob

--------------------------------------
I'll have a B please Bob.

Jay B. Harlow said:
Bob,
Rather then hard code the path separator I would use System.IO.Path.

Also your NodeTree.GetEnumerator.Current is probably not doing what you
think it is, it will always return the first child node, I suspect you
want the node you just added.

I would use something like:

Private Sub BuildNodeList(ByVal currentPath As String, ByVal children
As TreeNodeCollection)

If currentPath.StartsWith(System.IO.Path.DirectorySeparatorChar) _
OrElse
currentPath.StartsWith(System.IO.Path.AltDirectorySeparatorChar) Then
currentPath = currentPath.Substring(1)
End If

Dim paths() As String

paths = currentPath.Split(System.IO.Path.DirectorySeparatorChar,
System.IO.Path.AltDirectorySeparatorChar)

For Each path As String In paths
Dim child As TreeNode = Nothing

For Each child In children
If child.Text = path Then
Exit For
End If
Next

If child Is Nothing OrElse child.Text <> path Then
child = children.Add(path)
If System.IO.Path.HasExtension(path) Then
'file
child.ImageIndex = 2
child.SelectedImageIndex = 2
Else
'folder
child.ImageIndex = 1
child.SelectedImageIndex = 1
End If
End If
children = child.Nodes
Next

End Sub

Note: Using an extension to determine if you have a file or folder is
probably not a good idea, It might be better to check for the last element
in the array instead, for example assume its a folder, then just after the
For Each set for file...

Hope this helps
Jay
 
J

Jay B. Harlow [MVP - Outlook]

Bob,
As I stated:
The routine I gave works with the data you initially gave.

I did not test the following thought:So it may or may not work as you expect...

Hope this helps
Jay
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top