2008-08-14 168 views

回答

0

您可以将TreeView与DirectoryInfo类组合使用。

5

您可以使用System.Windows.Forms命名空间中的FolderBrowserDialog类。

+0

-1 Dup http://stackoverflow.com/a/11775/11635 – 2013-07-09 09:19:47

1

请不要尝试使用TreeView/DirectoryInfo类自己推出。首先,通过使用SHBrowseForFolder,您可以免费获得许多不错的功能(图标/右键单击/网络)。对于另一个有边缘情况/捕获,你可能不会知道。

0

要获得比FolderBrowserdialog更多的功能,比如过滤,复选框等,请查看Shell MegaPack等第三方控件。 由于它们是控件,所以它们可以放在自己的窗体中,而不是作为模态对话框出现。

+0

好主意,如果选择等是必需的。 – 2010-04-19 22:45:18

71
string folderPath = ""; 
FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog(); 
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) { 
    folderPath = folderBrowserDialog1.SelectedPath ; 
} 
+3

不要忘记包装在使用 使用(FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog()) – 2015-09-02 05:39:09

7

注:不保证此代码将在.NET Framework的未来版本。像这里通过反射一样使用私有的.Net框架内部结构可能不是很好。使用底部提到的互操作解决方案,因为Windows API不太可能改变。

如果你正在寻找一个文件夹选择器,看起来更像是Windows 7的对话框中,用从一个文本框底部和导航窗格中留下的最爱,常用位置复制和粘贴的能力,那么你可以以一种非常轻量级的方式访问它。

的的FolderBrowserDialog UI是很小的:

enter image description here

但你可以有这个代替:

enter image description here

下面是使用打开Vista风格的文件夹选择器类。网络私人IFileDialog接口,没有直接在代码中使用互操作(.Net为你照顾)。如果没有足够高的Windows版本,它会回到Vista之前的对话框。应该在Windows 7,8,9,10及更高版本(理论上)中工作。

using System; 
using System.Reflection; 
using System.Windows.Forms; 

namespace MyCoolCompany.Shuriken { 
    /// <summary> 
    /// Present the Windows Vista-style open file dialog to select a folder. Fall back for older Windows Versions 
    /// </summary> 
    public class FolderSelectDialog { 
     private string _initialDirectory; 
     private string _title; 
     private string _fileName = ""; 

     public string InitialDirectory { 
      get { return string.IsNullOrEmpty(_initialDirectory) ? Environment.CurrentDirectory : _initialDirectory; } 
      set { _initialDirectory = value; } 
     } 
     public string Title { 
      get { return _title ?? "Select a folder"; } 
      set { _title = value; } 
     } 
     public string FileName { get { return _fileName; } } 

     public bool Show() { return Show(IntPtr.Zero); } 

     /// <param name="hWndOwner">Handle of the control or window to be the parent of the file dialog</param> 
     /// <returns>true if the user clicks OK</returns> 
     public bool Show(IntPtr hWndOwner) { 
      var result = Environment.OSVersion.Version.Major >= 6 
       ? VistaDialog.Show(hWndOwner, InitialDirectory, Title) 
       : ShowXpDialog(hWndOwner, InitialDirectory, Title); 
      _fileName = result.FileName; 
      return result.Result; 
     } 

     private struct ShowDialogResult { 
      public bool Result { get; set; } 
      public string FileName { get; set; } 
     } 

     private static ShowDialogResult ShowXpDialog(IntPtr ownerHandle, string initialDirectory, string title) { 
      var folderBrowserDialog = new FolderBrowserDialog { 
       Description = title, 
       SelectedPath = initialDirectory, 
       ShowNewFolderButton = false 
      }; 
      var dialogResult = new ShowDialogResult(); 
      if (folderBrowserDialog.ShowDialog(new WindowWrapper(ownerHandle)) == DialogResult.OK) { 
       dialogResult.Result = true; 
       dialogResult.FileName = folderBrowserDialog.SelectedPath; 
      } 
      return dialogResult; 
     } 

