Existe-t-il un moyen "facile" de sélectionner un fichier OR un dossier dans la même boîte de dialogue?
Dans de nombreuses applications que je crée, les fichiers ou les dossiers sont autorisés en entrée. Jusque-là, je finissais toujours par créer un commutateur permettant de basculer entre les boîtes de dialogue de sélection de fichiers ou de dossiers ou de n'utiliser que la fonctionnalité glisser-déposer.
Étant donné que cela semble une chose fondamentale, j'imagine que cela a été créé auparavant, mais googler ne donne pas beaucoup d'informations. Il semble donc que je devrais commencer à partir de zéro et créer un dialogue de sélection personnalisé, mais je préfère ne pas présenter de problèmes en réinventant la roue pour une tâche aussi triviale.
Quelqu'un a des conseils ou des solutions existantes?
Pour que l'interface utilisateur reste cohérente, il serait bien qu'il soit possible d'étendre OpenFileDialog (ou FolderBrowserDialog).
Techniquement, c'est possible. La boîte de dialogue Shell utilisée par FolderBrowseDialog permet de renvoyer des fichiers et des dossiers. Malheureusement, cette fonctionnalité n'est pas exposée dans .NET. Même la réflexion ne peut déclencher l'indicateur d'option requis.
Pour que cela fonctionne, vous devez P/Invoke SHBrowseForFolder () avec le drapeau BIF_BROWSEINCLUDEFILES activé dans BROWSEINFO.ulFlags (valeur = 0x4000). Le P/Invoke est graveleux, il est préférable de copier et coller le code depuis une autre source ou la classe FolderBrowseDialog elle-même avec l'aide de Reflector.
Sur la base des conseils ci-dessus, j'ai trouvé un code qui utilise la boîte de dialogue standard du navigateur de dossiers à l'emplacement suivant: http://topic.csdn.net/t/20020703/05/845468.html
La classe pour la boîte de dialogue étendue du navigateur de dossiers
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
Le code pour implémenter le dialogue étendu
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
C'est fait. Vous pouvez utiliser FolderBrowserDialogEx - , Un dérivé réutilisable du FolderBrowserDialog intégré. Celui-ci vous permet de taper un chemin, même un chemin UNC. Vous pouvez rechercher des dossiers ou des fichiers + dossiers. Vous pouvez rechercher des ordinateurs ou des imprimantes avec. Basé sur le FBD intégré, mais ... meilleur. Plus flexible. Si vous cliquez sur un dossier dans l'interface graphique, le chemin d'accès apparaît dans la zone de texte. Si vous entrez un chemin, le dossier est activé. La boîte de dialogue intégrée manque de nombreuses options.
Code source complet. Libre. Licence MS-Public.
FolderBrowserDialogEx http://www.freeimagehosting.net/uploads/bfbab6cea5.png
Code pour l'utiliser:
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;
}
Vous pouvez utiliser OpenFileDialog standard pour sélectionner un dossier. Voici un article de CodeProject qui montre une façon de le faire ( http://www.codeproject.com/KB/dialog/OpenFileOrFolderDialog.aspx ).
http://www.pinvoke.net/default.aspx/Shell32.shbrowseforfolder
voici le lien gerat si vous changez dans cet exemple
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
pour
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE | BIF_BROWSEINCLUDEFILES;
vous obtiendrez ce que vous voulez
D'après les informations dont je dispose, rien dans le framework .NET ne le fait par défaut.
Les dialogues de fichiers .NET proviennent de CommonDialog :
Les classes héritées doivent Implémenter RunDialog en appelant ShowDialog pour créer une boîte de dialogue spécifique Commune. Les classes héritées peuvent Substituer HookProc pour implémenter une fonctionnalité []____ de crochet de boîte de dialogue spécifique .
Toutes les boîtes de dialogue intégrées utilisent les API Shell qui correspondent à leur action: PrintDialog, OpenFileDialog, SaveFileDialog, etc.
Vous devrez probablement créer manuellement cette fonctionnalité.
Si vous souhaitez afficher uniquement des types de fichiers spécifiques, le article suivant (avec le code source en C #) peut vous aider:
Il explique également les autres options disponibles pour "personnaliser" la boîte de dialogue FolderBrowser,
Les boîtes de dialogueOokiiimplémentent une boîte de dialogue de navigation dans les dossiers qui autorise les fichiers ou les dossiers en entrée et est disponible pour Windows Forms et WPF.
Ookii.Dialogs.Wpf
Ookii.Dialogs.WinForms
cela vous permettra de sélectionner des dossiers en utilisant OpenFileDialog
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;