如何配置OpenFileDialog以选择文件夹?

时间:2022-09-03 19:50:07

In VS .NET, when you are selecting a folder for a project, a dialog that looks like an OpenFileDialog or SaveFileDialog is displayed, but is set up to accept only folders. Ever since I've seen this I've wanted to know how it's done. I am aware of the FolderBrowserDialog, but I've never really liked that dialog. It starts too small and doesn't let me take advantage of being able to type a path.

在VS . net中,当您为一个项目选择一个文件夹时,将显示一个类似于OpenFileDialog或SaveFileDialog的对话框,但设置为只接受文件夹。自从我看到这个,我就想知道它是怎么做的。我知道FolderBrowserDialog,但是我从来都不喜欢这个对话。它开始时太小,不能让我利用能够键入路径的优势。

I'm almost certain by now there's not a way to do this from .NET, but I'm just as curious how you do it from unmanaged code as well. Short of completely reimplementing the dialog from scratch, how do you modify the dialog to have this behavior?

我几乎可以肯定,现在还没有从。net中实现这一点的方法,但我同样好奇的是,如何从非托管代码中实现这一点。如果没有完全从头重新实现该对话框,如何修改该对话框以实现此行为?

I'd also like to restate that I am aware of the FolderBrowserDialog but sometimes I don't like to use it, in addition to being genuinely curious how to configure a dialog in this manner. Telling me to just use the FolderBrowserDialog helps me maintain a consistent UI experience but doesn't satisfy my curiosity so it won't count as an answer.

我还想重申,我知道FolderBrowserDialog,但有时我不喜欢使用它,除了真正好奇如何以这种方式配置对话框之外。告诉我只使用FolderBrowserDialog可以帮助我保持一致的UI体验,但是不能满足我的好奇心,所以它不能算作一个答案。

It's not a Vista-specific thing either; I've been seeing this dialog since VS .NET 2003, so it is doable in Win2k and WinXP. This is less of a "I want to know the proper way to do this" question and more of a "I have been curious about this since I first wanted to do it in VS 2003" question. I understand that Vista's file dialog has an option to do this, but it's been working in XP so I know they did something to get it to work. Vista-specific answers are not answers, because Vista doesn't exist in the question context.

它也不是一个特定于病毒的东西;自从2003年VS . net以来,我就一直在看这个对话框,所以它在Win2k和WinXP中是可行的。这不是一个“我想知道正确的解决方法”的问题,而是一个“自从我在2003年VS . 2003年第一次想做这个问题以来,我一直对这个问题感到好奇”的问题。我知道Vista的文件对话框有这样的选项,但它一直在使用XP,所以我知道他们做了一些事情让它工作。特定于Vista的答案不是答案,因为Vista并不存在于问题环境中。

Update: I'm accepting Scott Wisniewski's answer because it comes with a working sample, but I think Serge deserves credit for pointing to the dialog customization (which is admittedly nasty from .NET but it does work) and Mark Ransom for figuring out that MS probably rolled a custom dialog for this task.

更新:我接受斯科特Wisniewski的回答,因为它有一个工作示例中,但是我认为应该承认哔叽指向自定义的对话框(这是不可否认的。net但它确实工作)和马克赎金找出女士可能滚这个任务的自定义对话框。

16 个解决方案

#1


53  

I have a dialog that I wrote called an OpenFileOrFolder dialog that allows you to open either a folder or a file.

我编写了一个名为OpenFileOrFolder的对话框,允许您打开文件夹或文件。

If you set its AcceptFiles value to false, then it operates in only accept folder mode.

如果您将它的AcceptFiles值设置为false,那么它将只使用accept文件夹模式。

You can download the source from GitHub here

您可以在这里从GitHub下载源代码

#2


46  

There is the Windows API Code Pack. It's got a lot of shell related stuff, including the CommonOpenFileDialog class (in the Microsoft.WindowsAPICodePack.Dialogs namespace). This is the perfect solution - the usual open dialog with only folders displayed.

有Windows API代码包。它有很多shell相关的东西,包括CommonOpenFileDialog类(在Microsoft.WindowsAPICodePack中)。对话框的名称空间)。这是一个完美的解决方案——通常只显示文件夹的打开对话框。

Here is an example of how to use it:

这里有一个如何使用它的例子:

CommonOpenFileDialog cofd = new CommonOpenFileDialog();
cofd.IsFolderPicker = true;
cofd.ShowDialog();

Unfortunately Microsoft no longer ships this package, but several people have unofficially uploaded binaries to NuGet. One example can be found here. This package is just the shell-specific stuff. Should you need it, the same user has several other packages which offer more functionality present in the original package.

