Click here to Skip to main content
15,889,931 members
Articles / Programming Languages / XML

FolderTreeView Control

Rate me:
Please Sign up or sign in to vote.
4.87/5 (33 votes)
25 Oct 20023 min read 392.1K   5K   129   107
A simple explorer-like FolderTreeView control for C#

Sample Image

Introduction

This is an all-new version of the FolderTreeView control I posted here at CodeProject some weeks ago. The control now starts in the Desktop namespace, and a new drilling method has been added so the startup folder can be specified. Please note that this control is not intended to have all of the functionality of the actual Windows Explorer TreeView - it is a light-weight control designed for use in projects where you want to supply a treeview for folder navigation, without supporting windows shell extensions. If you are looking for a control that supports shell extensions, you should be looking at the excellent ËxplorerTreeControl submitted by Carlos H Perez here at the CodeProject website.

How It Works

After calling the InitFolderTreeView() method, a dummy Desktop note is created as the root node, and then the shell's Desktop namespace is iterated to populate the first level nodes. The child nodes are then iterated, checking only for the presence of sub-child nodes. If sub-child nodes are found, a dummy node is inserted so that the [+] will be displayed for folders that can be expanded. When the BeforeExpand event fires, the folder being expanded is checked for a dummy node. If a dummy is present, it is removed and the node's children are re-populated. If the node's children have already been populated, no further action occurs.

Usage

The FolderTreeView control is based on 3 classes:

  • FolderTreeView - The FolderTreeView implementation
  • ShellOperations - Supporting Shell Operations
  • ExtractIcons - Shell Icon Extractor

The control naturally derives from the System.Windows.Forms.TreeView, exposing 1 new property, GetSelectedNodePath() which returns the currently selected node's full path. There are 2 new methods: InitFolderTreeView() must be called to populate the TreeView - normally, you would call this in your Form's OnLoad event. The 2nd method is DrillToFolder(string folderPath) - this will recurse through the tree looking for the specified folder path, returning a boolean to indicate if the search was successful or not.

The method used to retrieve the icon for the Desktop root node works fine, but is perhaps not the best way to go about it. This control has NOT been tested in Win9x, NT or 2000 - feedback on these OSs would be much appreciated. Of course, if you improve this control, I would appreciate the update, and if you have any feedback to offer, please post it below.

Updates

Version 1.11

  • Updated the GetDesktopIcon() method so it returns the shell's small desktop icon rather than the large version
  • Added code so that the Desktop node would return the full desktop folder path

I have now tested the code on Windows Me without problem - feedback on how it works with other OSs would be appreciated!

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
Web Developer
Thailand Thailand
Furty will code for food.

Comments and Discussions

 
GeneralRe: Performance and Shell32.dll questions Pin
Jim Wiese (aka Spunk)15-Sep-03 5:17
Jim Wiese (aka Spunk)15-Sep-03 5:17 
GeneralRe: Performance and Shell32.dll questions Pin
Member 26118820-Sep-03 23:55
Member 26118820-Sep-03 23:55 
GeneralRe: Performance and Shell32.dll questions Pin
Jonathan Gauthier23-Sep-03 10:04
Jonathan Gauthier23-Sep-03 10:04 
GeneralRe: Performance and Shell32.dll questions Pin
Member 26118823-Sep-03 10:17
Member 26118823-Sep-03 10:17 
GeneralRe: Performance and Shell32.dll questions Pin
IndyJason791-Jan-05 21:46
IndyJason791-Jan-05 21:46 
GeneralDesign View Pin
JPark31-Jul-03 22:12
JPark31-Jul-03 22:12 
GeneralMistakes in: Getting the FolderItem... Pin
ittay ophir22-Jul-03 3:43
ittay ophir22-Jul-03 3:43 
GeneralGetting the FolderItem Object From the Folder Interface Pin
ittay ophir21-Jul-03 0:38
ittay ophir21-Jul-03 0:38 
Hi Furty

As far as I could see, no one gave the solution to the Folder --> FolderItem problem. The last I saw was the ParentFolder.Items loop.
Well, you where right, there is a shorter way, and it comes from using Shell32.dll version 5.0 or later on win-2000 & Millennium. (I see that the Interop.Shell32 you attached to the demo, is from this version).

So this is the function I added to the ShellOperations class in FolderTreeView.cs:
public static Shell32.FolderItem GetFolderItemFromFolder(Shell32.Folder folder)
{
 if(folder != null)
 {
  try
  {
   /*
    * GetComInterfaceForObject is a wraper for a set of Ole calls, including
    *  (IDispatch.)GetTypeInfo , (ITypeInfo.)GetContainingTypeLib, GetTypeAttr,
    *  GetRefTypeOfImplType, GetRefTypeInfo and so on...
    * Notice that the IntPtr is a CLR complient type, so no need to use "unsafe" code
    * and "fixed" directive.
    * */
   IntPtr fldPtr = <a target=_blank title='New Window' href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimeinteropservicesmarshalclassgetcominterfaceforobjecttopic.asp">Marshal.GetComInterfaceForObject</a>(folder, typeof(Shell32.Folder2));
   /*
    * GetObjectForIUnknown is the way to convert the code-safe pointer into
    * a .NET interop class (in this case, an interface).
    * */
   Shell32.Folder2 fldr2 = (Shell32.Folder2)<a target=_blank title='New Window' href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimeinteropservicesmarshalclassgetobjectforiunknowntopic.asp">Marshal.GetObjectForIUnknown</a>(fldPtr);
   /*
    * And, Walla!
    * */
   return <a target=_blank title='New Window' href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/objects/folder2/self.asp">fldr2.Self</a>;
  }
  catch{}
  return null;
 }
 return null;
}

