Comment configurez-vous un OpenFileDialog pour sélectionner des dossiers?

251

Dans VS .NET, lorsque vous sélectionnez un dossier pour un projet, une boîte de dialogue qui ressemble à un OpenFileDialog ou SaveFileDialog s'affiche, mais est configurée pour accepter uniquement les dossiers. Depuis que j'ai vu ça, je veux savoir comment ça se passe. Je connais le FolderBrowserDialog, mais je n'ai jamais vraiment aimé cette boîte de dialogue. Il commence trop petit et ne me permet pas de saisir un chemin.

Je suis presque certain maintenant qu'il n'y a aucun moyen de le faire à partir de .NET, mais je suis tout aussi curieux de savoir comment vous le faites à partir de code non managé. À moins de réimplémenter complètement la boîte de dialogue à partir de zéro, comment modifiez-vous la boîte de dialogue pour avoir ce comportement?

Je voudrais également réaffirmer que je connais le FolderBrowserDialog mais parfois je n'aime pas l'utiliser, en plus d'être vraiment curieux de savoir comment configurer une boîte de dialogue de cette manière. Me dire de simplement utiliser le FolderBrowserDialog m'aide à maintenir une expérience d'interface utilisateur cohérente mais ne satisfait pas ma curiosité, donc cela ne comptera pas comme une réponse.

Ce n'est pas une chose spécifique à Vista non plus; J'ai vu cette boîte de dialogue depuis VS .NET 2003, donc c'est faisable dans Win2k et WinXP. Il s'agit moins d'une question «Je veux savoir comment faire correctement» et plus d'une question «J'ai été curieuse à ce sujet depuis que je voulais le faire dans VS 2003». Je comprends que la boîte de dialogue de fichier de Vista a une option pour le faire, mais cela fonctionne sous XP, donc je sais qu'ils ont fait quelque chose pour le faire fonctionner. Les réponses spécifiques à Vista ne sont pas des réponses, car Vista n'existe pas dans le contexte des questions.

Mise à jour: Je suis d' accepter la réponse de Scott Wisniewski parce qu'il est livré avec un échantillon de travail, mais je pense que Serge mérite pour pointer la personnalisation de dialogue (qui est certes désagréable de .NET , mais il fait le travail) et Mark Ransom pour déterminer que MS a probablement lancé une boîte de dialogue personnalisée pour cette tâche.

OwenP
la source
7
juste une solution simple de codeproject codeproject.com/Articles/44914/… [La clé pour que OpenFileDialog sélectionne à la fois des fichiers et des dossiers est de définir les propriétés ValidateNames et CheckFileExists sur false (dialog.ValidateNames = false; dialog.CheckFileExists = false) et définissez FileName sur un mot clé spécial pour vous assurer que les dossiers sont sélectionnés (dialog.FileName = "Folder Selection";).]
Riju
3
Soumettez ceci comme réponse, il a fait le travail pour mon projet.
CigarDoug
@Riju est dialog.FileName = "Folder Selection"censé être dialog.FileName = "Folder Selection."avec la période de fuite? de toute façon je ne peux pas le faire fonctionner en PowerShell sur le deuxième clic de "Open" de toute façon. Il continue de dire que le fichier est introuvable, même si CheckFileExists est censé être faux
ComradeJoecool
nvm, dans le paramètre powershell dialog.CheckFileExists = 0au lieu de faux résolu mon problème
ComradeJoecool
Avez-vous essayé les boîtes de dialogue Ookii pour WPF ?
C.Augusto Proiete

Réponses:

57

J'ai une boîte de dialogue que j'ai écrite appelée une boîte de dialogue OpenFileOrFolder qui vous permet d'ouvrir un dossier ou un fichier.

Si vous définissez sa valeur AcceptFiles sur false, il fonctionne uniquement en mode dossier d'acceptation.

Vous pouvez télécharger la source depuis GitHub ici