不幸的是,微软不再提供这个包,但是一些人已经非正式地将二进制文件上传到NuGet。这里有一个例子。这个包只是特定于shell的东西。如果您需要它,相同的用户有其他几个包,它们在原始包中提供了更多的功能。

#3


45  

You can use FolderBrowserDialogEx - a re-usable derivative of the built-in FolderBrowserDialog. This one allows you to type in a path, even a UNC path. You can also browse for computers or printers with it. Works just like the built-in FBD, but ... better.

您可以使用FolderBrowserDialogEx -一个可重用的内置FolderBrowserDialog的衍生版本。这个允许你输入路径,甚至UNC路径。你也可以用它浏览电脑或打印机。就像内置的FBD一样,但是…更好。

(EDIT: I should have pointed out that this dialog can be set to select files or folders. )

(编辑:我应该指出这个对话框可以设置为选择文件或文件夹)

Full Source code (one short C# module). Free. MS-Public license.

完整的源代码(一个简短的c#模块)。免费的。微软公开许可。

Code to use it:

代码使用它:

var dlg1 = new Ionic.Utils.FolderBrowserDialogEx();
dlg1.Description = "Select a folder to extract to:";
dlg1.ShowNewFolderButton = true;
dlg1.ShowEditBox = true;
//dlg1.NewStyle = false;
dlg1.SelectedPath = txtExtractDirectory.Text;
dlg1.ShowFullPathInEditBox = true;
dlg1.RootFolder = System.Environment.SpecialFolder.MyComputer;

// Show the FolderBrowserDialog.
DialogResult result = dlg1.ShowDialog();
if (result == DialogResult.OK)
{
    txtExtractDirectory.Text = dlg1.SelectedPath;
}

#4


32  

The Ookii.Dialogs package contains a managed wrapper around the new (Vista-style) folder browser dialog. It also degrades gracefully on older operating systems.

Ookii。对话框包包含一个管理包装,围绕新的(Vista-style)文件夹浏览器对话框。它还可以优雅地降级旧操作系统。

#5


27  

Better to use the FolderBrowserDialog for that.

最好使用FolderBrowserDialog。

using (FolderBrowserDialog dlg = new FolderBrowserDialog())
{
    dlg.Description = "Select a folder";
    if (dlg.ShowDialog() == DialogResult.OK)
    {
        MessageBox.Show("You selected: " + dlg.SelectedPath);
    }
}

#6


23  

After hours of searching I found this answer by leetNightShade to a working solution.

经过数小时的搜寻之后,我找到了这个答案。

There are three things I believe make this solution much better than all the others.

我认为有三件事比其他的事情更能解决这个问题。

  1. It is simple to use. It only requires you include two files (which can be combined to one anyway) in your project.
  2. 使用起来很简单。它只需要在项目中包含两个文件(无论如何都可以合并到一个)。
  3. It falls back to the standard FolderBrowserDialog when used on XP or older systems.
  4. 当在XP或旧系统上使用时,它会返回到标准的FolderBrowserDialog。
  5. The author grants permission to use the code for any purpose you deem fit.

    There’s no license as such as you are free to take and do with the code what you will.

    没有像您这样的许可,您可以*地使用这些代码,做您想做的事情。

Download the code here.

在这里下载代码。

#7


17  

OK, let me try to connect the first dot ;-) Playing a little bit with Spy++ or Winspector shows that the Folder textbox in the VS Project Location is a customization of the standard dialog. It's not the same field as the filename textbox in a standard file dialog such as the one in Notepad.

好的,让我试着连接第一个点;-)使用Spy++或Winspector播放一下,显示VS项目位置中的文件夹文本框是标准对话框的定制。它与标准文件对话框中的文件名文本框(如记事本中的文本框)不同。

From there on, I figure, VS hides the filename and filetype textboxes/comboboxes and uses a custom dialog template to add its own part in the bottom of the dialog.

从这里,我想,VS隐藏文件名和filetype文本框/组合框,并使用自定义对话框模板在对话框底部添加自己的部分。

EDIT: Here's an example of such customization and how to do it (in Win32. not .NET):

编辑:这里有一个这样定制的例子以及如何做(在Win32中)。没有。net):

m_ofn is the OPENFILENAME struct that underlies the file dialog. Add these 2 lines:

m_ofn是文件对话框下面的OPENFILENAME结构。把这两条线:

  m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEDIALOG_IMPORTXLIFF);
  m_ofn.Flags |= OFN_ENABLETEMPLATE;

where IDD_FILEDIALOG_IMPORTXLIFF is a custom dialog template that will be added in the bottom of the dialog. See the part in red below. alt text http://apptranslator.com/_so/customizedfiledialog.png