REMEMBER: This method might return null, if you do not have the right Shell32 version.

Now, that I have this short-cut, I changed the way DrillTree works.

The first change is in the way I think about locating the Tree-Path. I say, instead of looking from the root, lets start from the leaf.

We’ll get the folder using Shell.NameSpace, and fill a list with the Folder we found, and all its’ parent folders.
Then we’ll iterate backward in the list and forward in the tree, until we have the right node.

This is made out of two functions:
DrillToFolderByShell, replaces the original DrillToFolder we have now.
DrillTreeByFolderList, is the recursive TreeNode seek, the DrillToFolderByShell uses.
Both function are implemented in the FolderTreeView class.

DrillToFolderByShell:
public bool DrillToFolderByShell(string folderPath)
{
   Shell32.Shell shell32 = new Shell32.ShellClass();
   /* Here we'll get the leaf folder. 
    * This will work for Net path and Mapped paths 
    * as well as for standard locals. */
   Shell32.Folder shell32Folder = shell32.NameSpace(folderPath);
   if(shell32Folder != null)
   {
    /* If we found it, we'll add this folder, and all its' Parent-Folders
     * to a list. The last item in this list will be the root folder. */
    ArrayList fullLst = new ArrayList();
    fullLst.Add(shell32Folder);
    Shell32.Folder par = shell32Folder.ParentFolder;
    while(par != null)
    {
     fullLst.Add(par);
     par = par.ParentFolder;
    }
    /* Now, that we have our road map, we can drill down. 
     * We'll start from the root list. */
    SelectedNode =  DrillTreeByFolderList(Nodes, fullLst);
    return SelectedNode != null;
   }
   else
    throw new DirectoryNotFoundException("\"" + folderPath + "\" Not found");
}


DrillTreeByFolderList
private TreeNode DrillTreeByFolderList(TreeNodeCollection tnLst, ArrayList folderList)
 {
   /* This is the recursive drilling.
    * For each call, we'll take the last folder 
    * (closest to the root) , and remove it from the list. */
   Shell32.Folder seekFolder = folderList[titleList.Count - 1] as Shell32.Folder;
   folderList.RemoveAt(titleList.Count - 1);

   string s1 = seekFolder.Title;
   /* Using the Folder.Title is a guessing game. 
    * If we can get the actual FolderItem.Name, we'll be 100% right. */
   Shell32.FolderItem seekFldItem = ShellOperations.GetFolderItemFromFolder(seekFolder);
   if(seekFldItem != null)
    s1 = seekFldItem.Name;

   foreach(TreeNode tn in tnLst)
   {
    Shell32.FolderItem curFolder = (Shell32.FolderItem)tn.Tag;
    string s2 = curFolder.Name;
    /* Case-Insensitive comparison tells us if we have the right
     * folder, and if we can drill on or stop.*/
    if((String.Compare(s1, s2, true) == 0))
    {
     tn.Expand();
     if(titleList.Count > 0)
      return DrillTreeByTitleList(tn.Nodes, titleList);
     else
      return tn;
    }
   }

   /* Originally, I had a fail safe code here, that uses 
    * the dfolder.ParentFolder.Items() search, but I think
    * this is only necessary for Shell32 earlier then version 5. */

   return null;
 }

And this is it.

P.S. .NET 1.1 includes the DirectoryDialogBox, and I think that the Shell32 controls are close (if not included already). So all of this might be purely educational at the end.



Ittay
GeneralRe: Getting the FolderItem Object From the Folder Interface Pin
Furty21-Jul-03 11:02
Furty21-Jul-03 11:02 
GeneralFolderTreeView lists the zip-files on my desktop Pin
Terje Krång10-Jun-03 3:54
Terje Krång10-Jun-03 3:54 
GeneralRe: FolderTreeView lists the zip-files on my desktop Pin
eidylon29-Aug-03 7:35
eidylon29-Aug-03 7:35 
GeneralRe: FolderTreeView lists the zip-files on my desktop Pin
Furty29-Aug-03 12:01
Furty29-Aug-03 12:01 
GeneralHi Furty Pin
cuteo20009-May-03 13:36
cuteo20009-May-03 13:36 
GeneralRe: Hi Furty Pin
Jim Wiese (aka Spunk)8-Jul-03 13:09
Jim Wiese (aka Spunk)8-Jul-03 13:09 
GeneralRe: Hi Furty Pin
tunt5-Nov-03 16:47
tunt5-Nov-03 16:47 
GeneralRe: Hi Furty Pin
Furty6-Nov-03 12:23
Furty6-Nov-03 12:23 
GeneralCool tool Pin
FootFunk2-May-03 9:21
FootFunk2-May-03 9:21 
QuestionCould anyone give me a link to similar control in win32 or WTL ? Pin
Ilushka20-Feb-03 22:46
Ilushka20-Feb-03 22:46 
Questionicons have black shadows? Pin
scottfm7-Feb-03 14:25
scottfm7-Feb-03 14:25 
AnswerRe: icons have black shadows? Pin
Furty8-Feb-03 3:51
Furty8-Feb-03 3:51 
GeneralRe: icons have black shadows? Pin
mingot19-Mar-03 16:15
mingot19-Mar-03 16:15 
GeneralRe: icons have black shadows? Pin
Marc Clifton27-May-03 6:35
mvaMarc Clifton27-May-03 6:35 
GeneralHidden folders Pin
Scott Lee24-Jan-03 3:58
Scott Lee24-Jan-03 3:58 
GeneralRe: Hidden folders Pin
Tagsmas6-Jan-04 1:59
Tagsmas6-Jan-04 1:59 
AnswerRe: Hidden folders [modified] Pin
Jos Branders31-Oct-09 5:25
Jos Branders31-Oct-09 5:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.