web-dev-qa-db-fra.com

Dialogue de répertoire ouvert

Je veux que l'utilisateur sélectionne un répertoire dans lequel un fichier que je générerai ensuite sera sauvegardé. Je sais que dans WPF, je devrais utiliser la variable OpenFileDialog de Win32, mais malheureusement, la boîte de dialogue nécessite la sélection d'un fichier (s). Elle reste ouverte si je clique simplement sur OK sans en choisir un. Je pourrais "pirater" la fonctionnalité en laissant l’utilisateur choisir un fichier, puis en masquer le chemin pour déterminer le répertoire auquel il appartient, mais cela n’est pas tout à fait intuitif. Quelqu'un a-t-il déjà vu cela auparavant?

242
Alexandra

Vous pouvez utiliser la classe FolderBrowserDialog class intégrée pour cela. Ne vous inquiétez pas que cela se trouve dans l'espace de noms System.Windows.Forms.

using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{
    System.Windows.Forms.DialogResult result = dialog.ShowDialog();
}

Si vous souhaitez que la fenêtre soit modale sur une fenêtre WPF, consultez la question Comment utiliser un FolderBrowserDialog à partir d’une application WPF .


EDIT: Si vous voulez quelque chose d'un peu plus sophistiqué que le simple, dépliant Windows Forms FolderBrowserDialog, certaines alternatives vous permettent d'utiliser la boîte de dialogue Vista à la place:

  • Bibliothèques tierces, telles que Ookii dialogs (.NET 3.5)
  • Le Windows API Code Pack-Shell :

    using Microsoft.WindowsAPICodePack.Dialogs;
    
    ...
    
    var dialog = new CommonOpenFileDialog();
    dialog.IsFolderPicker = true;
    CommonFileDialogResult result = dialog.ShowDialog();
    

    Notez que cette boîte de dialogue n'est pas disponible sur les systèmes d'exploitation antérieurs à Windows Vista. Vérifiez donc d'abord CommonFileDialog.IsPlatformSupported.

367
Heinzi

J'ai créé un UserControl qui est utilisé comme ceci:

  <UtilitiesWPF:FolderEntry Text="{Binding Path=LogFolder}" Description="Folder for log files"/>

La source xaml ressemble à ceci:

<UserControl x:Class="Utilities.WPF.FolderEntry"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">
    <DockPanel>
        <Button Margin="0" Padding="0" DockPanel.Dock="Right" Width="Auto" Click="BrowseFolder">...</Button>
        <TextBox Height="Auto" HorizontalAlignment="Stretch" DockPanel.Dock="Right" 
           Text="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
    </DockPanel>
</UserControl>

et le code-behind

public partial class FolderEntry {
    public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(FolderEntry), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    public static DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(FolderEntry), new PropertyMetadata(null));

    public string Text { get { return GetValue(TextProperty) as string; } set { SetValue(TextProperty, value); }}

    public string Description { get { return GetValue(DescriptionProperty) as string; } set { SetValue(DescriptionProperty, value); } }

    public FolderEntry() { InitializeComponent(); }

    private void BrowseFolder(object sender, RoutedEventArgs e) {
        using (FolderBrowserDialog dlg = new FolderBrowserDialog()) {
            dlg.Description = Description;
            dlg.SelectedPath = Text;
            dlg.ShowNewFolderButton = true;
            DialogResult result = dlg.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK) {
                Text = dlg.SelectedPath;
                BindingExpression be = GetBindingExpression(TextProperty);
                if (be != null)
                    be.UpdateSource();
            }
        }
    }
 }
37
adrianm

J'utilise dialogues Ookii pendant un moment et ça marche bien pour WPF.

Voici la page directe:

http://www.ookii.org/Blog/new_download_ookiidialogs

8
Rafael

Pour que la boîte de dialogue Répertoire obtienne le chemin du répertoire, ajoutez d’abord la référence System.Windows.Forms, puis cliquez sur Résoudre, puis placez ce code en un clic de bouton.

    var dialog = new FolderBrowserDialog();
    dialog.ShowDialog();
    folderpathTB.Text = dialog.SelectedPath;

(folderpathTB est le nom de la zone de texte dans laquelle je mets le chemin du dossier, OR u peut l’affecter à une variable chaîne aussi).

    string folder = dialog.SelectedPath;

Et si vous voulez obtenir FileName/path, faites-le simplement en cliquant sur le bouton

    FileDialog fileDialog = new OpenFileDialog();
    fileDialog.ShowDialog();
    folderpathTB.Text = fileDialog.FileName;