IDD_FILEDIALOG_IMPORTXLIFF是一个自定义对话框模板,它将被添加到对话框的底部。见下面红色部分。alt文本http://apptranslator.com/_so/customizedfiledialog.png

In this case, the customized part is only a label + an hyperlink but it could be any dialog. It could contain an OK button that would let us validate folder only selection.

在这种情况下,定制部分只是一个标签+一个超链接,但它可以是任何对话框。它可以包含一个OK按钮,让我们只验证文件夹的选择。

But how we would get rid of some of the controls in the standard part of the dialog, I don't know.

但是我们如何去掉对话框标准部分的一些控件,我不知道。

More detail in this MSDN article.

更多细节见这篇MSDN文章。

#8


17  

Exact Audio Copy works this way on Windows XP. The standard file open dialog is shown, but the filename field contains the text "Filename will be ignored".

在Windows XP上,准确的音频拷贝就是这样工作的。标准文件打开对话框显示,但文件名字段包含文本“文件名将被忽略”。

Just guessing here, but I suspect the string is injected into the combo box edit control every time a significant change is made to the dialog. As long as the field isn't blank, and the dialog flags are set to not check the existence of the file, the dialog can be closed normally.

我只是猜测一下,但是我怀疑每次对对话框进行重大更改时,字符串都会被注入到组合框编辑控件中。只要字段不是空的,并且对话框标志被设置为不检查文件的存在,对话框就可以正常关闭。

Edit: this is much easier than I thought. Here's the code in C++/MFC, you can translate it to the environment of your choice.

编辑:这比我想象的要容易得多。这是c++ /MFC中的代码,您可以将其转换为您所选择的环境。

CFileDialog dlg(true, NULL, "Filename will be ignored", OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_PATHMUSTEXIST | OFN_READONLY, NULL, this);
dlg.DoModal();

Edit 2: This should be the translation to C#, but I'm not fluent in C# so don't shoot me if it doesn't work.

编辑2:这应该是对c#的翻译,但是我的c#不太流利,所以如果不行就不要开枪。

OpenFileDialog openFileDialog1 = new OpenFileDialog();

openFileDialog1.FileName = "Filename will be ignored";
openFileDialog1.CheckPathExists = true;
openFileDialog1.ShowReadOnly = false;
openFileDialog1.ReadOnlyChecked = true;
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;

if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
    // openFileDialog1.FileName should contain the folder and a dummy filename
}

Edit 3: Finally looked at the actual dialog in question, in Visual Studio 2005 (I didn't have access to it earlier). It is not the standard file open dialog! If you inspect the windows in Spy++ and compare them to a standard file open, you'll see that the structure and class names don't match. When you look closely, you can also spot some differences between the contents of the dialogs. My conclusion is that Microsoft completely replaced the standard dialog in Visual Studio to give it this capability. My solution or something similar will be as close as you can get, unless you're willing to code your own from scratch.

编辑3:最终在Visual Studio 2005中查看了所讨论的实际对话框(我之前没有访问过它)。这不是标准的文件打开对话框!如果您查看Spy++ +中的窗口并将它们与打开的标准文件进行比较,您将看到结构和类名不匹配。当您仔细观察时,您还可以发现对话框的内容之间的一些差异。我的结论是,微软完全取代了Visual Studio中的标准对话框,为其提供了这种功能。我的解决方案或类似的东西将尽可能接近,除非您愿意从头开始编写自己的代码。

#9


10  

You can subclass the file dialog and gain access to all its controls. Each has an identifier that can be used to obtain its window handle. You can then show and hide them, get messages from them about selection changes etc. etc. It all depends how much effort you want to take.

您可以对file对话框进行子类化,并获得对其所有控件的访问权限。每个窗口都有一个可以用来获取窗口句柄的标识符。然后你可以显示和隐藏它们,从它们那里得到关于选择变化的信息等等。这一切都取决于你想要付出多少努力。

We did ours using WTL class support and customized the file dialog to include a custom places bar and plug-in COM views.

我们使用WTL类支持并定制了文件对话框,以包含自定义位置栏和插件COM视图。

MSDN provides information on how to do this using Win32, this CodeProject article includes an example, and this CodeProject article provides a .NET example.

MSDN提供了关于如何使用Win32进行此操作的信息,本文的CodeProject包含一个示例,本文的CodeProject提供了一个。net示例。

#10


9  

You can use code like this

您可以使用这样的代码

  • The filter is hide files
  • 过滤器是隐藏文件。
  • The filename is hide first text
  • 文件名隐藏第一个文本

To advanced hide of textbox for filename you need to look at OpenFileDialogEx

要高级隐藏文件名的文本框,需要查看OpenFileDialogEx

The code:

代码:

{
    openFileDialog2.FileName = "\r";
    openFileDialog1.Filter = "folders|*.neverseenthisfile";
    openFileDialog1.CheckFileExists = false;
    openFileDialog1.CheckPathExists = false;
}

#11


5  

I assume you're on Vista using VS2008? In that case I think that the FOS_PICKFOLDERS option is being used when calling the Vista file dialog IFileDialog. I'm afraid that in .NET code this would involve plenty of gnarly P/Invoke interop code to get working.

我想你使用的是Vista VS2008?在这种情况下,我认为在调用Vista文件对话框IFileDialog时将使用FOS_PICKFOLDERS选项。我担心在。net代码中,这将涉及大量的复杂的P/调用互操作代码。

#12


2  

First Solution

第一个解决方案

I developed this as a cleaned up version of .NET Win 7-style folder select dialog by Bill Seddon of lyquidity.com (I have no affiliation). (I learned of his code from another answer on this page). I wrote my own because his solution requires an additional Reflection class that isn't needed for this focused purpose, uses exception-based flow control, doesn't cache the results of its reflection calls. Note that the nested static VistaDialog class is so that its static reflection variables don't try to get populated if the Show method is never called. It falls back to the pre-Vista dialog if not in a high enough Windows version. Should work in Windows 7, 8, 9, 10 and higher (theoretically).

我开发这是一个清理版。net Win 7风格的文件夹选择对话框,由lyquidity.com的Bill Seddon(我没有隶属关系)。(我是从本页上的另一个答案得知他的密码的。)我编写了自己的解决方案,因为他的解决方案需要一个额外的反射类,而这个反射类不需要用于这个目的,它使用基于异常的流控制,不缓存反射调用的结果。注意,嵌套的静态VistaDialog类是为了在从未调用Show方法时不尝试填充它的静态反射变量。如果不是在足够高的Windows版本中,它会回到vista前的对话框。应该适用于Windows 7、8、9、10或更高版本(理论上)。

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

namespace ErikE.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; } }
        }
    }
}

