Seleccione un archivo o carpeta del mismo cuadro de diálogo en .NET
-
06-07-2019 - |
Pregunta
¿Hay un " fácil " ¿Cómo seleccionar un archivo O una carpeta desde el mismo cuadro de diálogo?
En muchas aplicaciones que creo, permito tanto los archivos como las carpetas como entrada. Hasta ahora, siempre termino creando un interruptor para alternar entre los cuadros de diálogo de selección de archivos o carpetas o solo con la funcionalidad de arrastrar y soltar.
Dado que esto parece algo tan básico, me imagino que esto se ha creado antes, pero googlear no da como resultado mucha información. Por lo tanto, parece que tendría que comenzar desde cero y crear un Diálogo de selección personalizado, pero prefiero no presentar ningún problema reinventando la rueda para una tarea tan trivial.
¿Alguien algún consejo o soluciones existentes?
Para mantener la interfaz de usuario coherente, sería bueno si es posible extender OpenFileDialog (o FolderBrowserDialog).
Solución
Técnicamente, es posible. El cuadro de diálogo de shell utilizado por FolderBrowseDialog tiene la capacidad de devolver archivos y carpetas. Desafortunadamente, esa capacidad no está expuesta en .NET. Ni siquiera el reflejo puede tocar el indicador de opción requerido.
Para que funcione, tendría que P / Invocar SHBrowseForFolder () con el indicador BIF_BROWSEINCLUDEFILES activado en BROWSEINFO.ulFlags (valor = 0x4000). El P / Invoke es valiente, es mejor copiar y pegar el código de otra fuente o la clase FolderBrowseDialog en sí con la ayuda de Reflector.
Otros consejos
En base a los consejos anteriores, encontré un código de trabajo que utiliza el cuadro de diálogo estándar del Explorador de carpetas en la siguiente ubicación: http://topic.csdn.net/t/20020703/05/845468.html
La clase para el diálogo extendido del explorador de carpetas
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
El código para implementar el diálogo extendido
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
Puede usar OpenFileDialog estándar para seleccionar una carpeta. Aquí hay un artículo en CodeProject que demostró una forma de hacerlo ( http: // www. codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx ).
Ya está hecho. Puede usar FolderBrowserDialogEx - una derivada reutilizable del FolderBrowserDialog incorporado. Este le permite escribir una ruta, incluso una ruta UNC. Puede buscar carpetas o archivos + carpetas. Puede buscar computadoras o impresoras con él. Basado en el FBD incorporado, pero ... mejor. Mas flexible. Si hace clic en una carpeta en la GUI, la ruta aparece en el cuadro de texto. Si ingresa una ruta, la carpeta se activa. Muchas opciones que le faltan al diálogo incorporado.
Código fuente completo. Gratis. Licencia pública de MS.
Código para usarlo:
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;
}
AFAIK, no hay nada en .NET Framework que lo haga listo para usar.
Los cuadros de diálogo del archivo .NET se derivan de CommonDialog :
Se requieren clases heredadas para implementar RunDialog invocando ShowDialog para crear un común específico caja de diálogo. Las clases heredadas pueden anular HookProc para implementar gancho de cuadro de diálogo específico funcionalidad.
Todos los cuadros de diálogo integrados utilizan las API de shell que corresponden a su acción, PrintDialog, OpenFileDialog, SaveFileDialog, etc. ...
Lo más probable es que tenga que construir manualmente esta funcionalidad.
http://www.pinvoke.net/default.aspx/shell32.shbrowseforfolder
aquí está el enlace gerat si cambia en esta muestra
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
para
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;
obtendrás lo que quieres
Si desea mostrar solo tipos de archivos específicos, los siguientes el artículo (con el código fuente en C #) puede ayudarlo:
También explica las otras opciones que están disponibles para "personalizar" el cuadro de diálogo FolderBrowser,
esto le permitirá seleccionar carpetas usando OpenFileDialog
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;
Los Diálogos de Ookii implementan un diálogo de explorador de carpetas que permite ambos archivos o carpetas como entrada, y está disponible para Windows Forms y WPF.
Ookii.Dialogs.Wpf
Ookii.Dialogs.WinForms