(folderpathTB est le nom de la zone de texte dans laquelle je mets le chemin du fichier, OR u peut également l'affecter à une variable de chaîne)

Remarque: Pour la boîte de dialogue Dossier, la System.Windows.Forms.dll doit être ajoutée au projet, sinon cela ne fonctionnerait pas.

6
Zia Ur Rahman

La boîte de dialogue du dossier Ookii est disponible sur Nuget.

PM> Install-Package Ookii.Dialogs

Et, exemple de code est comme ci-dessous.

var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog();
if (dialog.ShowDialog(this).GetValueOrDefault())
{
    textBoxFolderPath.Text = dialog.SelectedPath;
}
5
Youngjae

Le meilleur moyen d’atteindre ce que vous voulez est de créer votre propre contrôle basé sur wpf ou d’utiliser un contrôle créé par d’autres personnes.
Pourquoi ? parce que l'utilisation de la boîte de dialogue winforms dans une application wpf aura un impact notable sur les performances (pour une raison quelconque)
je recommande ce projet
https://opendialog.codeplex.com/
ou Nuget: 

PM> Install-Package OpenDialog

il est très convivial avec MVVM et n'emballe pas le dialogue de winforms

4
bigworld12

Pour ceux qui ne veulent pas créer une boîte de dialogue personnalisée mais préfèrent tout de même une méthode 100% WPF et ne veulent pas utiliser de DDL séparés, de dépendances supplémentaires ou d'API obsolètes, j'ai conçu un hack très simple à l'aide de la boîte de dialogue Enregistrer sous. 

Aucune directive d'utilisation nécessaire, vous pouvez simplement copier-coller le code ci-dessous!

Il devrait toujours être très convivial et la plupart des gens ne le remarqueront jamais.

L'idée vient du fait que nous pouvons changer le titre de cette boîte de dialogue, cacher des fichiers et contourner le nom de fichier résultant assez facilement. 

C'est un gros bidouillage, c'est sûr, mais peut-être que ça fera l'affaire pour votre usage ...

Dans cet exemple, j'ai un objet textbox pour contenir le chemin résultant, mais vous pouvez supprimer les lignes associées et utiliser une valeur de retour si vous le souhaitez ... 

// Create a "Save As" dialog for selecting a directory (HACK)
var dialog = new Microsoft.Win32.SaveFileDialog();
dialog.InitialDirectory = textbox.Text; // Use current value for initial dir
dialog.Title = "Select a Directory"; // instead of default "Save As"
dialog.Filter = "Directory|*.this.directory"; // Prevents displaying files
dialog.FileName = "select"; // Filename will then be "select.this.directory"
if (dialog.ShowDialog() == true) {
    string path = dialog.FileName;
    // Remove fake filename from resulting path
    path = path.Replace("\\select.this.directory", "");
    path = path.Replace(".this.directory", "");
    // If user has changed the filename, create the new directory
    if (!System.IO.Directory.Exists(path)) {
        System.IO.Directory.CreateDirectory(path);
    }
    // Our final value is in path
    textbox.Text = path;
}

Les seuls problèmes avec ce hack sont:

  • Le bouton Acknowledge indique toujours "Enregistrer" au lieu de "Sélectionner le répertoire", mais dans un cas semblable à celui de la mine, je "Enregistrer" la sélection du répertoire afin qu'elle fonctionne toujours ... 
  • Le champ de saisie dit toujours "Nom du fichier" au lieu de "Nom du répertoire", mais on peut dire qu'un répertoire est un type de fichier ... 
  • Il y a toujours un menu déroulant "Enregistrer sous le type", mais sa valeur indique "Répertoire (* .this.directory)", et l'utilisateur ne peut pas le modifier pour autre chose, fonctionne pour moi ... 

La plupart des gens ne le remarqueront pas, même si je préférerais définitivement utiliser un moyen officiel de WPF si Microsoft leur en retirait la tête, mais tant qu'ils ne le font pas, c'est ma solution temporaire. 

4
Olivier St-L

J'ai trouvé le code ci-dessous sur le lien ci-dessous ... et cela a fonctionné Boîte de dialogue Sélectionner un dossier WPF

using Microsoft.WindowsAPICodePack.Dialogs;

var dlg = new CommonOpenFileDialog();
dlg.Title = "My Title";
dlg.IsFolderPicker = true;
dlg.InitialDirectory = currentDirectory;

dlg.AddToMostRecentlyUsedList = false;
dlg.AllowNonFileSystemItems = false;
dlg.DefaultDirectory = currentDirectory;
dlg.EnsureFileExists = true;
dlg.EnsurePathExists = true;
dlg.EnsureReadOnly = false;
dlg.EnsureValidNames = true;
dlg.Multiselect = false;
dlg.ShowPlacesList = true;

if (dlg.ShowDialog() == CommonFileDialogResult.Ok) 
{
  var folder = dlg.FileName;
  // Do something with selected folder string
}
4
Saurabh Raoot

Je suggérerais d'ajouter le paquet de pépites:

  Install-Package OpenDialog

Alors la façon de l'utiliser est:

    Gat.Controls.OpenDialogView openDialog = new Gat.Controls.OpenDialogView();
    Gat.Controls.OpenDialogViewModel vm = (Gat.Controls.OpenDialogViewModel)openDialog.DataContext;
    vm.IsDirectoryChooser = true;
    vm.Show();

    WPFLabel.Text = vm.SelectedFilePath.ToString();

Voici la documentation: http://opendialog.codeplex.com/documentation

Fonctionne pour les fichiers, les fichiers avec filtre, les dossiers, etc.

3
Jose Ortega

Le Ookii VistaFolderBrowserDialog est celui que vous voulez.

Si vous ne voulez que le navigateur de dossiers de Ooki Dialogs et rien d'autre alors téléchargez le fichier Source , sélectionnez les fichiers dont vous avez besoin pour le navigateur de dossiers (indice: 7 fichiers) et tout se passe bien sous .NET. 4.5.2. Je devais ajouter une référence à System.Drawing. Comparez les références du projet original au vôtre.

Comment déterminez-vous quels fichiers? Ouvrez votre application et Ookii dans différentes instances de Visual Studio. Ajoutez VistaFolderBrowserDialog.cs à votre application et continuez à ajouter des fichiers jusqu'à ce que les erreurs de génération disparaissent. Vous trouvez les dépendances dans le projet Ookii - Cliquez-droit sur celui que vous voulez suivre jusqu'à sa source (jeu de mots voulu).

Voici les fichiers dont vous avez besoin si vous êtes trop paresseux pour le faire ...

NativeMethods.cs
SafeHandles.cs
VistaFolderBrowserDialog.cs
\ Interop
   COMGuids.cs
   ErrorHelper.cs
   ShellComInterfaces.cs
   ShellWrapperDefinitions.cs

Modifiez la ligne 197 dans VistaFolderBrowserDialog.cs sauf si vous souhaitez inclure leur Resources.Resx

lancer la nouvelle InvalidOperationException (Properties.Resources.FolderBrowserDialogNoRootFolder);

throw new InvalidOperationException("Unable to retrieve the root folder.");

Ajouter leur avis de droit d'auteur à votre application selon leur license.txt

Le code dans \Ookii.Dialogs.Wpf.Sample\MainWindow.xaml.cs ligne 160-169 est un exemple que vous pouvez utiliser, mais vous devrez supprimer this, de MessageBox.Show(this, pour WPF.

Fonctionne sur ma machine [TM]

2
CAD bloke

Je sais que la question est ancienne, mais un moyen simple de le faire consiste à utiliser l'option FileDialog fournie par WPF et à utiliser System.IO.Path.GetDirectory (nom de fichier).

2
Gregory Eaton

Aucune de ces réponses n'a fonctionné pour moi (généralement, il manquait une référence ou quelque chose du genre)

Mais cela tout simplement fait:

Utilisation de FolderBrowserDialog dans l'application WPF

Ajoutez une référence à System.Windows.Forms et utilisez ce code:

  var dialog = new System.Windows.Forms.FolderBrowserDialog();
  System.Windows.Forms.DialogResult result = dialog.ShowDialog();

Pas besoin de rechercher les paquets manquants. Ou ajouter des classes énormes

Cela me donne un sélecteur de dossier moderne qui vous permet également de créer un nouveau dossier.

Je n'ai pas encore vu l'impact lorsque déployé sur d'autres machines

1
Nick.McDermaid

Vous pouvez utiliser qch comme ceci dans WPF. J'ai créé la méthode exemple. Vérifiez ci-dessous.

public string getFolderPath()
{
           // Create OpenFileDialog 
           Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

           OpenFileDialog openFileDialog = new OpenFileDialog();
           openFileDialog.Multiselect = false;

           openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
           if (openFileDialog.ShowDialog() == true)
           {
               System.IO.FileInfo fInfo = new System.IO.FileInfo(openFileDialog.FileName);
               return fInfo.DirectoryName;
           }
           return null;           
       }
0
koberone