It is used like so in a Windows Form:

在Windows窗体中是这样使用的:

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

You can of course play around with its options and what properties it exposes. For example, it allows multiselect in the Vista-style dialog.

当然,您可以使用它的选项和它公开的属性。例如,它允许在vista风格的对话框中进行多选择。

Second Solution

第二个解决方案

Simon Mourier gave an answer that shows how to do the exact same job using interop against the Windows API directly, though his version would have to be supplemented to use the older style dialog if in an older version of Windows. Unfortunately, I hadn't found his post yet when I worked up my solution. Name your poison!

Simon Mourier给出了一个答案,它展示了如何在Windows API上直接使用interop来完成同样的工作,但是如果在旧版本的Windows中,他的版本还需要使用旧的样式对话框。不幸的是,当我想出我的解决方案时,我还没有找到他的职位。名字你的毒药!

#13


1  

Try this one from Codeproject (credit to Nitron):

试试这个来自Codeproject(信用到Nitron)的方法:

I think it's the same dialog you're talking about - maybe it would help if you add a screenshot?

我想这和你说的是同一个对话框——如果你添加一个截图会有帮助吗?

bool GetFolder(std::string& folderpath, const char* szCaption=NULL, HWND hOwner=NULL)
{
    bool retVal = false;

    // The BROWSEINFO struct tells the shell how it should display the dialog.
    BROWSEINFO bi;
    memset(&bi, 0, sizeof(bi));

    bi.ulFlags   = BIF_USENEWUI;
    bi.hwndOwner = hOwner;
    bi.lpszTitle = szCaption;

    // must call this if using BIF_USENEWUI
    ::OleInitialize(NULL);

    // Show the dialog and get the itemIDList for the selected folder.
    LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);

    if(pIDL != NULL)
    {
        // Create a buffer to store the path, then get the path.
        char buffer[_MAX_PATH] = {'\0'};
        if(::SHGetPathFromIDList(pIDL, buffer) != 0)
        {
            // Set the string value.
            folderpath = buffer;
            retVal = true;
        }       

        // free the item id list
        CoTaskMemFree(pIDL);
    }

    ::OleUninitialize();

    return retVal;
}

#14


1  

On Vista you can use IFileDialog with FOS_PICKFOLDERS option set. That will cause display of OpenFileDialog-like window where you can select folders:

在Vista中,你可以使用带有FOS_PICKFOLDERS选项设置的IFileDialog。这将导致openfiledialog类窗口的显示,你可以在其中选择文件夹:

var frm = (IFileDialog)(new FileOpenDialogRCW());
uint options;
frm.GetOptions(out options);
options |= FOS_PICKFOLDERS;
frm.SetOptions(options);

if (frm.Show(owner.Handle) == S_OK) {
    IShellItem shellItem;
    frm.GetResult(out shellItem);
    IntPtr pszString;
    shellItem.GetDisplayName(SIGDN_FILESYSPATH, out pszString);
    this.Folder = Marshal.PtrToStringAuto(pszString);
}

For older Windows you can always resort to trick with selecting any file in folder.

对于较老的Windows,您可以选择在文件夹中选择任何文件。

Working example that works on .NET Framework 2.0 and later can be found here.

可以在这里找到在。net Framework 2.0和以后工作的示例。

#15


1  

You can use code like this

您可以使用这样的代码

The filter is empty string. The filename is AnyName but not blank

过滤器是空字符串。文件名是任何名称,但不是空白

        openFileDialog.FileName = "AnyFile";
        openFileDialog.Filter = string.Empty;
        openFileDialog.CheckFileExists = false;
        openFileDialog.CheckPathExists = false;

#16


0  

I know the question was on configuration of OpenFileDialog but seeing that Google brought me here i may as well point out that if you are ONLY looking for folders you should be using a FolderBrowserDialog Instead as answered by another SO question below

我知道这个问题是关于OpenFileDialog的配置的,但是看到谷歌把我带到了这里,我也可以指出,如果你只是在寻找文件夹,你应该使用FolderBrowserDialog,而不是下面另一个SO问题的答案

How to specify path using open file dialog in vb.net?

如何使用vb.net中的打开文件对话框指定路径?

#1


53  

I have a dialog that I wrote called an OpenFileOrFolder dialog that allows you to open either a folder or a file.

我编写了一个名为OpenFileOrFolder的对话框,允许您打开文件夹或文件。

If you set its AcceptFiles value to false, then it operates in only accept folder mode.

如果您将它的AcceptFiles值设置为false,那么它将只使用accept文件夹模式。

You can download the source from GitHub here

您可以在这里从GitHub下载源代码

#2


46  

There is the Windows API Code Pack. It's got a lot of shell related stuff, including the CommonOpenFileDialog class (in the Microsoft.WindowsAPICodePack.Dialogs namespace). This is the perfect solution - the usual open dialog with only folders displayed.

有Windows API代码包。它有很多shell相关的东西,包括CommonOpenFileDialog类(在Microsoft.WindowsAPICodePack中)。对话框的名称空间)。这是一个完美的解决方案——通常只显示文件夹的打开对话框。

Here is an example of how to use it:

这里有一个如何使用它的例子:

CommonOpenFileDialog cofd = new CommonOpenFileDialog();
cofd.IsFolderPicker = true;
cofd.ShowDialog();

Unfortunately Microsoft no longer ships this package, but several people have unofficially uploaded binaries to NuGet. One example can be found here. This package is just the shell-specific stuff. Should you need it, the same user has several other packages which offer more functionality present in the original package.

不幸的是,微软不再提供这个包,但是一些人已经非正式地将二进制文件上传到NuGet。这里有一个例子。这个包只是特定于shell的东西。如果您需要它,相同的用户有其他几个包,它们在原始包中提供了更多的功能。

#3


45  

You can use FolderBrowserDialogEx - a re-usable derivative of the built-in FolderBrowserDialog. This one allows you to type in a path, even a UNC path. You can also browse for computers or printers with it. Works just like the built-in FBD, but ... better.

您可以使用FolderBrowserDialogEx -一个可重用的内置FolderBrowserDialog的衍生版本。这个允许你输入路径,甚至UNC路径。你也可以用它浏览电脑或打印机。就像内置的FBD一样,但是…更好。

(EDIT: I should have pointed out that this dialog can be set to select files or folders. )

(编辑:我应该指出这个对话框可以设置为选择文件或文件夹)