     private static class VistaDialog { 
      private const string c_foldersFilter = "Folders|\n"; 

      private const BindingFlags c_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 
      private readonly static Assembly s_windowsFormsAssembly = typeof(FileDialog).Assembly; 
      private readonly static Type s_iFileDialogType = s_windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog"); 
      private readonly static MethodInfo s_createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", c_flags); 
      private readonly static MethodInfo s_onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", c_flags); 
      private readonly static MethodInfo s_getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", c_flags); 
      private readonly static MethodInfo s_setOptionsMethodInfo = s_iFileDialogType.GetMethod("SetOptions", c_flags); 
      private readonly static uint s_fosPickFoldersBitFlag = (uint) s_windowsFormsAssembly 
       .GetType("System.Windows.Forms.FileDialogNative+FOS") 
       .GetField("FOS_PICKFOLDERS") 
       .GetValue(null); 
      private readonly static ConstructorInfo s_vistaDialogEventsConstructorInfo = s_windowsFormsAssembly 
       .GetType("System.Windows.Forms.FileDialog+VistaDialogEvents") 
       .GetConstructor(c_flags, null, new[] { typeof(FileDialog) }, null); 
      private readonly static MethodInfo s_adviseMethodInfo = s_iFileDialogType.GetMethod("Advise"); 
      private readonly static MethodInfo s_unAdviseMethodInfo = s_iFileDialogType.GetMethod("Unadvise"); 
      private readonly static MethodInfo s_showMethodInfo = s_iFileDialogType.GetMethod("Show"); 

      public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory, string title) { 
       var openFileDialog = new OpenFileDialog { 
        AddExtension = false, 
        CheckFileExists = false, 
        DereferenceLinks = true, 
        Filter = c_foldersFilter, 
        InitialDirectory = initialDirectory, 
        Multiselect = false, 
        Title = title 
       }; 

       var iFileDialog = s_createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { }); 
       s_onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog }); 
       s_setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint) s_getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | s_fosPickFoldersBitFlag }); 
       var adviseParametersWithOutputConnectionToken = new[] { s_vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U }; 
       s_adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken); 

       try { 
        int retVal = (int) s_showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle }); 
        return new ShowDialogResult { 
         Result = retVal == 0, 
         FileName = openFileDialog.FileName 
        }; 
       } 
       finally { 
        s_unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] }); 
       } 
      } 
     } 

     // Wrap an IWin32Window around an IntPtr 
     private class WindowWrapper : IWin32Window { 
      private readonly IntPtr _handle; 
      public WindowWrapper(IntPtr handle) { _handle = handle; } 
      public IntPtr Handle { get { return _handle; } } 
     } 
    } 
} 

我开发了这个如由lyquidity.com比尔·塞登(我有没有隶属关系)的.NET Win 7-style folder select dialog一个清理版本。我写了我自己的,因为他的解决方案需要一个额外的Reflection类,这个重点目标不需要,使用基于异常的流控制,不缓存反射调用的结果。请注意,如果从未调用Show方法,则嵌套静态VistaDialog类会使其静态反射变量不尝试填充。

它在Windows窗体中使用像这样:

var dialog = new FolderSelectDialog { 
    InitialDirectory = musicFolderTextBox.Text, 
    Title = "Select a folder to import music from" 
}; 
if (dialog.Show(Handle)) { 
    musicFolderTextBox.Text = dialog.FileName; 
} 

当然,你可以玩弄它的选择和哪些属性它公开。例如,它允许在Vista风格的对话框中多选。

另外,请注意,Simon Mourier gave an answer显示了如何直接使用与Windows API互操作完成相同的作业,但是如果在较旧版本的Windows中,则必须补充其版本才能使用旧式对话框。不幸的是,当我制定解决方案时,我还没有找到他的职位。命名你的毒药!