从 .NET 中的同一对话框中选择文件或文件夹

发布于 2024-07-11 17:12:59 字数 332 浏览 11 评论 0原文

是否有一种“简单”的方法可以从同一对话框中选择文件或文件夹?

在我创建的许多应用程序中,我允许文件或文件夹作为输入。 到目前为止,我总是最终创建一个开关来在文件或文件夹选择对话框之间切换,或者仅使用拖放功能。

因为这似乎是一个基本的事情,我想它以前已经创建过,但谷歌搜索并没有产生太多信息。 所以看起来我需要从头开始并创建一个自定义选择对话框,但我不想通过为这样一个琐碎的任务重新发明轮子来引入任何问题。

有人有任何提示或现有解决方案吗?

为了保持 UI 的一致性,如果能够扩展 OpenFileDialog(或FolderBrowserDialog)就好了。

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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

℡寂寞咖啡 2024-07-18 17:12:59

从技术上来说,这是可能的。 FolderBrowseDialog 使用的 shell 对话框能够返回文件和文件夹。 不幸的是,.NET 中并未公开该功能。 甚至反射也无法戳到所需的选项标志。

为了使其工作,您必须在 BROWSEINFO.ulFlags 中打开 BIF_BROWSEINCLUDEFILES 标志(值 = 0x4000)的情况下 P/Invoke SHBrowseForFolder()。 P/Invoke 是坚韧不拔的,最好从 另一个来源 或在 Reflector 的帮助下使用FolderBrowseDialog 类本身。

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.

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 source or the FolderBrowseDialog class itself with Reflector's help.

池予 2024-07-18 17:12:59

根据上述提示,我在以下位置找到了一些使用标准文件夹浏览器对话框的工作代码: http://topic.csdn.net/t/20020703/05/845468.html

扩展文件夹浏览器对话框的类

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 

扩展对话框的实现代码

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

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

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
禾厶谷欠 2024-07-18 17:12:59

您可以使用标准 OpenFileDialog 来选择文件夹。 这是 CodeProject 中的一篇文章,演示了一种实现此操作的方法 (http://www. codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx)。

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).

凹づ凸ル 2024-07-18 17:12:59

已经完成了。 您可以使用 FolderBrowserDialogEx -
内置FolderBrowserDialog 的可重复使用的衍生产品。 该选项允许您输入路径,甚至是 UNC 路径。 您可以浏览文件夹或文件+文件夹。 您可以用它浏览计算机或打印机。 基于内置 FBD,但是……更好。 更灵活。 如果单击 GUI 中的文件夹,路径将显示在文本框中。 如果您键入路径,该文件夹就会被激活。 内置对话框缺少很多选项。

完整源代码。 自由的。 MS-公共许可证。

FolderBrowserDialogEx

使用它的代码:

     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;
     }

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.

Full Source code. Free. MS-Public license.

FolderBrowserDialogEx

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;
     }
无声情话 2024-07-18 17:12:59

AFAIK,.NET 框架中没有任何东西可以开箱即用地执行此操作。

.NET 文件对话框源自 CommonDialog :

需要继承类
通过调用来实现 RunDialog
ShowDialog创建特定的通用
对话框。 继承类可以
重写 HookProc 来实现
特定对话框挂钩
功能。

AFAIK, there is nothing in the .NET framework that does this out of the box.

The .NET file dialogs derive from 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.

十秒萌定你 2024-07-18 17:12:59

所有内置对话框都使用与其操作相对应的 shell API,例如 PrintDialog、OpenFileDialog、SaveFileDialog 等...

您很可能必须手动构建此功能。

All of the built in dialogs use the shell API's that correspond to their action, PrintDialog, OpenFileDialog, SaveFileDialog, etc...

You would most likely have to manually build this functionality.

柳若烟 2024-07-18 17:12:59

http://www.pinvoke.net/default.aspx/shell32.shbrowseforfolder

这是 gerat 链接,如果您对此示例进行更改

  bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;

  bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;

您将得到您想要的

http://www.pinvoke.net/default.aspx/shell32.shbrowseforfolder

here is gerat link if you change in this sample

  bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;

for

  bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;

you will get what you want

过气美图社 2024-07-18 17:12:59

如果您只想显示特定文件类型,请使用以下 文章(带有 C# 源代码)可以帮助您:

http://www .codeproject.com/KB/shell/csdoesshell1.aspx?fid=14137&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26

它还解释了其他选项可用于“自定义”FolderBrowser 对话框,

If you would like to display only specific file types, the following article (with source code in C#) can help you:

http://www.codeproject.com/KB/shell/csdoesshell1.aspx?fid=14137&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26

It also explains the other options that are available for "customizing" the FolderBrowser dialog,

你怎么敢 2024-07-18 17:12:59

这将允许您使用 OpenFileDialog 选择文件夹

        openFileDialog1.CheckFileExists = false;
        openFileDialog1.ValidateNames = false;

this will allow you to select folders using OpenFileDialog

        openFileDialog1.CheckFileExists = false;
        openFileDialog1.ValidateNames = false;
相守太难 2024-07-18 17:12:59

Ookii 对话框 实现了一个文件夹浏览器对话框,允许文件或文件夹作为输入,并且可用于 Windows 窗体和 WPF。

在此处输入图像描述

Ookii.Dialogs.Wpf

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


Ookii.Dialogs.WinForms

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

The Ookii Dialogs implement a folder browser dialog that allow for both files or folders as input, and is available for Windows Forms and WPF.

enter image description here

Ookii.Dialogs.Wpf

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


Ookii.Dialogs.WinForms

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文