Full Source code (one short C# module). Free. MS-Public license.

完整的源代码(一个简短的c#模块)。免费的。微软公开许可。

Code to use it:

代码使用它:

var dlg1 = new Ionic.Utils.FolderBrowserDialogEx();
dlg1.Description = "Select a folder to extract to:";
dlg1.ShowNewFolderButton = true;
dlg1.ShowEditBox = true;
//dlg1.NewStyle = false;
dlg1.SelectedPath = txtExtractDirectory.Text;
dlg1.ShowFullPathInEditBox = true;
dlg1.RootFolder = System.Environment.SpecialFolder.MyComputer;

// Show the FolderBrowserDialog.
DialogResult result = dlg1.ShowDialog();
if (result == DialogResult.OK)
{
    txtExtractDirectory.Text = dlg1.SelectedPath;
}

#4


32  

The Ookii.Dialogs package contains a managed wrapper around the new (Vista-style) folder browser dialog. It also degrades gracefully on older operating systems.

Ookii。对话框包包含一个管理包装,围绕新的(Vista-style)文件夹浏览器对话框。它还可以优雅地降级旧操作系统。

#5


27  

Better to use the FolderBrowserDialog for that.

最好使用FolderBrowserDialog。

using (FolderBrowserDialog dlg = new FolderBrowserDialog())
{
    dlg.Description = "Select a folder";
    if (dlg.ShowDialog() == DialogResult.OK)
    {
        MessageBox.Show("You selected: " + dlg.SelectedPath);
    }
}

#6


23  

After hours of searching I found this answer by leetNightShade to a working solution.

经过数小时的搜寻之后,我找到了这个答案。

There are three things I believe make this solution much better than all the others.

我认为有三件事比其他的事情更能解决这个问题。

  1. It is simple to use. It only requires you include two files (which can be combined to one anyway) in your project.
  2. 使用起来很简单。它只需要在项目中包含两个文件(无论如何都可以合并到一个)。
  3. It falls back to the standard FolderBrowserDialog when used on XP or older systems.
  4. 当在XP或旧系统上使用时,它会返回到标准的FolderBrowserDialog。
  5. The author grants permission to use the code for any purpose you deem fit.

    There’s no license as such as you are free to take and do with the code what you will.

    没有像您这样的许可,您可以*地使用这些代码,做您想做的事情。

Download the code here.

在这里下载代码。

#7


17  

OK, let me try to connect the first dot ;-) Playing a little bit with Spy++ or Winspector shows that the Folder textbox in the VS Project Location is a customization of the standard dialog. It's not the same field as the filename textbox in a standard file dialog such as the one in Notepad.

好的,让我试着连接第一个点;-)使用Spy++或Winspector播放一下,显示VS项目位置中的文件夹文本框是标准对话框的定制。它与标准文件对话框中的文件名文本框(如记事本中的文本框)不同。

From there on, I figure, VS hides the filename and filetype textboxes/comboboxes and uses a custom dialog template to add its own part in the bottom of the dialog.

从这里,我想,VS隐藏文件名和filetype文本框/组合框,并使用自定义对话框模板在对话框底部添加自己的部分。

EDIT: Here's an example of such customization and how to do it (in Win32. not .NET):

编辑:这里有一个这样定制的例子以及如何做(在Win32中)。没有。net):

m_ofn is the OPENFILENAME struct that underlies the file dialog. Add these 2 lines:

m_ofn是文件对话框下面的OPENFILENAME结构。把这两条线:

  m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEDIALOG_IMPORTXLIFF);
  m_ofn.Flags |= OFN_ENABLETEMPLATE;

where IDD_FILEDIALOG_IMPORTXLIFF is a custom dialog template that will be added in the bottom of the dialog. See the part in red below. alt text http://apptranslator.com/_so/customizedfiledialog.png

IDD_FILEDIALOG_IMPORTXLIFF是一个自定义对话框模板,它将被添加到对话框的底部。见下面红色部分。alt文本http://apptranslator.com/_so/customizedfiledialog.png

In this case, the customized part is only a label + an hyperlink but it could be any dialog. It could contain an OK button that would let us validate folder only selection.

在这种情况下,定制部分只是一个标签+一个超链接,但它可以是任何对话框。它可以包含一个OK按钮,让我们只验证文件夹的选择。

But how we would get rid of some of the controls in the standard part of the dialog, I don't know.

但是我们如何去掉对话框标准部分的一些控件,我不知道。

More detail in this MSDN article.

更多细节见这篇MSDN文章。

#8


17  

Exact Audio Copy works this way on Windows XP. The standard file open dialog is shown, but the filename field contains the text "Filename will be ignored".

在Windows XP上,准确的音频拷贝就是这样工作的。标准文件打开对话框显示,但文件名字段包含文本“文件名将被忽略”。

Just guessing here, but I suspect the string is injected into the combo box edit control every time a significant change is made to the dialog. As long as the field isn't blank, and the dialog flags are set to not check the existence of the file, the dialog can be closed normally.

我只是猜测一下,但是我怀疑每次对对话框进行重大更改时,字符串都会被注入到组合框编辑控件中。只要字段不是空的,并且对话框标志被设置为不检查文件的存在,对话框就可以正常关闭。

Edit: this is much easier than I thought. Here's the code in C++/MFC, you can translate it to the environment of your choice.

编辑:这比我想象的要容易得多。这是c++ /MFC中的代码,您可以将其转换为您所选择的环境。