Scott Wisniewski
la source
4
Très intéressant, et certainement aussi compliqué que je l'avais imaginé. Avez-vous une chance de l'annoter et de montrer ce qu'il fait? Ceci, ainsi que d'autres commentaires, me porte à croire que MS vient probablement de lancer sa propre boîte de dialogue.
OwenP
1
J'obtiens l'erreur suivante lorsque j'essaie de créer votre solution ... malheureusement c ++ dans aucun de mes points forts ... L'erreur 1 ne peut pas ouvrir le fichier d'inclusion 'afxres.h'.
Ignacio Soler Garcia
1
@SoMoS, et d'autres avec le même problème: dans le fichier WindowsFormsApplication1.csproj éditez la ligne 100 pour qu'elle corresponde à votre configuration. Dans mon cas, j'ai dû changer "9.0" en "10.0" (deux fois) et supprimer "(x86)" (deux fois).
RenniePet
2
J'ai téléchargé le code (zip) et trouvé le fichier .h (C) dans, et compilé avec une erreur telle que ne peut pas ouvrir le fichier d'inclusion 'sal.h'.
Lei Yang
2
Cette solution ne fonctionne pas non plus sur VS2010 et VS2017!
AleX_
49

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 également rechercher des ordinateurs ou des imprimantes avec elle. Fonctionne comme le FBD intégré, mais ... mieux.

