Выберите файл или папку из того же диалога в .NET - PullRequest
31 голосов
/ 09 января 2009

Есть ли "простой" способ выбрать файл или папку из того же диалога?

Во многих приложениях, которые я создаю, я разрешаю вводить как файлы, так и папки. До сих пор я всегда заканчивал тем, что создавал переключатель для переключения между диалогами выбора файлов или папок или придерживался только функции перетаскивания.

Поскольку это кажется такой простой вещью, я бы предположил, что это было создано ранее, но поиск в Google не приводит к большому количеству информации. Похоже, мне нужно было бы начать с нуля и создать собственный диалог выбора, но я бы не стал создавать никаких проблем, изобретая колесо для такой тривиальной задачи.

Кто-нибудь какие-нибудь советы или существующие решения?

Чтобы интерфейс оставался согласованным, было бы неплохо, если бы можно было расширить OpenFileDialog (или FolderBrowserDialog).

Ответы [ 10 ]

12 голосов
/ 10 января 2009

Технически это возможно. Диалоговое окно оболочки, используемое FolderBrowseDialog, может возвращать как файлы, так и папки. К сожалению, эта возможность не предоставляется в .NET. Даже отражение не может поставить нужный флаг опции.

Чтобы это работало, вам нужно выполнить P / Invoke SHBrowseForFolder () с включенным флагом BIF_BROWSEINCLUDEFILES в BROWSEINFO.ulFlags (значение = 0x4000). P / Invoke является жестким, лучше всего скопировать и вставить код из другого источника или самого класса FolderBrowseDialog с помощью Reflector.

7 голосов
/ 10 января 2009

На основании приведенных выше советов я нашел рабочий код, который использует стандартное диалоговое окно просмотра папок, в следующем месте: 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
5 голосов
/ 25 ноября 2009

Вы можете использовать стандартный OpenFileDialog для выбора папки. Вот статья в CodeProject, которая продемонстрировала способ сделать это (http://www.codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx).

5 голосов
/ 09 марта 2009

Это было сделано. Вы можете использовать FolderBrowserDialogEx - повторно используемая производная от встроенного FolderBrowserDialog. Этот позволяет вам ввести путь, даже путь UNC. Вы можете просматривать папки или файлы + папки. Вы можете просматривать компьютеры или принтеры с ним. На основе встроенного FBD, но ... лучше. Более гибкий. Если щелкнуть папку в графическом интерфейсе, путь появится в текстовом поле. Если вы введете путь, папка будет активирована. Много опций, которых нет во встроенном диалоге.

Полный исходный код. Свободно. Лицензия MS-Public.

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;
     }
1 голос
/ 09 сентября 2014

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

вот ссылка на Gerat, если вы измените в этом примере

  bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;

для

  bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;

вы получите то, что хотите

1 голос
/ 10 января 2009

Все встроенные диалоги используют API-интерфейсы оболочки, соответствующие их действию, PrintDialog, OpenFileDialog, SaveFileDialog и т. Д. *

Скорее всего, вам придется вручную создать эту функцию.

1 голос
/ 10 января 2009

AFAIK, в .NET Framework нет ничего такого, что могло бы сделать это из коробки.

Диалоги файлов .NET происходят от CommonDialog :

Унаследованные классы необходимы для реализовать RunDialog, вызвав ShowDialog для создания определенного общего диалоговое окно. Унаследованные классы могут переопределить HookProc для реализации конкретный диалог диалогового окна функциональность.

0 голосов
/ 21 октября 2018

Диалоги Ookii реализуют диалоговое окно браузера папок, которое позволяет вводить как файлы, так и папки, и доступно для Windows Forms и WPF.

enter image description here

Ookii.Dialogs.Wpf

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


Ookii.Dialogs.WinForms

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

0 голосов
/ 18 января 2016

это позволит вам выбирать папки, используя OpenFileDialog

        openFileDialog1.CheckFileExists = false;
        openFileDialog1.ValidateNames = false;
0 голосов
/ 14 января 2009

Если вы хотите отображать только определенные типы файлов, вам может помочь следующая статья (с исходным кодом на C #):

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

Также объясняются другие параметры, доступные для «настройки» диалога FolderBrowser,

...