hi..
Hi,
For each list in site
If list is a document library
For each file in root folder
Add file node to treeview
For each folder in root folder
Add folder node to treeview
Process contents of folder
As you can see, the program is very simple in concept. (Of course, you know it’s the details that keeps us programmers up at night!)
Recursion occurs when the Process contents of folder line is executed, and looks something like this:
For each file in folder
Add a file node to treeview
For each sub-folder in folder
Process contents of sub-folder
Iterating Through the Document Libraries, Folders and Files
Using the Sharepoint API you can navigate the list of document libraries, folders, documents and document properties on the current site. I’ll focus first on the steps to iterate through the list of document libraries, access their folders, files, and file properties. After that, I’ll come back to the steps required to format this data as a TreeView.
Step 1 – Getting the Current Site Context
Most SharePoint classes that you will use to create web parts need a context . This essentially tells the class what site it’s operating on. The following code fragment gets the context of the site on which the web part is placed:
Dim site As SPWeb =
Microsoft.SharePoint.WebControls.SPControl.GetContextWeb(Context)
Because all other SharePoint objects used will be based on child classes of site, they will inherit its context.
One thing to remember is that all web parts run in the context of the site of the page on which they’re placed. While it’s possible to create a web part that uses a context other than that of the current site, this is the exception rather than the rule. There are other uses for the SharePoint object model (such as to build administrative console applications or web services) where a context cannot be derived from the environment in which the application runs, and so must be provided by the end user or via some other means. The context ultimately resolves to the URL of the site to which the methods and properties refer.
Step 2 – Getting a Collection of All Lists in the Site
The next step is to obtain a collection of lists on the site. This will provide a starting point for navigating through all the document libraries, folders and files needed to display the DLTV.
dlCollection = site.Lists
Step 3 – Extracting the Document Library Lists
Of course, there are many types of lists, and the only ones we’re interested in are the document libraries. We’ll use the following conditional statement to return only the document libraries.
For Each dl In dlCollection
If IsInDoclibList(dl.Title, [DoclibName]) And dl.BaseType = _
SPBaseType.DocumentLibrary Then
The SPBaseType enumeration allows you to select just the document libraries. Note the IsInDoclibList() method call, this is a helper function I wrote to determine whether the document library being examined is one of those named in the web part Document library name property .
Step 4 – Displaying the Files in the Root Folder Level for a Doclib
Now that I have a pointer ( dl ) to a document library I want to include in the DLTV, I need a way to iterate through the files and folders of that library. To do so I’ve written a couple of helper functions that are executed recursively. They are ShowSortedFiles() and ShowSortedFolders() . Recursion is used to make it possible to process a tree structure of arbitrary depth without needing to know anything about the structure beforehand. If you’ve ever written code to navigate a file system directory structure, you’ve probably created similar code. I’ll discuss ShowSortedFiles() in this step, and ShowSortedFolders() in the next.
First, let’s dissect the parameter list for the helper function:
ShowSortedFiles(site.GetFolder(dl.Title.Trim),thisNodeId,output,colOutput)
The parameters for the ShowSortedFiles() method are:
site.GetFolder(dl.Title.Trim) – returns a folder object, in this case the document library’s root folder
thisNodeId – is a variable whose value uniquely identifies a node in the tree. If you are using a TreeView other than dtree, this may or may not apply.
output – is a reference to the web part’s Sytstem.Web.UI.HtmlTextWriter property. I need a handle to this to write out the client-side JavaScript that will display the tree.
colOutput – is a reference to a collection variable I use to buffer the output if the user has unchecked the Show folders? property. This and the other properties will be covered in the Creating the Web Part Properties section later in this article.
The skeleton of the ShowSortedFiles() method, shown below, is very straightforward.
Private Function ShowSortedFiles(ByVal fldr As SPFolder, _
ByVal thisNodeId As Integer, _
ByVal output As System.Web.UI.HtmlTextWriter, _
ByVal colOutput As Collection)
Dim arrFlSorted() As String
Dim i As Integer
Dim j As Integer
If _includeFiles Then
For i = 0 To fldr.Files.Count – 1
If fldr.Files(i).TimeLastModified >= _
Now.AddDays(-_daysBack2Include) Then
ReDim Preserve arrFlSorted(i)
If Order = EnumSortField.Name Then
arrFlSorted(i) = fldr.Files(i).Name & CONST_SPLITCHAR & i
ElseIf Order = EnumSortField.Title Then
arrFlSorted(i) = fldr.Files(i).Title & CONST_SPLITCHAR & i
ElseIf Order = EnumSortField.Sequence Then
arrFlSorted(i) = fldr.Files(i).Item("Sequence") & _
CONST_SPLITCHAR & i
End If
Next
End If
If _showFolders Then
Array.Sort(arrFlSorted)
For i = 0 To arrFlSorted.Length – 1
j = arrFlSorted(i).Split(CONST_SPLITCHAR)(1)
output.Write("d" & _treeViewId.ToString & ".add(" & _
IncrNodeId() & "," & thisNodeId & ",’" & _
FormatTreeNode(fldr.Files(j).Name, fldr.Files(j).Title, _
_maxLinkWidth, _
fldr.Files(j).TimeLastModified.ToShortDateString) & "’,’"_
& fldr.Files(j).Url & "’,’‘,’_self’,’_layouts/images/" & _
fldr.Files(j).IconUrl & "’);")
Next
Else
‘If not showing folders, delay writing out until all files
‘gathered, then sort all together.
End If
End Function
This code iterates through the Files collection of the current folder and writes a list of sort keys and associated indices to an array (delimited by CONST_SPLITCHAR so they may later be broken apart). Once I’ve written data for all the files to the array, I sort it so that the documents in the rendered TreeView will be sorted according to the order selected on the TreeView property sheet. Then I write out the JavaScript to create the TreeView nodes to the output stream. One twist occurs if I am not showing folders, in which case, the sort key and desired output are written to the colOutput collection to be sorted and written to the output stream later.
This same process is repeated (through recursion) for all subfolders of the root as described in the following section.
Step 5 – Displaying all Subfolders in the Root Folder
Any given folder, including the root, may have zero or more sub-folders. I want to display those using a folder icon, and allow the user to drill down to display any files or sub-folders under that folder. The following code shows how the ShowSortedFolders() helper function is called from the root level.
flCollection = site.GetFolder(dl.Title.Trim).SubFolders
ShowSortedFolders(flCollection, 1, thisNodeId, output, colOutput)
The parameters for the ShowSortedFolders() method are:
site.GetFolder(dl.Title.Trim).SubFolders – returns a collection of all sub-folders of the root folder
1 – is the level of the folder in the folder hierarchy, where 1=root
thisNodeId – is simply the node id of the root in our TreeView, in recursive calls to this function, this parameter will be replaced with the TreeView node id of the folder in which the sub-folders reside
output – is a reference to the web part’s Sytstem.Web.UI.HtmlTextWriter property
colOutput – is a reference to a collection variable used to buffer the output
Below is the code for this method with the comments removed:
Private Function ShowSortedFolders(ByVal fldrCol As SPFolderCollection, _
ByVal lvl As Integer, ByVal thisNodeId As Integer, _
ByVal output As System.Web.UI.HtmlTextWriter, _
ByVal colOutput As Collection)
Dim arrFldrSorted() As String
Dim i As Integer
Dim j As Integer
For i = 0 To fldrCol.Count – 1
ReDim Preserve arrFldrSorted(i)
arrFldrSorted(i) = fldrCol(i).Name & CONST_SPLITCHAR & i
Next
Array.Sort(arrFldrSorted)
For i = 0 To arrFldrSorted.Length – 1
j = arrFldrSorted(i).Split(CONST_SPLITCHAR)(1)
‘Don’t include forms library
If fldrCol(j).Name.ToLower <> "forms" Or lvl <> 1 Then
ShowFolderFiles(fldrCol(j), lvl, output, thisNodeId, colOutput)
End If
Next
End Function
You will notice that most of the processing is delegated to the ShowFolderFiles() method, which handles all the logic to add the appropriate nodes to the TreeView. This code could have been included in the ShowSortedFolders() method, but was extracted into a separate method for clarity.
One line of code you might be puzzled by is:
If fldrCol(j).Name.ToLower <> "forms" Or lvl <> 1 Then
SharePoint automatically adds a Forms folder when a doclib is created, so this folder needs to be explicitly excluded from the list of folders to process if we are at the root level (i.e. lvl = 1).
Now let’s look at the ShowFolderFiles() method which does the bulk of the work. For now, I want you to note the section that starts with:
If _folderLocation = EnumFolderLocation.Bottom Then
The two lines that follow this logical statement add nodes for the files and folders, respectively, to the TreeView . The call to the ShowSortedFolders() method is the recursive call that walks the hierarchy of folders. The conditional exists because the user may choose to display sub-folders at the top of a folder (as in Windows Explorer) or at the bottom (as does SharePoint).
Private Sub ShowFolderFiles(ByVal fl As SPFolder, ByVal lvl As Integer, _
ByVal output As System.Web.UI.HtmlTextWriter, _
ByVal parentNodeId As Integer, ByVal colOutput As Collection)
Dim sfl As SPFolder
Dim fi As SPFile
Dim thisNodeId As Integer = IIf(_showFolders, IncrNodeId(), parentNodeId)
If _showFolders Then
output.Write("d" & _treeViewId.ToString & ".add(" & thisNodeId & "," & _
parentNodeId & ",’" & fl.Name & "’,’" & fl.Url & _
"’,’‘,’‘,’_layouts/jtree/img/folder.gif’", _
"’_layouts/jtree/img/folderopen.gif’);")
End If
If _folderLocation = EnumFolderLocation.Bottom Then
ShowSortedFiles(fl, thisNodeId, output, colOutput)
ShowSortedFolders(fl.SubFolders, lvl + 1, thisNodeId, output, colOutput)
Else
ShowSortedFolders(fl.SubFolders, lvl + 1, thisNodeId, output, colOutput)
ShowSortedFiles(fl, thisNodeId, output, colOutput)
End If
End Sub
That’s really all there is to iterating through the document libraries, folders and files. Now let’s turn to the problem of formatting the output using the dtree TreeView routine.
Formatting the Output to Produce the TreeView
The DLTV is rendered in the user’s browser via JavaScript. The following outlines the basic process:
Include the dtree .js and .css files
Initialize the tree object in JavaScript
Add node objects to the tree object
Write out the tree
Note: Because there is an excellent document ( API.html ) that can be found in the Jtree folder, that describes the dtree API, I won’t cover it in this article.
In any web part, the code to render contents to the web part page, whether HTML or JavaScript, occurs in the RenderWebPart() method which overrides the method of the same name in the base Microsoft.SharePoint.WebPartPages.WebPart class. In effect, the DLTV web part is simply a JavaScript generator that inserts calls to the dtree.js library into the web part page.
Step 1 – Including References to the dTree Library and .css Files
The first step is to make sure the dtree.js library and its associated components are included in the page:
output.Write("<link rel=‘StyleSheet’ href=’_layouts/jtree/dtree.css’
type=‘text/css’ />")
output.Write("<script type=‘text/javascript’
src=’_layouts/jtree/dtree.js’></script>")
output.Write("<script type=‘text/javascript’>")
Note: During installation you placed the Jtree folder under [drive]:program filescommon filesMicrosoft sharedweb server extensions60TEMPLATELAYOUTS . Any web application components under this folder will be available as relative URLs within a SharePoint site by prefacing the reference with _layouts/ .
The output.Write statements appear throughout the code and are similar to the Respone.Write() statements used in typical ASP.NET programming. output refers to the System.Web.UI.HtmlTextWriter output stream that is used to write contents to the web part page. Note that in the third output statement I am opening a JavaScript tag. All subsequent output will be JavaScript within this <script> tag and the </script> tag that will be written at the end of the RenderWebPart() method.
Step 2 – Creating an Instance of the TreeView Object
The next line of code instantiates the TreeView object in JavaScript. The _treeViewId returns the value of the TreeView’s ClientId property, which is a unique value automatically generated by .NET for each web page control. Assigning this unique identifier to the TreeView allows multiple instances of the TreeView to coexist on the same web part page.
output.Write("d" & _treeViewId.ToString & " = new dTree(‘d" &
_treeViewId.ToString & "’);")
A small sample of the generated code looks something like this:
<link rel=‘StyleSheet’ href=’_layouts/jtree/dtree.css’ type=‘text/css’ />
<script type=‘text/javascript’ src=’_layouts/jtree/dtree.js’></script>
<script type=‘text/javascript’>
dLeft_g_213c6909_723c_4456_b02a_f3e58f132ea6 =
new dTree(‘dLeft_g_213c6909_723c_4456_b02a_f3e58f132ea6’);
dLeft_g_213c6909_723c_4456_b02a_f3e58f132ea6.config.useLines = true;
dLeft_g_213c6909_723c_4456_b02a_f3e58f132ea6.add(
1,-1,’‘,’‘,’‘,’‘,’_layouts/images/empty.gif’,’_layouts/images/empty.gif’);
Step 3 – Inserting Document Library Node if Multiple Libraries Displayed
The next section of code, shown below, checks to see if more than one document library will be displayed, if so it adds a root node for each document library to the tree. If there is only one document library specified in the DoclibName property, we skip over this code:
If _showFolders And IsMultipleDocs([DoclibName]) Then
thisNodeId = IncrNodeId()
output.Write("d" & _treeViewId.ToString & ".add(" & thisNodeId & "," & _
parentNodeId & ",’" & dl.Title.Trim & "’,’" & _
GetDoclibDefaultViewUrl(dl) & "’,’‘,’_self’,’" & _
dl.ImageUrl & "’,’" & dl.ImageUrl & "’);")
End If
The IncrNodeId() method simply returns the value of a global integer and increments it at the same time (a la i++ ). This is necessary because each node must have a unique id number.
Also in the above code are references to several properties of a SharePoint List object. These are self-evident, but one of the more interesting ones is ImageUrl , which returns the url of the image for the type of list (in our case a document library) referenced. By using this property, you can let SharePoint figure out what icon to use for this node of the tree.
Because I want the user to be able to click on the document library link to go to the associated default (usually allitems.aspx ) page for this library, I need a way to determine the url to that view. The following code does just that.
Private Function GetDoclibDefaultViewUrl(ByVal dl As SPList) As String
Dim i As Integer
Dim vw As SPView
For Each vw In dl.Views
If vw.DefaultView Then
Return vw.Url
End If
Next
Return ""
End Function
Step 4 – Inserting Nodes for each File in the Current Folder
As noted above, the ShowSortedFiles() method writes a TreeView nodes for each file in the folder. The following code from that routine does the work:
Array.Sort(arrFlSorted)
For i = 0 To arrFlSorted.Length – 1
j = arrFlSorted(i).Split(CONST_SPLITCHAR)(1)
output.Write("d" & _treeViewId.ToString & ".add(" & IncrNodeId() & "," & _
thisNodeId & ",’" & FormatTreeNode(fldr.Files(j).Name, _
fldr.Files(j).Title, _maxLinkWidth, _
fldr.Files(j).TimeLastModified.ToShortDateString) & "’,’" &_
fldr.Files(j).Url & "’,’‘,’_self’,’_layouts/images/" & _
fldr.Files(j).IconUrl & "’);")
Next
This is very similar to the statement to write a document library node. A few differences include:
FormatTreeNode() – is a helper function to format the node text based on the NodeFormat property
_maxLinkWidth – a parameter based on the MaxLinkWidth property
fldr.Files(j).IconUrl – a property, which returns the appropriate icon .gif url for the current document
Step 5 – Inserting Nodes for each Subfolder of the Current Folder
Finally, in the ShowFolderFiles() method, there is a variant of the above output statement to display a folder.
If _showFolders Then
output.Write("d" & _treeViewId.ToString & ".add(" & thisNodeId & "," & _
parentNodeId & ",’" & fl.Name & "’,’" & fl.Url & _
"’,’‘,’‘,’_layouts/jtree/img/folder.gif’," & _
"’_layouts/jtree/img/folderopen.gif’);")
End If
The only difference being that the folder icons are explicitly referenced as _layouts/jtree/img/folder.gif and _layouts/jtree/img/folderopen.gif .
If the ShowFolders property was set to False , the data for the file nodes was written to a global collection rather than directly to the output stream. This code appears at the bottom of the RenderWebPart() method:
If Not _showFolders Then
Dim arrSortValue(colOutput.Count – 1) As String
For i = 1 To colOutput.Count
arrSortValue(i – 1) = CType(colOutput.Item(i), _
String).Split(CONST_SPLITCHAR)(0) & _
CONST_SPLITCHAR & CType(colOutput.Item(i), _
String).Split(CONST_SPLITCHAR)(1)
Next
Array.Sort(arrSortValue)
For i = 0 To arrSortValue.Length – 1
j = arrSortValue(i).Split(CONST_SPLITCHAR)(1)
output.Write(CType(colOutput.Item(j + 1), _
String).Split(CONST_SPLITCHAR)(2))
Next
End If
Finally, I write out the JavaScript to display the TreeView, and close the <script> tag.
output.Write("document. write(d" & _treeViewId.ToString & ");")
output.Write("</script>")