2008-08-14 131 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中,則必須補充其版本才能使用舊式對話框。不幸的是,當我制定解決方案時,我還沒有找到他的職位。命名你的毒藥!