web-dev-qa-db-fra.com

Sélectionnez un fichier ou un dossier dans la même boîte de dialogue dans .NET

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

31
barry

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.

12
Hans Passant

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
7
barry

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;
     }
5
Cheeso

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

5
stankovski

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

1
Araym

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 .

1
Mitch Wheat

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

1
Tom Anderson

Si vous souhaitez afficher uniquement des types de fichiers spécifiques, le article suivant (avec le code source en C #) peut vous aider: 

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

Il explique également les autres options disponibles pour "personnaliser" la boîte de dialogue FolderBrowser,

0
barry

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.

 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
Caio Proiete

cela vous permettra de sélectionner des dossiers en utilisant OpenFileDialog

        openFileDialog1.CheckFileExists = false;
        openFileDialog1.ValidateNames = false;
0
Jason P