.NET 8 中的 WPF File Dialog 改进

作者:Dipesh Kumar

排版:Alan Wang

我们很高兴宣布从 .NET 8 Preview 7 开始,对 WPF 中的通用文件对话框 API 进行了一系列新的改进。其中包括迄今为止存储库中投票最多的 API 建议 -- 允许用户选择文件夹的 OpenFolderDialog 控件 -- 以及文件对话框上支持新的用户场景的几个新属性,例如单独保存状态、限制文件夹导航等。

到目前为止,WPF 支持 Windows Vista 中引入的 Common Item Dialog API 以及在旧操作系统上运行时遗留的 GetOpenFileNameGetSaveFileName 函数。作为此更新的一部分,由于 .NET 支持的所有 Windows 版本都只使用较新的 API,因此对话框代码被清理,遗留函数的基础架构被删除。在兼容模式下运行的应用程序将继续工作,但它们将使用 Common Item Dialog API 来呈现通用对话框。

OpenFolderDialog

WPF 社区中用于选择文件夹的对话框是最受欢迎的功能之一。示例用例包括在 Visual Studio 或 Visual Studio Code 中打开文件夹、在 Outlook 中保存附件、将压缩文件解压到用户选择的文件夹中。到目前为止,开发人员必须使用 Windows Forms或依赖第三方库才能提供这种体验,这引入了不必要的依赖关系从而不适合现有的对话框模型。

从 .NET 8 开始,我们在 WPF 中提供了对此对话框的本机支持。社区中已经有很多关于如何将此功能集成到现有文件对话框模型中的讨论,试图平衡兼容性要求、简洁的架构设计和底层 API 结构。最终,我们决定在继承链中引入一个新的基类 CommonItemDialog ,其中所有公共对话框属性都被移动:

这使我们能够保持与现有应用程序的向后兼容。有关设计和讨论的更多详细信息您可以在请求API 提案中找到。

使用 OpenFolderDialog 类似于使用 WPF 中现有的文件对话框:

csharp 复制代码
var folderDialog = new OpenFolderDialog
{
    Title = "Select Folder",
    InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
};

if (folderDialog.ShowDialog() == true)
{
    var folderName = folderDialog.FolderName;
    MessageBox.Show($"You picked ${folderName}!");
}

其中 ShowDialog 方法打开对话框并等待用户输入:

您可以在 WPF-Samples 存储库中找到演示 OpenFolderDialog 和其他文件对话框用法的更多示例。

新对话框属性

我们还扩展了属性的数量来配置 WPF 中文件对话框的行为,尽可能多地涵盖当前的底层 API。以下强调了其中的一些:

  • ClientGuid 标识对话框的持久状态。这允许 Windows 记住对话框状态,例如窗口大小、每个对话框最后使用的文件夹,例如"Save"和"Save As"对话框。
  • AddToRecent 设置为 false 指示对话框不把打开或保存的文件或文件夹添加到 Windows 为用户维护的最新项目列表中。例如,这可以用于防止配置文件出现在"Start"菜单的"Recommended"部分中。
  • CreateTestFile 设置为 false 可防止 SaveFileDialog 通过创建和删除虚拟文件来验证用户是否有权访问所选位置。当访问该位置的成本预计很高时,这会很有用。但是,应用程序在创建文件本身时必须执行所有适当的错误处理。
  • RootDirectory 将对话框中的文件夹树限制为某个文件夹及其子文件夹。以下是将 RootDirectory 设置为用户的 Pictures 文件夹的示例:

请检查请求API 提案中所有新属性的列表。我们诚邀您尝试新功能并向我们提供反馈。

File Dialogs 的下一步计划

关于文件对话框仍有改进的空间,例如支持虚拟文件、通过在用户界面中包含附加控件来自定义对话框。我们收到了来自社区提议实施文件对话框控件的请求,我们想邀请所有感兴趣的人参与制定此提案,并帮助我们确定对您和您的应用程序重要的功能的优先级。

社区亮点

特别感谢我们的社区贡献者 Jan Kučera 为保持对话框更新活跃而做出的不懈努力。他探索了不同的设计选项,准备了 API 提案,并全程参与实现了该功能。谢谢 Jan!

大家好,我是 Jan,一名研究员、开发人员,也是 WPF 的忠实粉丝!

自 Microsoft 开始公开谈论 WPF 至今已有 20 年了,当时它的代号是 Avalon(这方面的知识让我赢得了我的第一本 WinFX 书),它成为使用 .NET 时间最长的应用程序框架之一。虽然它启发了许多其他框架,但似乎没有一个能在功能和简单性方面与它相媲美,这就是为什么 WPF 一直是我的首选。我特别看重它的布局系统,允许应用程序适应其内容。

对我来说,编程最有趣的部分就是与现实世界互动。我作为与社区合作的 Core Team 成员参与了 .NET Micro Framework(它将 WPF UI 模型引入嵌入式设备)。在 Microsoft Research,我在 James Scott 和 Steve Hodges 的出色团队中负责 .NET Gadgeteer工作。在他们的指导下,我成为了人机交互领域的研究员。

我的大部分空闲时间都花在了 Unicode 志愿服务上,我是 Unicode's Script Ad Hoc Group 和 Keyboard Subcommittee 的副主席。我对国际化(尤其是文本输入和输出)的热情使我能够为 DirectWrite 文本整形引擎和新键盘布局的设计做出贡献。这项工作使我能够帮助越来越多的社区实现数字化,我希望我们也能让 WPF 跟上他们的需求。

我很高兴看到人们对 WPF 持续的兴趣和发展,并可以推荐任何考虑加入 WPF 的人加入这个热情的社区并塑造其未来。

相关推荐
fkdw2 小时前
C# Newtonsoft.Json 反序列化派生类数据丢失问题
c#·json
浅尝辄止;5 小时前
C# 异步编程
c#
liyongqiangcc5 小时前
了解 ASP.NET Core 中的中间件
.net
ou.cs9 小时前
c# 实现一个简单的异常日志记录(异常迭代+分片+定时清理)+AOP Rougamo全局注入
c#
Kiros_Jiang9 小时前
开源低代码平台-Microi吾码 打印引擎使用
javascript·开源·json·.net·pip
一只小小汤圆10 小时前
编译笔记:vs 中 正在从以下位置***加载符号 C# 中捕获C/C++抛出的异常
c++·c#
码农君莫笑11 小时前
Blazor项目中使用EF读写 SQLite 数据库
linux·数据库·sqlite·c#·.netcore·人机交互·visual studio
呆呆小雅12 小时前
C#关键字volatile
java·redis·c#