OpenFileDialog
,但不幸的是,该对话框需要选择文件 - 如果我只是单击确定而没有选择文件,则它会保持打开状态。我可以通过让用户选择一个文件,然后剥离路径以找出它属于哪个目录来“破解”功能,但这最多也只是不直观的。有人见过这样做吗?OpenFileDialog
,但不幸的是,该对话框需要选择文件 - 如果我只是单击确定而没有选择文件,则它会保持打开状态。我可以通过让用户选择一个文件,然后剥离路径以找出它属于哪个目录来“破解”功能,但这最多也只是不直观的。有人见过这样做吗?System.Windows.Forms
命名空间中。using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
}
编辑:如果你想要比普通且丑陋的Windows Forms FolderBrowserDialog更加精致的东西,那么有一些替代方案可以让你使用Vista对话框:
第三方库,例如Ookii对话框(.NET 4.5+)
using Microsoft.WindowsAPICodePack.Dialogs;
...
var dialog = new CommonOpenFileDialog();
dialog.IsFolderPicker = true;
CommonFileDialogResult result = dialog.ShowDialog();
请注意,此对话框在早于Windows Vista的操作系统上不可用,因此请先检查CommonFileDialog.IsPlatformSupported
。
WindowsAPICodePack
中的CommonOpenFileDialog
,您需要安装WindowsAPICodePack-Shell
软件包。答案提供的链接没有列出这一点。 - Nikola Novak我创建了一个用户控件,可以像这样使用:
<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();
}
}
}
}
be.UpdateSource
?在依赖属性中,改变通知不应该是自动的吗? - Heinzi如前面的回答所述,FolderBrowserDialog
是用于此问题的类。一些人对此对话框的外观和行为有(合理的)担忧。好消息是,在.NET Core 3.0中它“现代化”了,因此现在是一种可行的选择,适用于编写针对该版本或更高版本的Windows Forms或WPF应用程序的人(如果仍在使用NET Framework,则没有希望)。
在.NET Core 3.0中,Windows Forms用户使用了一个新的基于COM的控件,该控件在Windows Vista中首次引入:
要在NET Core WPF应用程序中引用System.Windows.Forms
,需要编辑项目文件并添加以下行:
<UseWindowsForms>true</UseWindowsForms>
这可以直接放置在现有的<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)
{
...
}
FolderBrowserDialog
有一个RootFolder
属性,据说可以“设置浏览开始的根文件夹”,但是不管我设置成什么都没有任何区别;SelectedPath
似乎更适合用于此目的,但需要包含尾部反斜杠。
此外,ShowNewFolderButton
属性似乎也被忽略了,该按钮始终显示。
Ookii文件夹对话框可以在Nuget上找到。
PM> Install-Package Ookii.Dialogs.Wpf
示例代码如下。
var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog();
if (dialog.ShowDialog(this).GetValueOrDefault())
{
textBoxFolderPath.Text = dialog.SelectedPath;
}
如何使用该工具的更多信息,请参考https://github.com/augustoproiete/ookii-dialogs-wpf
对于那些不想创建自定义对话框,但仍然希望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;
}
这种方法唯一的问题是:
大多数人不会注意到这些问题,尽管我肯定更喜欢使用官方的WPF方式,如果微软能够理智些,但在他们采取行动之前,这就是我的临时解决方案。
dialog.FileName = "select"; // Filename will then be "select.this.directory"
的实现方式之前,感觉有点混乱,对于非技术终端用户来说可能会有些困惑。但除此之外,这是一个有趣的、零依赖的技巧。 - ruffin若要获取文件夹路径,请先引用 System.Windows.Forms,然后解析,最后在按钮单击事件中加入以下代码。
var dialog = new FolderBrowserDialog();
dialog.ShowDialog();
folderpathTB.Text = dialog.SelectedPath;
string folder = dialog.SelectedPath;
如果您想获取文件名/路径,只需在按钮单击时执行以下操作
FileDialog fileDialog = new OpenFileDialog();
fileDialog.ShowDialog();
folderpathTB.Text = fileDialog.FileName;
(folderpathTB是我想放置文件路径的文本框的名称,或者您也可以将它分配给字符串变量)
注意:对于文件夹对话框,必须将System.Windows.Forms.dll添加到项目中,否则它将无法工作。
我在以下链接中找到了下面的代码...并且它可以工作:选择文件夹对话框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
}
Install-Package OpenDialog
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();
实现您想要的最佳方法是创建基于wpf的自定义控件,或使用其他人制作的控件。
为什么?因为在wpf应用程序中使用winforms对话框会产生明显的性能影响(由于某种原因)。
我推荐这个项目:
https://opendialog.codeplex.com/
或者Nuget:
PM> Install-Package OpenDialog
它非常支持MVVM模式,并且不会包装WinForms对话框。