我希望用户选择一个目录,我将生成的文件将保存在其中。我知道在WPF中,我应该使用Win32中的OpenFileDialog,但不幸的是,对话框需要选择文件-如果我只是单击确定而不选择一个,它就会保持打开。我可以通过让用户选择一个文件,然后剥离路径以找出它属于哪个目录来“hack”该功能,但这充其量是不直观的。有人见过这种情况吗?
当前回答
正如前面的回答中所述,FolderBrowserDialog是为此使用的类。有些人(有理由)担心这个对话框的外观和行为。好消息是它在NET Core 3.0中被“现代化”了,所以现在对于那些针对该版本或更高版本编写Windows窗体或WPF应用程序的人来说是一个可行的选择(如果你仍然使用NET Framework,那就不走运了)。
在。net Core 3.0中,Windows窗体用户[原文如此]在Windows Vista中引入了一个新的基于com的控件:
要在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属性似乎也被忽略了,按钮总是显示不管。
其他回答
对于那些不想创建自定义对话框,但仍然喜欢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方式,如果微软能把他们的头从他们的屁股里拿出来,但在他们这样做之前,这是我的临时修复。
Ookii对话框包括一个选择文件夹(而不是文件)的对话框:
https://github.com/ookii-dialogs
这些答案都不适合我(通常是缺少参考资料或类似的东西)
但这很简单:
在WPF应用程序中使用FolderBrowserDialog
添加一个对System.Windows.Forms的引用,并使用以下代码:
var dialog = new System.Windows.Forms.FolderBrowserDialog();
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
没有必要去寻找丢失的包裹。或者添加大量的类
这为我提供了一个现代化的文件夹选择器,还允许您创建一个新文件夹
我还没有看到部署到其他机器上的影响
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Gearplay
{
/// <summary>
/// Логика взаимодействия для OpenFolderBrows.xaml
/// </summary>
public partial class OpenFolderBrows : Page
{
internal string SelectedFolderPath { get; set; }
public OpenFolderBrows()
{
InitializeComponent();
Selectedpath();
InputLogicalPathCollection();
}
internal void Selectedpath()
{
Browser.Navigate(@"C:\");
Browser.Navigated += Browser_Navigated;
}
private void Browser_Navigated(object sender, NavigationEventArgs e)
{
SelectedFolderPath = e.Uri.AbsolutePath.ToString();
//MessageBox.Show(SelectedFolderPath);
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
}
string [] testing { get; set; }
private void InputLogicalPathCollection()
{ // add Menu items for Cotrol
string[] DirectoryCollection_Path = Environment.GetLogicalDrives(); // Get Local Drives
testing = new string[DirectoryCollection_Path.Length];
//MessageBox.Show(DirectoryCollection_Path[0].ToString());
MenuItem[] menuItems = new MenuItem[DirectoryCollection_Path.Length]; // Create Empty Collection
for(int i=0;i<menuItems.Length;i++)
{
// Create collection depend how much logical drives
menuItems[i] = new MenuItem();
menuItems[i].Header = DirectoryCollection_Path[i];
menuItems[i].Name = DirectoryCollection_Path[i].Substring(0,DirectoryCollection_Path.Length-1);
DirectoryCollection.Items.Add(menuItems[i]);
menuItems[i].Click += OpenFolderBrows_Click;
testing[i]= DirectoryCollection_Path[i].Substring(0, DirectoryCollection_Path.Length - 1);
}
}
private void OpenFolderBrows_Click(object sender, RoutedEventArgs e)
{
foreach (string str in testing)
{
if (e.OriginalSource.ToString().Contains("Header:"+str)) // Navigate to Local drive
{
Browser.Navigate(str + @":\");
}
}
}
private void Goback_Click(object sender, RoutedEventArgs e)
{// Go Back
try
{
Browser.GoBack();
}catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void Goforward_Click(object sender, RoutedEventArgs e)
{ //Go Forward
try
{
Browser.GoForward();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void FolderForSave_Click(object sender, RoutedEventArgs e)
{
// Separate Click For Go Back same As Close App With send string var to Main Window ( Main class etc.)
this.NavigationService.GoBack();
}
}
}
实现你想要的最好的方法是创建你自己的基于wpf的控件,或者使用别人做的控件 为什么?因为在WPF应用程序中使用winforms对话框会有明显的性能影响(出于某种原因) 我推荐这个项目 https://opendialog.codeplex.com/ 或Nuget:
PM> Install-Package OpenDialog
它是非常MVVM友好的,它没有包装winforms对话框