316 votes

Dialogue d'ouverture de répertoire

Je veux que l'utilisateur sélectionne un répertoire où sera enregistré un fichier que je vais ensuite générer. Je sais que, dans WPF, je dois utiliser la fonction OpenFileDialog à partir de Win32, mais malheureusement, la boîte de dialogue exige que le ou les fichiers soient sélectionnés - elle reste ouverte si je clique simplement sur OK sans en choisir un. Je pourrais "bidouiller" la fonctionnalité en laissant l'utilisateur choisir un fichier et ensuite dépouiller le chemin pour déterminer à quel répertoire il appartient, mais ce n'est pas très intuitif. Quelqu'un a-t-il déjà vu cela ?

0 votes

0 votes

2 votes

440voto

Heinzi Points 66519

Vous pouvez utiliser la fonction intégrée FolderBrowserDialog pour cela. Ne faites pas attention au fait que c'est dans la classe System.Windows.Forms espace de noms.

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

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


EDITAR: Si vous voulez quelque chose d'un peu plus sophistiqué que l'affreux FolderBrowserDialog de Windows Forms, il existe des alternatives qui vous permettent d'utiliser la boîte de dialogue Vista à la place :

  • Des bibliothèques tierces, telles que Dialogues Ookii (.NET 4.5+)

  • El Pack de code API Windows-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. CommonFileDialog.IsPlatformSupported d'abord.

89 votes

Notez que c'est un dialogue affreux. Vous ne pouvez pas y copier et coller un chemin, et elle ne prend pas en charge les dossiers favoris. Globalement, je lui donne un 0 sur 5 et je recommande à tout le monde de ne jamais l'utiliser. Sauf qu'il n'y avait pas d'alternative raisonnable avant la sortie de Windows Vista avec la boîte de dialogue des dossiers, bien meilleure . Il existe bonnes bibliothèques gratuites qui montrent le bon dialogue sur Vista+, et le mauvais sur XP.

0 votes

@MohamedSakherSawan : Vous n'avez pas besoin d'utiliser Windows Forms, vous devez simplement utiliser une classe de l'espace de nom System.Windows.Forms.

1 votes

Je sais, mais notre objectif est de supprimer la référence à l'assemblage des formulaires Windows de notre application WPF, car les formulaires Windows ont causé de nombreux problèmes et un blocage dans notre application dans le passé, ce blocage a consommé d'énormes ressources pour être résolu !

48voto

adrianm Points 7067

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();
            }
        }
    }
 }

1 votes

+1, bel exemple sur la façon d'écrire un UserControl. Une question : Pourquoi avez-vous besoin be.UpdateSource ? Les notifications de changement ne devraient-elles pas être automatiques dans les propriétés de dépendance ?

4 votes

Vous pourriez spécifier dans la liaison quand déclencher les mises à jour. Par défaut, c'est lors du LostFocus, mais vous pouvez également lui demander de déclencher les mises à jour lors des PropertyChanged.

3 votes

La liaison sera alors également mise à jour pour chaque frappe de touche. Si l'utilisateur effectue une sorte de validation lors de la mise à jour (par exemple Directory.Exist), cela peut poser des problèmes.

24voto

Steven Rands Points 3102

Comme indiqué dans les réponses précédentes, FolderBrowserDialog est la classe à utiliser pour cela. Certaines personnes sont préoccupées (à juste titre) par l'apparence et le comportement de cette boîte de dialogue. La bonne nouvelle est qu'elle a été "modernisé" dans NET Core 3.0 Il s'agit donc maintenant d'une option viable pour ceux qui écrivent des applications Windows Forms ou WPF ciblant cette version ou une version ultérieure (vous n'avez pas de chance si vous utilisez toujours NET Framework).

Dans .NET Core 3.0, les utilisateurs de Windows Forms [sic] un contrôle plus récent basé sur COM qui a été introduit dans Windows Vista : FolderBrowserDialog in NET Core 3.0

A référence System.Windows.Forms dans une application WPF NET Core il est nécessaire d'éditer le fichier du projet et d'ajouter la ligne suivante :

<UseWindowsForms>true</UseWindowsForms>

Elle peut être placée directement après l'actuelle <UseWPF> élément.

Il ne reste plus qu'à utiliser le dialogue :

using System;
using System.Windows.Forms;

...

using var dialog = new FolderBrowserDialog
{
    Description = "Time to select a folder",
    UseDescriptionForTitle = true,
    SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
        + Path.DirectorySeparatorChar,
    ShowNewFolderButton = true
};

if (dialog.ShowDialog() == DialogResult.OK)
{
    ...
}

FolderBrowserDialog a un RootFolder qui est censé "définit le dossier racine à partir duquel la navigation commence". mais quel que soit le réglage que j'ai fait, ça n'a fait aucune différence ; SelectedPath semble être la meilleure propriété à utiliser dans ce but, mais la barre oblique inversée de fin est nécessaire.

En outre, le ShowNewFolderButton semble également être ignorée, le bouton est toujours affiché quoi qu'il en soit.

22voto

Youngjae Points 1457

Le dialogue du dossier Ookii se trouve à Nuget.

PM> Install-Package Ookii.Dialogs.Wpf

Et, l'exemple de code est le suivant.

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

Plus d'informations sur la façon de l'utiliser : https://github.com/augustoproiete/ookii-dialogs-wpf

14voto

Rafael Points 68

Dialogues d'Ookii comprend une boîte de dialogue permettant de sélectionner un dossier (au lieu d'un fichier) :

Ookii Dialogs Select Folder Screenshot

https://github.com/ookii-dialogs

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X