(EDIT: j'aurais dû souligner que cette boîte de dialogue peut être définie pour sélectionner des fichiers ou des dossiers.)

Code source complet (un court module C #). Libre. Licence MS-Public.

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;
}
Cheeso
la source
7
Désolé si j'ai offensé, c'est juste frustrant de poser une question et d'exprimer "je veux cette chose spécifique, pas ces autres choses" et d'avoir des gens qui suggèrent joyeusement la chose non demandée. Je voulais une boîte de dialogue de navigateur de fichiers, pas une boîte de dialogue de navigateur de dossiers.
OwenP
15
La façon dont la question est formulée, il me semble qu'elle demande une boîte de dialogue de sélection de dossier - n'est-ce pas le cas? Quoi qu'il en soit, c'est exactement ce que je cherchais +1
Tim
Certainement la meilleure réponse jusqu'à présent
Vasil Popov
1
Cela ne change rien au fait que la réponse est toujours une réponse de lien uniquement. Montrer comment utiliser le code hébergé sur une ressource hors site cesse d'être utile lorsque ce lien devient lui aussi temporairement ou définitivement indisponible. Les règles sont là pour une raison, et cette contribution est en conflit avec ces règles.
IInspectable
1
J'ai regardé cette réponse, et elle ne fait apparemment pas référence à une ressource hors site. Donc, "toutes les autres réponses" sont clairement fausses. Si vous pensez que je réagis de manière excessive, vous devriez peut-être soulever un problème lors de la méta pour discuter des règles. Je ne le ferai pas. Je vais juste les appliquer.
IInspectable
48

Il y a le pack de codes Windows API. Il y a beaucoup de choses liées au shell, y compris la CommonOpenFileDialogclasse (dans l' Microsoft.WindowsAPICodePack.Dialogsespace de noms). C'est la solution parfaite - la boîte de dialogue ouverte habituelle avec uniquement les dossiers affichés.

Voici un exemple d'utilisation:

CommonOpenFileDialog cofd = new CommonOpenFileDialog();
cofd.IsFolderPicker = true;
cofd.ShowDialog();

Malheureusement, Microsoft ne livre plus ce package, mais plusieurs personnes ont téléchargé officieusement des fichiers binaires sur NuGet. Un exemple peut être trouvé ici . Ce paquet est juste le truc spécifique au shell. Si vous en avez besoin, le même utilisateur a plusieurs autres packages qui offrent plus de fonctionnalités présentes dans le package d'origine.

Ken Wayne VanderLinde
la source
1
Je ne savais pas que c'était dans Windows API Code Pack - merci de l'avoir signalé.
Patrick Klug
10
La classe CommonOpenFileDialog n'existe que sur Windows Vista ou version ultérieure, donc lèvera une exception sur les anciens systèmes d'exploitation
Rachel
1
Pouvez-vous indiquer comment référencer le pack de codes API Windows?
jeff
1
La galerie d'archives a été retirée. , ou alors le lien dit .. Serait- ce le nouvel endroit pour cela?
Par défaut
3
Par ailleurs, la classe CommonOpenFileDialog se trouve dans l'espace de noms Microsoft.WindowsAPICodePack.Dialogs (il m'a fallu un certain temps pour le trouver).
morgb
35

Le package Ookii.Dialogs contient un wrapper géré autour de la nouvelle boîte de dialogue du navigateur de dossiers (de style Vista). Il se dégrade également gracieusement sur les anciens systèmes d'exploitation.

Christian Klauser
la source
2
Cool, c'est open source sous licence BSD!
Roman Starkov
7
le seul problème est que je ne me laisserai pas utiliser le profil client du framework .net comme cible.
Kugel
2
Très belle solution. C'est à mon avis LA meilleure réponse. Exactement ce que je cherchais depuis 3 ans.
Samuel
1
Autre problème avec cette solution: elle ne permet pas à l'utilisateur de coller un chemin inexistant. Un mineur, comparativement, mais toujours dommage.
Roman Starkov
1
Meilleure réponse pratique pour ceux qui veulent une OpenFileDialogboîte de dialogue de dossier de style.
aqua
27

Mieux vaut utiliser le FolderBrowserDialog pour cela.

using (FolderBrowserDialog dlg = new FolderBrowserDialog())
{
    dlg.Description = "Select a folder";
    if (dlg.ShowDialog() == DialogResult.OK)
    {
        MessageBox.Show("You selected: " + dlg.SelectedPath);
    }
}
Ryan Farley
la source
9
Je suis conscient qu'il est préférable d'utiliser un FolderBrowserDialog. Je suis curieux de savoir comment cela a été fait malgré tout. Le FolderBrowserDialog pue de plusieurs façons de toute façon; même sous Vista, il n'a pas la barre des lieux. C'est drôle, si c'est mieux, MS l'a évité jusqu'à présent dans les versions 3 VS.
OwenP
24
Le FolderBrowserDialog a de nombreux problèmes d'utilisation. Je n'envisagerais pas de le mettre dans une application. Voir mon article pour une boîte de dialogue qui a une bien meilleure convivialité
Scott Wisniewski
6
FolderBrowserDialog ne permet pas de: - taper / coller des chemins complets dans le champ de texte en bas - utiliser la barre "Liens favoris" sur Vista - utiliser la recherche sur Vista
decasteljau
89
Le FolderBrowserDialog est une interface utilisateur vraiment horrible.
mackenir
32
Sérieusement, les gens, VEUILLEZ arrêter de mettre cette boîte de dialogue ennuyeuse dans vos applications. Il a une interface utilisateur TRÈS MAUVAISE comme souligné par les commentaires précédents.
Roman Starkov
23

Après des heures de recherche, j'ai trouvé cette réponse par leetNightShade à une solution de travail .

Je pense qu'il y a trois choses qui rendent cette solution bien meilleure que toutes les autres.

  1. C'est simple à utiliser. Il vous suffit d'inclure deux fichiers (qui peuvent être combinés à un de toute façon) dans votre projet.
  2. Il revient au FolderBrowserDialog standard lorsqu'il est utilisé sur XP ou sur des systèmes plus anciens.
  3. L'auteur accorde la permission d'utiliser le code à toute fin que vous jugez appropriée.

    Il n'y a pas de licence en tant que telle, vous êtes libre de prendre et de faire avec le code ce que vous voulez.

Téléchargez le code ici .

Alex Essilfie
la source
@MattDavis: J'ai confirmé que cela fonctionne sur .NET Framework 4.0 (à la fois Standard et Client Profile). Assurez-vous simplement que les fichiers FolderSelectDialog.cs et Reflector.cs sont ajoutés à votre projet. Une chose cependant ... exécutez-vous sur Windows 8? J'ai testé sur un ordinateur Win7.
Alex Essilfie
@Alex Essilfie, vous avez raison. J'ai dû faire quelque chose de mal en l'intégrant dans mon projet. Je vais supprimer mon commentaire précédent pour plus de clarté.
Matt Davis
Parcourez plusieurs options et pensez que celle-ci est la meilleure. Je recommande.
Jaded
A travaillé dans Windows 10 pour moi. Bonne solution simple
David Wilton
doivent respecter le basculement dans les anciens systèmes
Mike M
17

Exact Audio Copy fonctionne de cette façon sur Windows XP. La boîte de dialogue d'ouverture de fichier standard s'affiche, mais le champ du nom de fichier contient le texte "Le nom de fichier sera ignoré".

Je devine juste ici, mais je soupçonne que la chaîne est injectée dans le contrôle d'édition de la zone de liste déroulante chaque fois qu'une modification importante est apportée à la boîte de dialogue. Tant que le champ n'est pas vide et que les indicateurs de dialogue sont définis pour ne pas vérifier l'existence du fichier, la boîte de dialogue peut être fermée normalement.

Edit: c'est beaucoup plus facile que je ne le pensais. Voici le code en C ++ / MFC, vous pouvez le traduire dans l'environnement de votre choix.

CFileDialog dlg(true, NULL, "Filename will be ignored", OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_PATHMUSTEXIST | OFN_READONLY, NULL, this);
dlg.DoModal();

Edit 2: Cela devrait être la traduction en C #, mais je ne parle pas couramment C #, alors ne me tirez pas dessus si cela ne fonctionne pas.

OpenFileDialog openFileDialog1 = new OpenFileDialog();

openFileDialog1.FileName = "Filename will be ignored";
openFileDialog1.CheckPathExists = true;
openFileDialog1.ShowReadOnly = false;
openFileDialog1.ReadOnlyChecked = true;
openFileDialog1.CheckFileExists = false;
openFileDialog1.ValidateNames = false;

if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
    // openFileDialog1.FileName should contain the folder and a dummy filename
}

