Select either a file or folder from the same dialog in .NET
Asked Answered
N

10

33

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

Nihilism answered 9/1, 2009 at 15:8 Comment(2)
This question is very similar to this one that I asked. You may find it an interesting reference. #100764Trumantrumann
Check out the Ookii Dialogs libraries which have implementations of a folder browser dialog for Windows Forms and WPF respectively...Pygidium
F
13

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.

Furie answered 10/1, 2009 at 15:1 Comment(1)
Thanks, the BIF_BROWSEINCLUDEFILES did the trick. See answer below for a code sample.Nihilism
N
8

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
Nihilism answered 10/1, 2009 at 15:47 Comment(1)
I converted this class to C# for anyone interested (pastebin.com/33X93vKt).Brother
S
5

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;
     }
Supermarket answered 9/3, 2009 at 7:20 Comment(1)
To save other people the trouble in future, I used this dialog and it does not allow you multiple selections. And in order to get it to pick files at all, your answer should mention setting dlg1.ShowBothFilesAndFolders = true;Watchman
N
5

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

Nonmetal answered 25/11, 2009 at 20:54 Comment(3)
Thanks! i gave it a try, but i could not get it to work. The file open dialog could only Open files. It might have to do with the OS (I am using Windows 7). It would be really nice if we could use the File Open Dialog without having to create a custom control from scratch. The previous solutions using "extended" folder selection dialogs work but the resulting UI feels outdated.Nihilism
I found the problem with Windows 7. In addition to ValidateNames the following 2 flags should be set: dialog.CheckFileExists = false; dialog.CheckPathExists = true;Nonmetal
@Nonmetal Can you give me a sample code on how you did it? I can't figure it out. I'm getting errors and don't know how or where to use the code. Do I create a new class or use it in the main form? The reset part is giving error saying it can't override it. I'm new to C#. Thank you in advance.Melone
S
1

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.

Smtih answered 10/1, 2009 at 1:10 Comment(0)
T
1

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.

Triiodomethane answered 10/1, 2009 at 1:21 Comment(0)
D
1

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

Deeplaid answered 9/9, 2014 at 6:40 Comment(0)
N
0

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,

Nihilism answered 14/1, 2009 at 6:42 Comment(0)
S
0

this will allow you to select folders using OpenFileDialog

        openFileDialog1.CheckFileExists = false;
        openFileDialog1.ValidateNames = false;
Sarnen answered 18/1, 2016 at 4:22 Comment(0)
P
0

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

Pygidium answered 20/10, 2018 at 21:40 Comment(2)
I tried the VistaFolderBrowserDialog Winforms one from nuget and it doesn't allow me to select files and it doesn't allow me to select multiple folders and/or files.Intolerance
@Intolerance Create an issue on the repository with a reproducible example of the issue you seePygidium

© 2022 - 2024 — McMap. All rights reserved.