打开目录对话框

Ale*_*dra 260 filesystems wpf dialog

我希望用户选择一个目录,然后保存我将生成的文件.我知道在WPF中我应该使用OpenFileDialog来自Win32,但不幸的是,对话框需要选择文件 - 如果我只是单击"确定"而不选择一个文件,它将保持打开状态.我可以通过让用户选择一个文件然后去除路径以找出它所属的目录来"破解"该功能,但这最多是不直观的.以前有人见过这个吗?

Hei*_*nzi 390

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

using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{
    System.Windows.Forms.DialogResult result = dialog.ShowDialog();
}
Run Code Online (Sandbox Code Playgroud)

如果您希望窗口在某些WPF窗口上是模态的,请参阅如何从WPF应用程序使用FolderBrowserDialog这一问题.


编辑:如果你想要比简单,丑陋的Windows窗体FolderBrowserDialog更有趣的东西,有一些替代方案,允许您使用Vista对话框:

  • 第三方库,例如Ookii对话框(.NET 3.5)
  • Windows API的代码包壳牌:

    using Microsoft.WindowsAPICodePack.Dialogs;
    
    ...
    
    var dialog = new CommonOpenFileDialog();
    dialog.IsFolderPicker = true;
    CommonFileDialogResult result = dialog.ShowDialog();
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,此对话框在Windows Vista之前的操作系统上不可用,因此请务必先检查CommonFileDialog.IsPlatformSupported.

  • 请注意,这是一个糟糕的对话.您无法将路径复制并粘贴到其中,也不支持收藏夹文件夹.总的来说,我给它一个0分,并建议没有人使用它.除非在Windows Vista出现[更好的文件夹对话框]之前没有合理的替代方案(http://www.ookii.org/software/dialogs/images/folderbrowserdialog.png).[好的免费图书馆](http://www.ookii.org/software/dialogs/)显示了Vista +上的良好对话,以及XP上的糟糕对话. (74认同)
  • 不过,为什么WPF提供了一个很好的OpenFileDialog而没有OpenFolderDialog?这有点奇怪吗?为什么WPF缺少这里?是否有计划在WPF中为此对话框添加类? (66认同)
  • 不要忘记FolderBrowserDialog是一次性的. (13认同)
  • 注意,为了使用来自`WindowsAPICodePack`的`CommonOpenFileDialog`,你需要`Install-Package WindowsAPICodePack-Shell`.答案中提供的链接没有列出. (9认同)
  • Ookii对话框不是在.NET 4下编译的. (8认同)
  • "无法找到类型或命名空间CommonOpenFileDialog".这是2017年,我不能选择_folder_ (2认同)
  • @CodeNovice:因为我使用Common ** Open ** FileDialog。:-) (2认同)
  • 请注意(至少在 NET Core 3 中)`FolderBrowserDialog` 已更新为使用 *“Windows Vista 中引入的基于 COM 的较新控件”*,因此它的外观和行为现在不太令人反感。 (2认同)

adr*_*anm 42

我创建了一个UserControl,使用如下:

  <UtilitiesWPF:FolderEntry Text="{Binding Path=LogFolder}" Description="Folder for log files"/>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

和代码隐藏

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();
            }
        }
    }
 }
Run Code Online (Sandbox Code Playgroud)

  • 您可以在绑定中指定何时触发更新.默认情况下,它位于LostFocus上,但您可以告诉它也可以触发PropertyChanged上的更新. (4认同)
  • 然后还将针对每次击键更新绑定.如果用户在更新时进行某种验证(例如Directory.Exist),则可能会导致问题. (3认同)

Raf*_*ael 10

我正在使用Ookii对话框一段时间,它对WPF 很有用.

这是直接页面:

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


Zia*_*man 7

对于目录对话框以获取目录路径,首先添加引用System.Windows.Forms,然后单击Resolve,然后将此代码放入按钮单击中.

    var dialog = new FolderBrowserDialog();
    dialog.ShowDialog();
    folderpathTB.Text = dialog.SelectedPath;
Run Code Online (Sandbox Code Playgroud)