Edit 3: enfin regardé la boîte de dialogue en question, dans Visual Studio 2005 (je n'y avais pas accès plus tôt). Ce n'est pas la boîte de dialogue d'ouverture de fichier standard! Si vous inspectez les fenêtres dans Spy ++ et les comparez à un fichier standard ouvert, vous verrez que la structure et les noms de classe ne correspondent pas. Lorsque vous regardez de plus près, vous pouvez également repérer certaines différences entre le contenu des boîtes de dialogue. Ma conclusion est que Microsoft a complètement remplacé la boîte de dialogue standard dans Visual Studio pour lui donner cette capacité. Ma solution ou quelque chose de similaire sera aussi proche que possible, à moins que vous ne souhaitiez coder la vôtre à partir de zéro.

Mark Ransom
la source
17

OK, permettez-moi d'essayer de connecter le premier point ;-) Jouer un peu avec Spy ++ ou Winspector montre que la zone de texte Dossier dans l'emplacement du projet VS est une personnalisation de la boîte de dialogue standard. Ce n'est pas le même champ que la zone de texte du nom de fichier dans une boîte de dialogue de fichier standard telle que celle du Bloc-notes.

À partir de là, je pense que VS cache le nom de fichier et les zones de texte / combobox de type de fichier et utilise un modèle de boîte de dialogue personnalisé pour ajouter sa propre partie au bas de la boîte de dialogue.

EDIT: Voici un exemple d'une telle personnalisation et comment le faire (dans Win32. Pas .NET):

m_ofn est la structure OPENFILENAME qui sous-tend la boîte de dialogue de fichier. Ajoutez ces 2 lignes:

  m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEDIALOG_IMPORTXLIFF);
  m_ofn.Flags |= OFN_ENABLETEMPLATE;

où IDD_FILEDIALOG_IMPORTXLIFF est un modèle de boîte de dialogue personnalisé qui sera ajouté au bas de la boîte de dialogue. Voir la partie en rouge ci-dessous. (source: apptranslator.com )texte alternatif

Dans ce cas, la pièce personnalisée n'est qu'une étiquette + un lien hypertexte mais il peut s'agir de n'importe quelle boîte de dialogue. Il pourrait contenir un bouton OK qui nous permettrait de valider la sélection du dossier uniquement.

Mais comment nous pourrions nous débarrasser de certains des contrôles dans la partie standard de la boîte de dialogue, je ne sais pas.

Plus de détails dans cet article MSDN .

Serge Wautier
la source
1
Cela ressemble à des explications que j'ai entendues dans le passé, mais je n'ai jamais vu de démonstration du concept. Existe-t-il des procédures pas à pas dans la documentation MSDN?
OwenP
10

Vous pouvez sous-classer la boîte de dialogue de fichier et accéder à tous ses contrôles. Chacun a un identifiant qui peut être utilisé pour obtenir son handle de fenêtre. Vous pouvez ensuite les afficher et les masquer, obtenir des messages de leur part sur les changements de sélection, etc. etc. Tout dépend de l'effort que vous souhaitez consacrer.

Nous avons fait le nôtre en utilisant le support de classe WTL et personnalisé la boîte de dialogue de fichier pour inclure une barre d'espaces personnalisée et des vues COM de plug-in.

MSDN fournit des informations sur la façon de procéder à l'aide de Win32, cet article CodeProject comprend un exemple et cet article CodeProject fournit un exemple .NET .

