Выберите файл или папку из того же диалогового окна в .NET.
Есть ли "простой" способ выбрать либо файл, либо папку из того же диалога?
Во многих приложениях, которые я создаю, я разрешаю вставлять как файлы, так и папки.
До сих пор я всегда создавал переключатель для переключения между диалоговыми окнами выбора файлов или папок или только с функцией перетаскивания.
Так как это кажется такой основной вещью, я бы предположил, что это было создано раньше, но googling не приводит к большой информации. Так что, похоже, мне нужно будет начать с нуля и создать настраиваемый диалог выбора, но я скорее не буду вводить никаких проблем, изобретая колесо для такой тривиальной задачи.
Есть ли какие-либо советы или существующие решения?
Чтобы поддерживать согласованный интерфейс, было бы неплохо, если можно расширить OpenFileDialog (или FolderBrowserDialog).
Ответы
Ответ 1
Технически это возможно. Диалоговое окно оболочки, используемое FolderBrowseDialog, позволяет возвращать файлы и папки. К сожалению, эта возможность не отображается в .NET. Даже отражение может выставить требуемый флажок.
Чтобы заставить его работать, вы должны P/Invoke SHBrowseForFolder() с флагом BIF_BROWSEINCLUDEFILES, включенным в BROWSEINFO.ulFlags(value = 0x4000). P/Invoke является сложным, лучше скопировать и вставить код из другого источника или самого класса FolderBrowseDialog с помощью справки Reflector.
Ответ 2
На основе приведенных выше советов я нашел некоторый рабочий код, который использует стандартный диалог браузера папок в следующем месте: 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
Ответ 3
Это было сделано. Вы можете использовать FolderBrowserDialogEx -
повторно используемую производную от встроенного FolderBrowserDialog. Это позволяет вам вводить путь, даже путь UNC. Вы можете просматривать папки или файлы + папки. Вы можете просматривать с ним компьютеры или принтеры. На основе встроенного FBD, но... лучше. Более гибкий. Если вы щелкнете папку в графическом интерфейсе, путь появится в текстовом поле. Если вы укажете путь, папка активируется. Множество опций отсутствует в встроенном диалоговом окне.
Полный исходный код. Свободно. Лицензия MS-Public.
FolderBrowserDialogEx http://www.freeimagehosting.net/uploads/bfbab6cea5.png
Код для использования:
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;
}
Ответ 4
Вы можете использовать стандартный OpenFileDialog для выбора папки. Вот статья в CodeProject, которая продемонстрировала способ сделать это.
Ответ 5
AFAIK, в .NET Framework нет ничего, что делает это из коробки.
Диалоги файлов .NET выводятся из CommonDialog:
Унаследованные классы необходимы для реализовать RunDialog путем вызова ShowDialog для создания определенного общего диалоговое окно. Унаследованные классы могут переопределить HookProc для реализации привязка конкретного диалогового окна функциональность.
Ответ 6
Все встроенные диалоги используют API-интерфейс оболочки, соответствующий их действию, PrintDialog, OpenFileDialog, SaveFileDialog и т.д.
Вам, скорее всего, придется вручную создать эту функциональность.
Ответ 7
http://www.pinvoke.net/default.aspx/shell32.shbrowseforfolder
здесь ссылка gerat, если вы измените этот пример
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
для
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;
вы получите то, что хотите
Ответ 8
Если вы хотите отображать только определенные типы файлов, следующая статья (с исходным кодом на С#) может помочь вам:
http://www.codeproject.com/KB/shell/csdoesshell1.aspx?fid=14137&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26
Он также объясняет другие параметры, доступные для "настройки" диалога FolderBrowser,
Ответ 9
это позволит вам выбирать папки с помощью OpenFileDialog
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;