在C#中浏览目录

我如何向用户展示一个控件,让他/她select一个目录?

似乎没有任何原生的.net控件这样做?

FolderBrowserDialog类是最好的select。

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

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

注意:不能保证此代码将在.Net框架的将来版本中工作。 使用私有的.Net框架内部结构通过reflection在这里完成可能不是很好的整体。 使用底部提到的互操作解决scheme,因为Windows API不太可能改变。

如果您正在寻找一个类似于Windows 7对话框的文件夹select器,可以从底部的文本框和左侧的导航窗格中复制和粘贴collections夹和常用位置,然后您就可以访问在一个非常轻量级的方式。

FolderBrowserDialog UI非常小:

在这里输入图像说明

但是你可以改为:

在这里输入图像说明

这里有一个类,它使用.Net私有的IFileDialog接口打开一个Vista风格的文件夹select器,而不是直接在代码中使用互操作(.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的Bill Seddon(我没有从属关系)的.NET Win 7样式文件夹select对话框的清理版本。 我写了我自己的,因为他的解决scheme需要一个额外的Reflection类,这是不需要这个重点的目的,使用基于exception的stream量控制,不caching其reflection调用的结果。 请注意,嵌套静态VistaDialog类是这样的,如果Show方法从不调用,它的静态reflectionvariables不会尝试填充。

它在Windows窗体中的使用方式如下:

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

你当然可以玩弄它的select和它暴露的属性。 例如,它允许在Vista风格的对话框中多选。

此外,请注意, Simon Mourier给出了一个答案 ,显示了如何使用互操作对Windows API进行完全相同的工作,尽pipe如果在旧版本的Windows中,他的版本将不得不补充使用旧式对话框。 不幸的是,当我完成我的解决scheme时,我还没有find他的职位。 命名你的毒药!

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

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

对于比FolderBrowserdialog更多的function,如过滤,checkbox等,看看第三方控制像壳牌MegaPack 。 由于它们是控件,因此它们可以放在自己的窗体中,而不是作为modal dialog出现。