Jeff Yates
la source
10

Vous pouvez utiliser du code comme celui-ci

  • Le filtre est masquer les fichiers
  • Le nom de fichier est masquer le premier texte

Pour masquer la zone de texte avancée pour le nom de fichier, vous devez regarder OpenFileDialogEx

Le code:

{
    openFileDialog2.FileName = "\r";
    openFileDialog1.Filter = "folders|*.neverseenthisfile";
    openFileDialog1.CheckFileExists = false;
    openFileDialog1.CheckPathExists = false;
}
Avram
la source
Simple et c'est ce dont j'ai besoin pour Windows 7+
Hao Nguyen
OFN_NOVALIDATE est également requis dans les drapeaux
Goblin Alchemist
5

Je suppose que vous utilisez Vista sous VS2008? Dans ce cas, je pense que l' option FOS_PICKFOLDERS est utilisée lors de l'appel de la boîte de dialogue de fichier Vista IFileDialog . Je crains que dans le code .NET, cela implique beaucoup de code d'interopérabilité P / Invoke noueux pour fonctionner.

Duncan Smart
la source
1
Spécifique à Vista; J'ai vu cela pour la première fois sur VS 2003 sous Windows XP.
OwenP
2

Première solution

J'ai développé cela comme une version nettoyée de la boîte de dialogue de sélection de dossier de style .NET Win 7 par Bill Seddon de lyquidity.com (je n'ai aucune affiliation). (J'ai appris son code d' une autre réponse sur cette page ). J'ai écrit le mien parce que sa solution nécessite une classe de réflexion supplémentaire qui n'est pas nécessaire à cette fin, utilise un contrôle de flux basé sur des exceptions, ne met pas en cache les résultats de ses appels de réflexion. Notez que la VistaDialogclasse statique imbriquée est telle que ses variables de réflexion statique n'essaient pas d'être renseignées si la Showméthode n'est jamais appelée. Il revient à la boîte de dialogue pré-Vista si ce n'est pas dans une version Windows suffisamment élevée. Devrait fonctionner sous Windows 7, 8, 9, 10 et supérieur (théoriquement).

using System;
using System.Reflection;
using System.Windows.Forms;

namespace ErikE.Shuriken {
    /// <summary>
    /// Present the Windows Vista-style open file dialog to select a folder. Fall back for older Windows Versions
    /// </summary>
    public class FolderSelectDialog {
        private string _initialDirectory;
        private string _title;
        private string _fileName = "";

        public string InitialDirectory {
            get { return string.IsNullOrEmpty(_initialDirectory) ? Environment.CurrentDirectory : _initialDirectory; }
            set { _initialDirectory = value; }
        }
        public string Title {
            get { return _title ?? "Select a folder"; }
            set { _title = value; }
        }
        public string FileName { get { return _fileName; } }

        public bool Show() { return Show(IntPtr.Zero); }

        /// <param name="hWndOwner">Handle of the control or window to be the parent of the file dialog</param>
        /// <returns>true if the user clicks OK</returns>
        public bool Show(IntPtr hWndOwner) {
            var result = Environment.OSVersion.Version.Major >= 6
                ? VistaDialog.Show(hWndOwner, InitialDirectory, Title)
                : ShowXpDialog(hWndOwner, InitialDirectory, Title);
            _fileName = result.FileName;
            return result.Result;
        }

        private struct ShowDialogResult {
            public bool Result { get; set; }
            public string FileName { get; set; }
        }

        private static ShowDialogResult ShowXpDialog(IntPtr ownerHandle, string initialDirectory, string title) {
            var folderBrowserDialog = new FolderBrowserDialog {
                Description = title,
                SelectedPath = initialDirectory,
                ShowNewFolderButton = false
            };
            var dialogResult = new ShowDialogResult();
            if (folderBrowserDialog.ShowDialog(new WindowWrapper(ownerHandle)) == DialogResult.OK) {
                dialogResult.Result = true;
                dialogResult.FileName = folderBrowserDialog.SelectedPath;
            }
            return dialogResult;
        }

        private static class VistaDialog {
            private const string c_foldersFilter = "Folders|\n";