CFileDialog dlg(true, NULL, "Filename will be ignored", OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_PATHMUSTEXIST | OFN_READONLY, NULL, this);
dlg.DoModal();

Edit 2: This should be the translation to C#, but I'm not fluent in C# so don't shoot me if it doesn't work.

编辑2:这应该是对c#的翻译,但是我的c#不太流利,所以如果不行就不要开枪。

OpenFileDialog openFileDialog1 = new OpenFileDialog();

openFileDialog1.FileName = "Filename will be ignored";
openFileDialog1.CheckPathExists = true;
openFileDialog1.ShowReadOnly = false;
openFileDialog1.ReadOnlyChecked = true;
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;

if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
    // openFileDialog1.FileName should contain the folder and a dummy filename
}

Edit 3: Finally looked at the actual dialog in question, in Visual Studio 2005 (I didn't have access to it earlier). It is not the standard file open dialog! If you inspect the windows in Spy++ and compare them to a standard file open, you'll see that the structure and class names don't match. When you look closely, you can also spot some differences between the contents of the dialogs. My conclusion is that Microsoft completely replaced the standard dialog in Visual Studio to give it this capability. My solution or something similar will be as close as you can get, unless you're willing to code your own from scratch.

编辑3:最终在Visual Studio 2005中查看了所讨论的实际对话框(我之前没有访问过它)。这不是标准的文件打开对话框!如果您查看Spy++ +中的窗口并将它们与打开的标准文件进行比较,您将看到结构和类名不匹配。当您仔细观察时,您还可以发现对话框的内容之间的一些差异。我的结论是,微软完全取代了Visual Studio中的标准对话框,为其提供了这种功能。我的解决方案或类似的东西将尽可能接近,除非您愿意从头开始编写自己的代码。

#9


10  

You can subclass the file dialog and gain access to all its controls. Each has an identifier that can be used to obtain its window handle. You can then show and hide them, get messages from them about selection changes etc. etc. It all depends how much effort you want to take.

您可以对file对话框进行子类化,并获得对其所有控件的访问权限。每个窗口都有一个可以用来获取窗口句柄的标识符。然后你可以显示和隐藏它们,从它们那里得到关于选择变化的信息等等。这一切都取决于你想要付出多少努力。

We did ours using WTL class support and customized the file dialog to include a custom places bar and plug-in COM views.

我们使用WTL类支持并定制了文件对话框,以包含自定义位置栏和插件COM视图。

MSDN provides information on how to do this using Win32, this CodeProject article includes an example, and this CodeProject article provides a .NET example.

MSDN提供了关于如何使用Win32进行此操作的信息,本文的CodeProject包含一个示例,本文的CodeProject提供了一个。net示例。

#10


9  

You can use code like this

您可以使用这样的代码

  • The filter is hide files
  • 过滤器是隐藏文件。
  • The filename is hide first text
  • 文件名隐藏第一个文本

To advanced hide of textbox for filename you need to look at OpenFileDialogEx

要高级隐藏文件名的文本框,需要查看OpenFileDialogEx

The code:

代码:

{
    openFileDialog2.FileName = "\r";
    openFileDialog1.Filter = "folders|*.neverseenthisfile";
    openFileDialog1.CheckFileExists = false;
    openFileDialog1.CheckPathExists = false;
}

#11


5  

I assume you're on Vista using VS2008? In that case I think that the FOS_PICKFOLDERS option is being used when calling the Vista file dialog IFileDialog. I'm afraid that in .NET code this would involve plenty of gnarly P/Invoke interop code to get working.

我想你使用的是Vista VS2008?在这种情况下,我认为在调用Vista文件对话框IFileDialog时将使用FOS_PICKFOLDERS选项。我担心在。net代码中,这将涉及大量的复杂的P/调用互操作代码。

#12


2  

First Solution

第一个解决方案

I developed this as a cleaned up version of .NET Win 7-style folder select dialog by Bill Seddon of lyquidity.com (I have no affiliation). (I learned of his code from another answer on this page). I wrote my own because his solution requires an additional Reflection class that isn't needed for this focused purpose, uses exception-based flow control, doesn't cache the results of its reflection calls. Note that the nested static VistaDialog class is so that its static reflection variables don't try to get populated if the Show method is never called. It falls back to the pre-Vista dialog if not in a high enough Windows version. Should work in Windows 7, 8, 9, 10 and higher (theoretically).

我开发这是一个清理版。net Win 7风格的文件夹选择对话框,由lyquidity.com的Bill Seddon(我没有隶属关系)。(我是从本页上的另一个答案得知他的密码的。)我编写了自己的解决方案,因为他的解决方案需要一个额外的反射类,而这个反射类不需要用于这个目的,它使用基于异常的流控制,不缓存反射调用的结果。注意,嵌套的静态VistaDialog类是为了在从未调用Show方法时不尝试填充它的静态反射变量。如果不是在足够高的Windows版本中,它会回到vista前的对话框。应该适用于Windows 7、8、9、10或更高版本(理论上)。

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

namespace ErikE.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; } }
        }
    }
}

