C# 从 .NET 中的同一对话框中选择文件或文件夹
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/428410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Select either a file or folder from the same dialog in .NET
提问by barry
Is there an "easy" way to select either a file OR a folder from the same dialog?
是否有一种“简单”的方法可以从同一个对话框中选择文件或文件夹?
In many apps I create I allow for both files or folders as input. Until now i always end up creating a switch to toggle between file or folder selection dialogs or stick with drag-and-drop functionality only.
在我创建的许多应用程序中,我允许将文件或文件夹作为输入。到现在为止,我总是最终创建一个开关来在文件或文件夹选择对话框之间切换,或者只坚持使用拖放功能。
Since this seems such a basic thing i would imagine this has been created before, but googling does not result in much information. So it looks like i would need to start from scratch and create a custom selection Dialog, but I rather not introduce any problems by reinventing the wheel for such a trivial task.
由于这似乎是一件基本的事情,我想这之前已经创建过,但是谷歌搜索不会产生太多信息。所以看起来我需要从头开始并创建一个自定义选择对话框,但我宁愿通过为这样一个微不足道的任务重新发明轮子来引入任何问题。
Anybody any tips or existing solutions?
有人有任何提示或现有的解决方案吗?
To keep the UI consistent it would be nice if it is possible to extend the OpenFileDialog (or the FolderBrowserDialog).
为了保持 UI 一致,如果可以扩展 OpenFileDialog(或 FolderBrowserDialog),那就太好了。
采纳答案by Hans Passant
Technically, it is possible. The shell dialog used by FolderBrowseDialog has the ability to return both files and folders. Unfortunately, that capability isn't exposed in .NET. Not even reflection can poke the required option flag.
从技术上讲,这是可能的。FolderBrowseDialog 使用的外壳对话框能够返回文件和文件夹。不幸的是,该功能未在 .NET 中公开。甚至反射都无法戳到所需的选项标志。
To make it work, you'd have to P/Invoke SHBrowseForFolder() with the BIF_BROWSEINCLUDEFILES flag turned on in BROWSEINFO.ulFlags (value = 0x4000). The P/Invoke is gritty, it is best to copy and paste the code from another sourceor the FolderBrowseDialog class itself with Reflector's help.
要使其工作,您必须在 BROWSEINFO.ulFlags(值 = 0x4000)中打开 BIF_BROWSEINCLUDEFILES 标志的情况下 P/Invoke SHBrowseForFolder()。P/Invoke 是坚韧不拔的,最好在Reflector 的帮助下从另一个源或 FolderBrowseDialog 类本身复制和粘贴代码。
回答by Mitch Wheat
AFAIK, there is nothing in the .NET framework that does this out of the box.
AFAIK,.NET 框架中没有任何东西可以开箱即用。
The .NET file dialogs derive from CommonDialog:
.NET 文件对话框派生自CommonDialog:
Inherited classes are required to implement RunDialog by invoking ShowDialog to create a specific common dialog box. Inherited classes can override HookProc to implement specific dialog box hook functionality.
继承类需要通过调用 ShowDialog 创建特定的公共对话框来实现 RunDialog。继承的类可以覆盖 HookProc 以实现特定的对话框钩子功能。
回答by Tom Anderson
All of the built in dialogs use the shell API's that correspond to their action, PrintDialog, OpenFileDialog, SaveFileDialog, etc...
所有内置对话框都使用与其操作相对应的 shell API,如 PrintDialog、OpenFileDialog、SaveFileDialog 等...
You would most likely have to manually build this functionality.
您很可能必须手动构建此功能。
回答by barry
Based on the above tips I found some working code that uses the standard Folder Browser dialog at the following location: http://topic.csdn.net/t/20020703/05/845468.html
根据上述提示,我在以下位置找到了一些使用标准文件夹浏览器对话框的工作代码:http: //topic.csdn.net/t/20020703/05/845468.html
The Class for the extended Folder Browser Dialog
扩展文件夹浏览器对话框的类
Imports System
Imports System.Text
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Public Class DirectoryDialog
Public Structure BROWSEINFO
Public hWndOwner As IntPtr
Public pIDLRoot As Integer
Public pszDisplayName As String
Public lpszTitle As String
Public ulFlags As Integer
Public lpfnCallback As Integer
Public lParam As Integer
Public iImage As Integer
End Structure
Const MAX_PATH As Integer = 260
Public Enum BrowseForTypes As Integer
Computers = 4096
Directories = 1
FilesAndDirectories = 16384
FileSystemAncestors = 8
End Enum
Declare Function CoTaskMemFree Lib "ole32" Alias "CoTaskMemFree" (ByVal hMem As IntPtr) As Integer
Declare Function lstrcat Lib "kernel32" Alias "lstrcat" (ByVal lpString1 As String, ByVal lpString2 As String) As IntPtr
Declare Function SHBrowseForFolder Lib "shell32" Alias "SHBrowseForFolder" (ByRef lpbi As BROWSEINFO) As IntPtr
Declare Function SHGetPathFromIDList Lib "shell32" Alias "SHGetPathFromIDList" (ByVal pidList As IntPtr, ByVal lpBuffer As StringBuilder) As Integer
Protected Function RunDialog(ByVal hWndOwner As IntPtr) As Boolean
Dim udtBI As BROWSEINFO = New BROWSEINFO()
Dim lpIDList As IntPtr
Dim hTitle As GCHandle = GCHandle.Alloc(Title, GCHandleType.Pinned)
udtBI.hWndOwner = hWndOwner
udtBI.lpszTitle = Title
udtBI.ulFlags = BrowseFor
Dim buffer As StringBuilder = New StringBuilder(MAX_PATH)
buffer.Length = MAX_PATH
udtBI.pszDisplayName = buffer.ToString()
lpIDList = SHBrowseForFolder(udtBI)
hTitle.Free()
If lpIDList.ToInt64() <> 0 Then
If BrowseFor = BrowseForTypes.Computers Then
m_Selected = udtBI.pszDisplayName.Trim()
Else
Dim path As StringBuilder = New StringBuilder(MAX_PATH)
SHGetPathFromIDList(lpIDList, path)
m_Selected = path.ToString()
End If
CoTaskMemFree(lpIDList)
Else
Return False
End If
Return True
End Function
Public Function ShowDialog() As DialogResult
Return ShowDialog(Nothing)
End Function
Public Function ShowDialog(ByVal owner As IWin32Window) As DialogResult
Dim handle As IntPtr
If Not owner Is Nothing Then
handle = owner.Handle
Else
handle = IntPtr.Zero
End If
If RunDialog(handle) Then
Return DialogResult.OK
Else
Return DialogResult.Cancel
End If
End Function
Public Property Title() As String
Get
Return m_Title
End Get
Set(ByVal Value As String)
If Value Is DBNull.Value Then
Throw New ArgumentNullException()
End If
m_Title = Value
End Set
End Property
Public ReadOnly Property Selected() As String
Get
Return m_Selected
End Get
End Property
Public Property BrowseFor() As BrowseForTypes
Get
Return m_BrowseFor
End Get
Set(ByVal Value As BrowseForTypes)
m_BrowseFor = Value
End Set
End Property
Private m_BrowseFor As BrowseForTypes = BrowseForTypes.Directories
Private m_Title As String = ""
Private m_Selected As String = ""
Public Sub New()
End Sub
End Class
The code to implement the extended dialog
实现扩展对话框的代码
Sub Button1Click(ByVal sender As Object, ByVal e As EventArgs)
Dim frmd As DirectoryDialog = New DirectoryDialog()
' frmd.BrowseFor = DirectoryDialog.BrowseForTypes.Directories
' frmd.BrowseFor = DirectoryDialog.BrowseForTypes.Computers
frmd.BrowseFor = DirectoryDialog.BrowseForTypes.FilesAndDirectories
frmd.Title = "Select a file or a folder"
If frmd.ShowDialog(Me) = DialogResult.OK Then
MsgBox(frmd.Selected)
End If
End Sub
回答by barry
回答by Cheeso
It's been done. 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 browse for folders, or files+folders. You can browse for computers or printers with it. Based on the built-in FBD, but ... better. More flexible. If you click a folder in the GUI, the path appears in the textbox. If you key in a path, the folder gets activatied. Lots of options the built-in dialog lacks.
它已经完成了。您可以使用FolderBrowserDialogEx- 内置 FolderBrowserDialog 的可重用派生。这允许您输入路径,甚至是 UNC 路径。您可以浏览文件夹或文件+文件夹。您可以使用它浏览计算机或打印机。基于内置 FBD,但...更好。更灵活。如果单击 GUI 中的文件夹,则该路径会出现在文本框中。如果您键入路径,则该文件夹将被激活。内置对话框缺少很多选项。
Full Source code. Free. MS-Public license.
完整的源代码。自由。MS-公共许可证。
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;
}
回答by stankovski
You can use standard OpenFileDialog to select a folder. Here is an article in CodeProject that demonstrated a way to do it (http://www.codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx).
您可以使用标准的 OpenFileDialog 来选择文件夹。这是 CodeProject 中的一篇文章,演示了一种方法(http://www.codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx)。
回答by Araym
http://www.pinvoke.net/default.aspx/shell32.shbrowseforfolder
http://www.pinvoke.net/default.aspx/shell32.shbrowseforfolder
here is gerat link if you change in this sample
如果您在此示例中更改,这里是 gerat 链接
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
for
为了
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;
you will get what you want
你会得到你想要的
回答by Jason P
this will allow you to select folders using OpenFileDialog
这将允许您使用 OpenFileDialog 选择文件夹
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;
回答by C. Augusto Proiete
The Ookii Dialogsimplement a folder browser dialog that allow for both files or folders as input, and is available for Windows Forms and WPF.
该Ookii对话框实现文件夹的浏览器对话框,允许两个文件或文件夹作为输入,可用于Windows Forms和WPF。
Ookii.Dialogs.Wpf
Ookii.Dialogs.Wpf
Ookii.Dialogs.WinForms
Ookii.Dialogs.WinForms