            private const BindingFlags c_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            private readonly static Assembly s_windowsFormsAssembly = typeof(FileDialog).Assembly;
            private readonly static Type s_iFileDialogType = s_windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog");
            private readonly static MethodInfo s_createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", c_flags);
            private readonly static MethodInfo s_onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", c_flags);
            private readonly static MethodInfo s_getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", c_flags);
            private readonly static MethodInfo s_setOptionsMethodInfo = s_iFileDialogType.GetMethod("SetOptions", c_flags);
            private readonly static uint s_fosPickFoldersBitFlag = (uint) s_windowsFormsAssembly
                .GetType("System.Windows.Forms.FileDialogNative+FOS")
                .GetField("FOS_PICKFOLDERS")
                .GetValue(null);
            private readonly static ConstructorInfo s_vistaDialogEventsConstructorInfo = s_windowsFormsAssembly
                .GetType("System.Windows.Forms.FileDialog+VistaDialogEvents")
                .GetConstructor(c_flags, null, new[] { typeof(FileDialog) }, null);
            private readonly static MethodInfo s_adviseMethodInfo = s_iFileDialogType.GetMethod("Advise");
            private readonly static MethodInfo s_unAdviseMethodInfo = s_iFileDialogType.GetMethod("Unadvise");
            private readonly static MethodInfo s_showMethodInfo = s_iFileDialogType.GetMethod("Show");

            public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory, string title) {
                var openFileDialog = new OpenFileDialog {
                    AddExtension = false,
                    CheckFileExists = false,
                    DereferenceLinks = true,
                    Filter = c_foldersFilter,
                    InitialDirectory = initialDirectory,
                    Multiselect = false,
                    Title = title
                };

                var iFileDialog = s_createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { });
                s_onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog });
                s_setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint) s_getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | s_fosPickFoldersBitFlag });
                var adviseParametersWithOutputConnectionToken = new[] { s_vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U };
                s_adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken);

                try {
                    int retVal = (int) s_showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle });
                    return new ShowDialogResult {
                        Result = retVal == 0,
                        FileName = openFileDialog.FileName
                    };
                }
                finally {
                    s_unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] });
                }
            }
        }

        // Wrap an IWin32Window around an IntPtr
        private class WindowWrapper : IWin32Window {
            private readonly IntPtr _handle;
            public WindowWrapper(IntPtr handle) { _handle = handle; }
            public IntPtr Handle { get { return _handle; } }
        }
    }
}

Il est utilisé comme tel dans un Windows Form:

var dialog = new FolderSelectDialog {
    InitialDirectory = musicFolderTextBox.Text,
    Title = "Select a folder to import music from"
};
if (dialog.Show(Handle)) {
    musicFolderTextBox.Text = dialog.FileName;
}

Vous pouvez bien sûr jouer avec ses options et les propriétés qu'il expose. Par exemple, il permet la sélection multiple dans la boîte de dialogue de style Vista.

Deuxième solution

Simon Mourier a donné une réponse qui montre comment faire exactement le même travail en utilisant l'interopérabilité directement avec l'API Windows, bien que sa version devrait être complétée pour utiliser l'ancienne boîte de dialogue de style si dans une ancienne version de Windows. Malheureusement, je n'avais pas encore trouvé son poste lorsque j'ai élaboré ma solution. Nommez votre poison!

ErikE
la source
Exemple d'utilisation similaire pour appeler cette boîte de dialogue fine en tant que boîte de dialogue (par exemple à partir d'applications de type console) avec une poignée vide: compile dès la sortie de la boîte: var dialog = new FolderSelectDialog {InitialDirectory = "C: \\", Title = "Select a dossier pour importer de la musique à partir de "}; if (dialog.Show ()) {string myFolder = dialog.FileName; }
Philm
Remarque: Mon exemple d'utilisation en tant que commentaire est difficile à lire, par conséquent: Modification la plus importante de "l'exemple" d'utilisation d'origine: Utilisez une virgule entre InitialDirectory et Title ..
Philm
1

Essayez celui-ci de Codeproject (crédit à Nitron):

Je pense que c'est la même boîte de dialogue dont vous parlez - peut-être que cela aiderait si vous ajoutez une capture d'écran?