It is used like so in a Windows Form:

在Windows窗体中是这样使用的:

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

You can of course play around with its options and what properties it exposes. For example, it allows multiselect in the Vista-style dialog.

当然,您可以使用它的选项和它公开的属性。例如,它允许在vista风格的对话框中进行多选择。

Second Solution

第二个解决方案

Simon Mourier gave an answer that shows how to do the exact same job using interop against the Windows API directly, though his version would have to be supplemented to use the older style dialog if in an older version of Windows. Unfortunately, I hadn't found his post yet when I worked up my solution. Name your poison!

Simon Mourier给出了一个答案,它展示了如何在Windows API上直接使用interop来完成同样的工作,但是如果在旧版本的Windows中,他的版本还需要使用旧的样式对话框。不幸的是,当我想出我的解决方案时,我还没有找到他的职位。名字你的毒药!

#13


1  

Try this one from Codeproject (credit to Nitron):

试试这个来自Codeproject(信用到Nitron)的方法:

I think it's the same dialog you're talking about - maybe it would help if you add a screenshot?

我想这和你说的是同一个对话框——如果你添加一个截图会有帮助吗?

bool GetFolder(std::string& folderpath, const char* szCaption=NULL, HWND hOwner=NULL)
{
    bool retVal = false;

    // The BROWSEINFO struct tells the shell how it should display the dialog.
    BROWSEINFO bi;
    memset(&bi, 0, sizeof(bi));

    bi.ulFlags   = BIF_USENEWUI;
    bi.hwndOwner = hOwner;
    bi.lpszTitle = szCaption;

    // must call this if using BIF_USENEWUI
    ::OleInitialize(NULL);

    // Show the dialog and get the itemIDList for the selected folder.
    LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);

    if(pIDL != NULL)
    {
        // Create a buffer to store the path, then get the path.
        char buffer[_MAX_PATH] = {'\0'};
        if(::SHGetPathFromIDList(pIDL, buffer) != 0)
        {
            // Set the string value.
            folderpath = buffer;
            retVal = true;
        }       

        // free the item id list
        CoTaskMemFree(pIDL);
    }

    ::OleUninitialize();

    return retVal;
}

#14


1  

On Vista you can use IFileDialog with FOS_PICKFOLDERS option set. That will cause display of OpenFileDialog-like window where you can select folders:

在Vista中,你可以使用带有FOS_PICKFOLDERS选项设置的IFileDialog。这将导致openfiledialog类窗口的显示,你可以在其中选择文件夹:

var frm = (IFileDialog)(new FileOpenDialogRCW());
uint options;
frm.GetOptions(out options);
options |= FOS_PICKFOLDERS;
frm.SetOptions(options);

if (frm.Show(owner.Handle) == S_OK) {
    IShellItem shellItem;
    frm.GetResult(out shellItem);
    IntPtr pszString;
    shellItem.GetDisplayName(SIGDN_FILESYSPATH, out pszString);
    this.Folder = Marshal.PtrToStringAuto(pszString);
}

For older Windows you can always resort to trick with selecting any file in folder.

对于较老的Windows,您可以选择在文件夹中选择任何文件。

Working example that works on .NET Framework 2.0 and later can be found here.

可以在这里找到在。net Framework 2.0和以后工作的示例。

#15


1  

You can use code like this

您可以使用这样的代码

The filter is empty string. The filename is AnyName but not blank

过滤器是空字符串。文件名是任何名称,但不是空白

        openFileDialog.FileName = "AnyFile";
        openFileDialog.Filter = string.Empty;
        openFileDialog.CheckFileExists = false;
        openFileDialog.CheckPathExists = false;

#16


0  

I know the question was on configuration of OpenFileDialog but seeing that Google brought me here i may as well point out that if you are ONLY looking for folders you should be using a FolderBrowserDialog Instead as answered by another SO question below

我知道这个问题是关于OpenFileDialog的配置的,但是看到谷歌把我带到了这里,我也可以指出,如果你只是在寻找文件夹,你应该使用FolderBrowserDialog,而不是下面另一个SO问题的答案

How to specify path using open file dialog in vb.net?

如何使用vb.net中的打开文件对话框指定路径?