Select folder dialog WPF

后端 未结 10 649
暗喜
暗喜 2020-11-28 19:32

I develop a WPF4 application and in my app I need to let the user select a folder where the application will store something (files, generated reports etc.).

My requ

相关标签:
10条回答
  • 2020-11-28 19:49

    Add The Windows API Code Pack-Shell to your project

    using Microsoft.WindowsAPICodePack.Dialogs;
    
    ...
    
    var dialog = new CommonOpenFileDialog();
    dialog.IsFolderPicker = true;
    CommonFileDialogResult result = dialog.ShowDialog();
    
    0 讨论(0)
  • 2020-11-28 19:58

    If you don't want to use Windows Forms nor edit manifest files, I came up with a very simple hack using WPF's SaveAs dialog for actually selecting a directory.

    No using directive needed, you may simply copy-paste the code below !

    It should still be very user-friendly and most people will never notice.

    The idea comes from the fact that we can change the title of that dialog, hide files, and work around the resulting filename quite easily.

    It is a big hack for sure, but maybe it will do the job just fine for your usage...

    In this example I have a textbox object to contain the resulting path, but you may remove the related lines and use a return value if you wish...

    // 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;
    }
    

    The only issues with this hack are :

    • Acknowledge button still says "Save" instead of something like "Select directory", but in a case like mines I "Save" the directory selection so it still works...
    • Input field still says "File name" instead of "Directory name", but we can say that a directory is a type of file...
    • There is still a "Save as type" dropdown, but its value says "Directory (*.this.directory)", and the user cannot change it for something else, works for me...

    Most people won't notice these, although I would definitely prefer using an official WPF way if microsoft would get their heads out of their asses, but until they do, that's my temporary fix.

    0 讨论(0)
  • 2020-11-28 19:58

    Based on Oyun's answer, it's better to use a dependency property for the FolderName. This allows (for example) binding to sub-properties, which doesn't work in the original. Also, in my adjusted version, the dialog shows selects the initial folder.

    Usage in XAML:

    <Button Content="...">
       <i:Interaction.Behaviors>
          <Behavior:FolderDialogBehavior FolderName="{Binding FolderPathPropertyName, Mode=TwoWay}"/>
        </i:Interaction.Behaviors>
    </Button>
    

    Code:

    using System.Windows;
    using System.Windows.Forms;
    using System.Windows.Interactivity;
    using Button = System.Windows.Controls.Button;
    
    public class FolderDialogBehavior : Behavior<Button>
    {
        #region Attached Behavior wiring
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.Click += OnClick;
        }
    
        protected override void OnDetaching()
        {
            AssociatedObject.Click -= OnClick;
            base.OnDetaching();
        }
        #endregion
    
        #region FolderName Dependency Property
        public static readonly DependencyProperty FolderName =
                DependencyProperty.RegisterAttached("FolderName",
                typeof(string), typeof(FolderDialogBehavior));
    
        public static string GetFolderName(DependencyObject obj)
        {
            return (string)obj.GetValue(FolderName);
        }
    
        public static void SetFolderName(DependencyObject obj, string value)
        {
            obj.SetValue(FolderName, value);
        }
        #endregion
    
        private void OnClick(object sender, RoutedEventArgs e)
        {
            var dialog = new FolderBrowserDialog();
            var currentPath = GetValue(FolderName) as string;
            dialog.SelectedPath = currentPath;
            var result = dialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                SetValue(FolderName, dialog.SelectedPath);
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-28 19:59

    Windows Presentation Foundation 4.5 Cookbook by Pavel Yosifovich on page 155 in the section on "Using the common dialog boxes" says:

    "What about folder selection (instead of files)? The WPF OpenFileDialog does not support that. One solution is to use Windows Forms' FolderBrowseDialog class. Another good solution is to use the Windows API Code Pack described shortly."

    I downloaded the API Code Pack from Windows® API Code Pack for Microsoft® .NET Framework Windows API Code Pack: Where is it?, then added references to Microsoft.WindowsAPICodePack.dll and Microsoft.WindowsAPICodePack.Shell.dll to my WPF 4.5 project.

    Example:

    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
    }
    
    0 讨论(0)
  • 2020-11-28 20:01

    Just to say one thing, WindowsAPICodePack can not open CommonOpenFileDialog on Windows 7 6.1.7600.

    0 讨论(0)
  • 2020-11-28 20:03

    Only such dialog is FileDialog. Its part of WinForms, but its actually only wrapper around WinAPI standard OS file dialog. And I don't think it is ugly, its actually part of OS, so it looks like OS it is run on.

    Other way, there is nothing to help you with. You either need to look for 3rd party implementation, either free (and I don't think there are any good) or paid.

    0 讨论(0)
提交回复
热议问题