bool GetFolder(std::string& folderpath, const char* szCaption=NULL, HWND hOwner=NULL)
{
    bool retVal = false;

    // The BROWSEINFO struct tells the shell how it should display the dialog.
    BROWSEINFO bi;
    memset(&bi, 0, sizeof(bi));

    bi.ulFlags   = BIF_USENEWUI;
    bi.hwndOwner = hOwner;
    bi.lpszTitle = szCaption;

    // must call this if using BIF_USENEWUI
    ::OleInitialize(NULL);

    // Show the dialog and get the itemIDList for the selected folder.
    LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);

    if(pIDL != NULL)
    {
        // Create a buffer to store the path, then get the path.
        char buffer[_MAX_PATH] = {'\0'};
        if(::SHGetPathFromIDList(pIDL, buffer) != 0)
        {
            // Set the string value.
            folderpath = buffer;
            retVal = true;
        }       

        // free the item id list
        CoTaskMemFree(pIDL);
    }

    ::OleUninitialize();

    return retVal;
}
demoncodemonkey
la source
images.google.com/… Faites des recherches en cas d'incertitude. J'ai décrit ce que je voulais et FolderBrowserDialog a déjà été disqualifié comme réponse.
OwenP
"Je connais le FolderBrowserDialog, mais je n'ai jamais vraiment aimé cette boîte de dialogue. Elle commence trop petite et ne me permet pas de saisir un chemin." Faites vous-même des recherches - vous pouvez y taper un chemin. Quoi qu'il en soit, je pense que c'est une question un peu ambiguë, alors bonne chance.
demoncodemonkey
@demoncodemonkey: vous ne pouvez pas taper une partie du chemin d'accès, puis naviguer vers la cible souhaitée. De loin pas aussi pratique que les options offertes par FileOpenDialog.
Treb
1

Sur Vista, vous pouvez utiliser IFileDialog avec le jeu d'options FOS_PICKFOLDERS. Cela entraînera l'affichage d'une fenêtre de type OpenFileDialog où vous pourrez sélectionner des dossiers:

var frm = (IFileDialog)(new FileOpenDialogRCW());
uint options;
frm.GetOptions(out options);
options |= FOS_PICKFOLDERS;
frm.SetOptions(options);

if (frm.Show(owner.Handle) == S_OK) {
    IShellItem shellItem;
    frm.GetResult(out shellItem);
    IntPtr pszString;
    shellItem.GetDisplayName(SIGDN_FILESYSPATH, out pszString);
    this.Folder = Marshal.PtrToStringAuto(pszString);
}

Pour les anciennes versions de Windows, vous pouvez toujours recourir à une astuce pour sélectionner un fichier dans un dossier.

Un exemple de travail qui fonctionne sur .NET Framework 2.0 et versions ultérieures peut être trouvé ici .

Josip Medved
la source
1

Vous pouvez utiliser du code comme celui-ci

Le filtre est une chaîne vide. Le nom de fichier est AnyName mais pas vide

        openFileDialog.FileName = "AnyFile";
        openFileDialog.Filter = string.Empty;
        openFileDialog.CheckFileExists = false;
        openFileDialog.CheckPathExists = false;
lantran
la source
6
Je sais que c'est un ancien message, mais pour le bien de tous ceux qui veulent l'essayer, cela ne fonctionne pas à moins que le répertoire que vous souhaitez ouvrir ne contienne absolument aucun répertoire enfant. Donc, si je veux laisser mon utilisateur parcourir un dossier et le sélectionner, et remplir le chemin du dossier dans une zone de texte, l'utilisateur ne pourra jamais sélectionner C: \ SomeParentDir si le répertoire C: \ SomeParentDir \ SomeChildDir existe, car en sélectionnant "Ouvrir "vous amène simplement au répertoire enfant.
Jim
Bien essayé .. mais cela se traduit par une interface utilisateur terrible car "AnyFile" dans la zone de texte n'attend que l'utilisateur pour remplacer son texte .. à part cela, l'utilisateur peut également sélectionner des fichiers - pas assez bon. mais bon essai ..
GY
-1

Je sais que la question portait sur la configuration de OpenFileDialogmais vu que Google m'a amené ici, je peux aussi souligner que si vous recherchez UNIQUEMENT des dossiers, vous devriez utiliser un FolderBrowserDialogAu lieu de répondre par une autre question SO ci-dessous

Comment spécifier le chemin en utilisant la boîte de dialogue d'ouverture de fichier dans vb.net?

AltF4_
la source
Trompeur. 1) Ce n'est pas le seul choix; 2) Ce n'est pas un bon choix dans la plupart des cas; Il nécessite toujours le moins de code, échangé par plus de temps passé par l'utilisateur final.
Meow Cat 2012