我希望用户选择一个目录,将在该目录中保存随后将生成的文件。我知道在WPF中我应该使用OpenFileDialog
Win32中的from,但是不幸的是,该对话框要求选择文件-如果我只单击OK而不选择其中一个,它将保持打开状态。我可以通过让用户选择一个文件然后剥离路径以找出该文件属于哪个目录来“破解”该功能,但这充其量是不直观的。有人看过吗?
我希望用户选择一个目录,将在该目录中保存随后将生成的文件。我知道在WPF中我应该使用OpenFileDialog
Win32中的from,但是不幸的是,该对话框要求选择文件-如果我只单击OK而不选择其中一个,它将保持打开状态。我可以通过让用户选择一个文件然后剥离路径以找出该文件属于哪个目录来“破解”该功能,但这充其量是不直观的。有人看过吗?
Answers:
您可以为此使用内置的FolderBrowserDialog类。不要介意它在System.Windows.Forms
名称空间中。
using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
}
如果希望该窗口在某些WPF窗口上具有模式,请参阅问题如何从WPF应用程序中使用FolderBrowserDialog。
编辑:如果您要比普通的,丑陋的Windows窗体FolderBrowserDialog多花哨的东西,可以使用一些替代方法来使用Vista对话框:
using Microsoft.WindowsAPICodePack.Dialogs;
...
var dialog = new CommonOpenFileDialog();
dialog.IsFolderPicker = true;
CommonFileDialogResult result = dialog.ShowDialog();
请注意,此对话框在Windows Vista之前的操作系统上不可用,因此请务必先检查CommonFileDialog.IsPlatformSupported
。
CommonOpenFileDialog
from,WindowsAPICodePack
您需要Install-Package WindowsAPICodePack-Shell
。答案中提供的链接未列出该链接。
我创建了一个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();
}
}
}
}
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,然后解析,然后将此代码单击按钮。
var dialog = new FolderBrowserDialog();
dialog.ShowDialog();
folderpathTB.Text = dialog.SelectedPath;
(folderpathTB是我要在其中放置文件夹路径的TextBox的名称,或者u也可以将其分配给字符串变量,例如)
string folder = dialog.SelectedPath;
如果要获取文件名/路径,只需在按钮上单击即可
FileDialog fileDialog = new OpenFileDialog();
fileDialog.ShowDialog();
folderpathTB.Text = fileDialog.FileName;
(folderpathTB是我要在其中放置文件路径的TextBox的名称,或者您也可以将其分配给字符串变量)
注意:对于“文件夹对话框”,必须将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
}
实现所需目标的最佳方法是创建自己的基于wpf的控件,或使用别人制作的控件,
为什么?因为在wpf应用程序中使用winforms对话框时(由于某些原因)会显着影响性能,所以
我建议您使用
https://opendialog.codeplex.com/
或Nuget 这个项目:
PM> Install-Package OpenDialog
这对MVVM非常友好,并且没有包装winforms对话框
我建议添加金块包:
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
适用于文件,带过滤器的文件,文件夹等
VistaFolderBrowserDialog
是您想要的。如果只需要Ooki对话框中的文件夹浏览器,而没有其他东西,则下载Source,樱桃式选择文件夹浏览器所需的文件(提示:7个文件),它在.NET 4.5.2中可以正常运行。我必须添加对的引用System.Drawing
。将原始项目中的引用与您的引用进行比较。
您如何找出哪些文件?在不同的Visual Studio实例中打开您的应用程序和Ookii。添加VistaFolderBrowserDialog.cs
到您的应用程序并继续添加文件,直到构建错误消失。您可以在Ookii项目中找到依赖项-按住Control键并单击要跟踪的依赖项,再回到其源代码(双关语)。
如果您懒得执行以下操作,则需要这些文件...
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)。
这些答案都不适合我(通常缺少参考文献或类似内容)
但这很简单:
在WPF应用程序中使用FolderBrowserDialog
添加引用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;
}