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

到目前为止,我几乎可以肯定在。net中没有办法做到这一点,但我很好奇在非托管代码中如何做到这一点。如果不从头开始完全重新实现对话框,如何修改对话框以使其具有这种行为呢?

我还想重申,我知道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.

更新:我接受Scott Wisniewski的答案,因为它附带了一个工作示例,但我认为Serge值得赞扬,因为他指出了对话框定制(这在。net中确实很讨厌,但它确实有效),Mark Ransom指出微软可能为这个任务推出了一个自定义对话框。


当前回答

WPF库的Ookii对话框有一个类,它提供了WPF文件夹浏览器对话框的实现。

https://github.com/augustoproiete/ookii-dialogs-wpf

还有一个版本可以使用Windows窗体。

其他回答

Ookii。对话框包包含一个托管包装器围绕新的(vista风格)文件夹浏览器对话框。它在旧的操作系统上也会优雅地退化。

面向。net 4.5的WPF Ookii对话框,在NuGet上可用 面向。net 4.5的Windows窗体Ookii对话框,可在NuGet上使用

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

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

MSDN提供了关于如何使用Win32实现这一点的信息,这篇CodeProject文章包含了一个示例,这篇CodeProject文章提供了一个. net示例。

经过几个小时的搜索,我通过leetNightShade找到了一个有效的解决方案。

我认为有三件事使这个解决方案比其他解决方案要好得多。

使用起来很简单。 它只需要您在项目中包含两个文件(无论如何都可以合并为一个文件)。 当在XP或旧系统上使用时,它会退回到标准的FolderBrowserDialog。 作者允许您将代码用于您认为合适的任何目的。 没有什么许可可以让你随心所欲地使用代码。

在这里下载代码。

您可以使用这样的代码

过滤器是隐藏文件 文件名是隐藏第一个文本

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

代码:

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

您可以使用这样的代码

过滤器为空字符串。 文件名为AnyName,但不为空

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