我希望用户选择一个目录,我将生成的文件将保存在其中。我知道在WPF中,我应该使用Win32中的OpenFileDialog,但不幸的是,对话框需要选择文件-如果我只是单击确定而不选择一个,它就会保持打开。我可以通过让用户选择一个文件,然后剥离路径以找出它属于哪个目录来“hack”该功能,但这充其量是不直观的。有人见过这种情况吗?


当前回答

我创建了一个UserControl,它是这样使用的:

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

xaml源代码如下所示:

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

还有隐藏代码

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

其他回答

对于那些不想创建自定义对话框,但仍然喜欢100% WPF方式,不想使用单独的ddl,额外的依赖项或过时的api的人,我提出了一个非常简单的hack,使用另存为对话框。

不需要使用指令,你可以简单地复制粘贴下面的代码!

它应该仍然是非常友好的,大多数人都不会注意到。

这个想法来自于这样一个事实,我们可以改变对话框的标题,隐藏文件,并很容易地处理产生的文件名。

这是一个大黑客肯定,但也许它会做的工作只是为了你的使用…

在这个例子中,我有一个文本框对象来包含结果路径,但是如果你愿意,你可以删除相关的行,并使用一个返回值…

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

这个黑客唯一的问题是:

确认按钮仍然显示“保存”而不是“选择目录”,但在像我这样的情况下,我“保存”目录选择,所以它仍然有效…… 输入字段仍然显示“文件名”而不是“目录名”,但我们可以说目录是一种文件类型… 仍然有一个“另存为类型”下拉菜单,但它的值是“目录(*.this.directory)”,用户不能更改它为其他东西,对我来说…

大多数人不会注意到这些,尽管我肯定更喜欢使用官方的WPF方式,如果微软能把他们的头从他们的屁股里拿出来,但在他们这样做之前,这是我的临时修复。

这些答案都不适合我(通常是缺少参考资料或类似的东西)

但这很简单:

在WPF应用程序中使用FolderBrowserDialog

添加一个对System.Windows.Forms的引用,并使用以下代码:

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

没有必要去寻找丢失的包裹。或者添加大量的类

这为我提供了一个现代化的文件夹选择器,还允许您创建一个新文件夹

我还没有看到部署到其他机器上的影响

为此,您可以使用内置的FolderBrowserDialog类。不要介意它在System.Windows.Forms命名空间中。

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

如果你想让窗口在某些WPF窗口上是模态的,请参阅如何从WPF应用程序中使用FolderBrowserDialog问题。


编辑:如果你想要一些比普通的、丑陋的Windows窗体文件夹浏览器对话框更花哨的东西,有一些选择允许你使用Vista对话框:

第三方库,如Ookii对话框(。NET 4.5 +) Windows API代码包- shell: 使用Microsoft.WindowsAPICodePack.Dialogs; ... var dialog = new CommonOpenFileDialog(); 对话框。IsFolderPicker = true; commonfiledialgresult result = dialog.ShowDialog(); 注意,这个对话框在Windows Vista之前的操作系统上是不可用的,所以一定要检查CommonFileDialog。IsPlatformSupported第一。

Ookii对话框包括一个选择文件夹(而不是文件)的对话框:

https://github.com/ookii-dialogs

我在下面的链接上找到了下面的代码…这个方法奏效了 选择文件夹对话框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
}