(folderpathTB是TextBox的名称,我将wana放在文件夹路径中,或者你也可以将它分配给字符串变量ie)

    string folder = dialog.SelectedPath;
Run Code Online (Sandbox Code Playgroud)

如果您获得FileName/path,只需在Button Click上执行此操作

    FileDialog fileDialog = new OpenFileDialog();
    fileDialog.ShowDialog();
    folderpathTB.Text = fileDialog.FileName;
Run Code Online (Sandbox Code Playgroud)

(folderpathTB是我在wana放置文件路径的TextBox的名称,或者你也可以将它分配给字符串变量)

注意:对于文件夹对话框,必须将System.Windows.Forms.dll添加到项目中,否则它将无法正常工作.


You*_*jae 7

可以在Nuget找到Ookii文件夹对话框.

PM> Install-Package Ookii.Dialogs

并且,示例代码如下.

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


小智 7

对于那些不想创建自定义对话框但仍然喜欢使用100%WPF方式并且不想使用单独的DDL,其他依赖项或过时的API的用户,我想到了使用“另存为”对话框的非常简单的技巧。

无需使用指令,您只需将以下代码复制粘贴即可!

它仍然应该非常用户友好,并且大多数人不会注意到。

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

当然,这是一个大技巧,但也许它将对您的使用效果很好...

在此示例中,我有一个文本框对象来包含结果路径,但是您可以删除相关的行,并根据需要使用返回值...

// 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;
}
Run Code Online (Sandbox Code Playgroud)

此骇客的唯一问题是:

  • 确认按钮仍然显示“保存”,而不是“选择目录”之类的内容,但是在我的情况下,我“保存”目录选择,因此它仍然有效...
  • 输入字段仍然显示“文件名”而不是“目录名”,但是我们可以说目录是一种文件类型...
  • 仍然有一个“另存为类型”下拉列表,但其值显示为“目录(* .this.directory)”,并且用户无法将其更改为其他内容,对我有用。

大多数人不会注意到这些,尽管如果微软想让头脑冷静的话,我绝对会喜欢使用官方的WPF方法,但是直到他们这样做之前,这就是我的临时解决方案。


Ste*_*nds 6

正如前面的答案中所述,FolderBrowserDialog是用于此目的的类。有些人对此对话框的外观和行为有(合理的)担忧。好消息是它在 NET Core 3.0 中进行了“现代化”,因此对于那些编写面向该版本或更高版本的 Windows 窗体或 WPF 应用程序的人来说,这是一个可行的选择(不过,如果仍在使用 NET Framework,那你就不走运了)。

在 .NET Core 3.0 中,Windows 窗体用户[原文如此]在 Windows Vista 中引入了一个较新的基于 COM 的控件: NET Core 3.0 中的 FolderBrowserDialog

在 NET Core WPF 应用程序中引用System.Windows.Forms需要编辑项目文件并添加以下行:

<UseWindowsForms>true</UseWindowsForms>
Run Code Online (Sandbox Code Playgroud)

这可以直接放在现有<UseWPF>元素之后。

那么这只是使用对话框的一种情况:

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)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

FolderBrowserDialog有一个RootFolder属性,应该是“设置浏览开始的根文件夹”,但无论我如何设置它都没有任何区别;SelectedPath似乎是用于此目的的更好的属性,但是需要尾随反斜杠。

此外,该ShowNewFolderButton属性似乎也被忽略,无论如何总是显示按钮。

  • 我希望我能不止一次地对此投赞成票!我在其他答案上浪费了很多时间,但没有解释如何在 .NET Core 中获取对话框。谢谢 (2认同)

Sau*_*oot 5

我在下面的链接上找到了下面的代码......并且它起作用了 选择文件夹对话框 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
}
Run Code Online (Sandbox Code Playgroud)


Jos*_*ega 5

我建议在 nugget 包中添加:

  Install-Package OpenDialog
Run Code Online (Sandbox Code Playgroud)

那么使用方法就是:

    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();
Run Code Online (Sandbox Code Playgroud)

这是文档: http://opendialog.codeplex.com/documentation

适用于文件、带过滤器的文件、文件夹等