我希望用户选择一个目录,然后保存我将生成的文件。我知道在WPF中我应该使用Win32中的OpenFileDialog
,但不幸的是对话框需要选择文件 - 如果我只是单击OK而不选择一个文件,它将保持打开状态。我可以通过让用户选择一个文件然后去除路径以找出它所属的目录来“破解”这个功能,但最好不直观。有没有人见过这个呢?
您可以使用内置的FolderBrowserDialog类。不要介意它在System.Windows.Forms
名称空间中。
using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
}
如果您希望窗口在某个WPF窗口上是模态的,请参阅问题How to use a FolderBrowserDialog from a WPF application。
编辑:如果你想要一些比简单,丑陋的Windows窗体FolderBrowserDialog更有趣的东西,有一些替代方案,允许您使用Vista对话框:
using Microsoft.WindowsAPICodePack.Dialogs;
...
var dialog = new CommonOpenFileDialog();
dialog.IsFolderPicker = true;
CommonFileDialogResult result = dialog.ShowDialog();
请注意,此对话框在Windows Vista之前的操作系统上不可用,因此请务必先检查CommonFileDialog.IsPlatformSupported
。VistaFolderBrowserDialog
is the one you want.如果你只想要来自Ooki Dialogs的文件夹浏览器而不是download the Source,请选择文件夹浏览器所需的文件(提示:7个文件),并在.NET 4.5.2中构建它。我不得不添加对System.Drawing
的引用。将原始项目中的引用与您的引用进行比较。
你怎么弄清楚哪些文件?在不同的Visual Studio实例中打开您的应用程序和Ookii。将VistaFolderBrowserDialog.cs
添加到您的应用程序并继续添加文件,直到构建错误消失。您可以在Ookii项目中找到依赖项 - 控制 - 单击要跟踪其源(双关语)的依赖项。
如果你太懒,那么你需要的文件......
NativeMethods.cs
SafeHandles.cs
VistaFolderBrowserDialog.cs
\ Interop
COMGuids.cs
ErrorHelper.cs
ShellComInterfaces.cs
ShellWrapperDefinitions.cs
在VistaFolderBrowserDialog.cs
编辑第197行,除非你想包括他们的Resources.Resx
抛出新的InvalidOperationException(Properties.Resources.FolderBrowserDialogNoRootFolder);
throw new InvalidOperationException("Unable to retrieve the root folder.");
根据他们的license.txt
将他们的版权声明添加到您的应用中
\Ookii.Dialogs.Wpf.Sample\MainWindow.xaml.cs
第160-169行中的代码是您可以使用的示例,但您需要从this,
中删除MessageBox.Show(this,
以获取WPF。
适用于我的机器[TM]
我知道这是一个老问题,但一个简单的方法是使用WPF提供的FileDialog选项并使用System.IO.Path.GetDirectory(filename)。
这些答案都不适用于我(通常有一个缺失的参考或类似的东西)
但这很简单:
Using FolderBrowserDialog in WPF application
添加对System.Windows.Forms
的引用并使用以下代码:
var dialog = new System.Windows.Forms.FolderBrowserDialog();
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
无需追踪丢失的包裹。或者添加大量的课程
这给了我一个现代文件夹选择器,它还允许您创建一个新文件夹
我还没有看到部署到其他机器时的影响
你可以在WPF中使用像这样的smth。我已经创建了示例方法。检查下面。
public string getFolderPath()
{
// Create OpenFileDialog
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Multiselect = false;
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
if (openFileDialog.ShowDialog() == true)
{
System.IO.FileInfo fInfo = new System.IO.FileInfo(openFileDialog.FileName);
return fInfo.DirectoryName;
}
return null;
}
我创建了一个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的人,我想出了一个非常简单的黑客使用“另存为”对话框。
不需要使用指令,您可以简单地复制粘贴下面的代码!
它应该仍然是非常用户友好的,大多数人永远不会注意到。
这个想法来自于我们可以更改对话框的标题,隐藏文件以及轻松处理生成的文件名。
这肯定是一个很大的黑客,但也许它可以很好地满足你的使用......
在这个例子中,我有一个文本框对象来包含结果路径,但如果你愿意,你可以删除相关的行并使用返回值...
// 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方式,如果微软会从他们的屁股中脱颖而出,但直到他们这样做,这是我的临时修复。
对于目录对话框以获取目录路径,首先添加引用System.Windows.Forms,然后单击Resolve,然后将此代码放入按钮单击中。
var dialog = new FolderBrowserDialog();
dialog.ShowDialog();
folderpathTB.Text = dialog.SelectedPath;
(folderpathTB是TextBox的名称,我将wana放在文件夹路径中,或者你也可以将它分配给字符串变量,即)
string folder = dialog.SelectedPath;
如果你想获得FileName / path,只需在Button Click上执行此操作
FileDialog fileDialog = new OpenFileDialog();
fileDialog.ShowDialog();
folderpathTB.Text = fileDialog.FileName;
(folderpathTB是我在wana放置文件路径的TextBox的名称,或者你也可以将它分配给字符串变量)
注意:对于文件夹对话框,必须将System.Windows.Forms.dll添加到项目中,否则它将无法正常工作。
可以在Nuget找到Ookii文件夹对话框。
PM> Install-Package Ookii.Dialogs
并且,示例代码如下。
var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog();
if (dialog.ShowDialog(this).GetValueOrDefault())
{
textBoxFolderPath.Text = dialog.SelectedPath;
}
实现您想要的最佳方法是创建自己的基于wpf的控件,或者使用由其他人制作的控件 为什么?因为在wpf应用程序中使用winforms对话框时会有明显的性能影响(由于某种原因) 我推荐这个项目 https://opendialog.codeplex.com/ 或Nuget:
PM> Install-Package OpenDialog
它非常友好的MVVM,并没有包装winforms对话框
我在下面的链接上找到了以下代码......它工作了Select folder dialog 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
}
我建议,添加nuget包:
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();
这是文档:http://opendialog.codeplex.com/documentation
适用于文件,带过滤器的文件,文件夹等