在WPF.NET中使用 UWP FolderPicker 作为文件夹选择对话框:Invalid window handle. (0x80070578)

WPF.NET没有原生的文件夹选择对话框,只能“借用”为其它框架设计的文件夹选择对话框。在前UWP时代,WPF通常需要借用Windows窗体的FolderBrowserDialog,但这个对话框的缺点是只能选择单个文件夹,不支持多选。后来UWP提供了原生的FolderPicker,支持包括文件夹多选等更多丰富功能。对于新开发的应用,我们应当尽量使用FolderPicker,弃用FolderBrowserDialog。

但是,在WPF中使用FolderPicker并不像原本使用FolderBrowserDialog那样,只要在项目属性中启用Windows窗体就可以直接使用。首先,你需要在项目属性中设置受支持的OS版本:

建议对新开发的应用至少选择19041以上版本,除非特别需要支持旧版系统。完成设置后,你应当能在代码中使用Windows.Storage命名空间了。

Imports Windows.Storage
Class MainWindow
'''
    ReadOnly 目录浏览对话框 As New Pickers.FolderPicker
'''
End Class

但在WPF中,仅仅这样做是不够的。如果你直接调用其PickSingleFolderAsync方法,将会遇到如下错误:

System.Runtime.InteropServices.COMException:“Invalid window handle. (0x80070578)
Consider WindowNative, InitializeWithWindow
See https://aka.ms/cswinrt/interop#windows-sdk”

这是因为,WPF要求对FolderPicker实行更复杂的初始化: 

Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
	'只能在Loaded中初始化,因为构造阶段窗口还没有句柄
	WinRT.Interop.InitializeWithWindow.Initialize(目录浏览对话框, New System.Windows.Interop.WindowInteropHelper(Me).Handle)

    'Win10中必须添加FileTypeFilter,Win11中为可选添加。
	目录浏览对话框.FileTypeFilter.Add("*")
End Sub

这个初始化方法来自官方文档:

从 .NET 应用调用互操作 APIhttps://learn.microsoft.com/zh-cn/windows/apps/desktop/modernize/winrt-com-interop-csharp此方法因为要获取WPF应用的窗口句柄,所以必须在窗口建立后才能调用,而不能在窗口类的构造方法中调用。此外,示例代码中设置了FileTypeFilter,测试发现此设置在Win10中为必需,Win11则不需要,但设置了也不会出错。

完成初始化后,可以持久保留FolderPicker对象以便重复多次使用,不需要重新设置。典型的使用方法如下:

Dim 目录 As StorageFolder = Await 目录浏览对话框.PickSingleFolderAsync
If 目录 IsNot Nothing Then
    '''
End If

此代码要求其所在的方法声明为Async。如果用户没有选择任何文件夹就关闭了窗口,将会返回Nothing;否则将会返回一个StorageFolder对象,你可以进行任何后续操作。

<think>好的,我现在需要解决用户的问题:在WPF应用程序中实现文件夹选择对话框的功能。用户要求示例代码,所以我要先回顾相关的知识,然后整理出正确的实现方法。 首先,我记得WPF本身没有原生的文件夹选择对话框。以前的做法通常是使用Windows Forms的FolderBrowserDialog,但用户可能希望用更现代的方法,比如UWPFolderPicker。不过根据引用[2]和[3],使用UWPFolderPickerWPF中可能会遇到问题,比如无效的窗口句柄错误。而引用[3]提到需要添加对WinForms的引用,使用FolderBrowserDialog。但用户可能想要更先进的选项,比如多选,这时候可能需要UWP的解决方案,但需要注意兼容性问题。 用户的问题可能需要一个直接的示例,所以可能需要提供两种方法:传统的WinForms方法和UWP方法,并指出各自的优缺点。 首先,传统方法使用FolderBrowserDialog。需要引用System.Windows.Forms和WindowsFormsIntegration。然后在代码中使用这个对话框,设置属性如Description、SelectedPath等。示例代码的结构应该是初始化对话框,显示,然后处理结果。 其次,UWPFolderPicker方法,但根据引用[2],可能会遇到句柄问题,需要正确的窗口关联。需要添加对Windows的引用,使用WinRT.Interop的InitializeWithWindow方法来关联窗口句柄。然后调用PickSingleFolderAsync来获取结果。 此外,引用[4]详细说明了OpenFileDialog和SaveFileDialog的属性,但用户需要的是文件夹选择,所以这部分可能不直接相关,但可以作为参考。 现在需要组织代码示例,确保两种方法都正确,并且处理可能的异常。例如,UWP方法需要检查环境是否支持,或者是否需要特定的Windows版本。 可能的问题点:用户的项目是否需要配置特定的NuGet包或引用,比如在UWP方法中需要安装Windows API包。因此,在示例中需要说明这些依赖。 另外,需要注意线程问题,因为WPF的UI线程需要处理对话框的调用,确保在正确的线程上操作。 最后,生成相关问题,帮助用户进一步了解相关主题,比如性能分析、多选支持等。 总结步骤: 1. 使用WinForms的FolderBrowserDialog的步骤和示例代码。 2. 使用UWPFolderPicker的步骤和示例代码,处理窗口句柄问题。 3. 对比两种方法的优缺点。 4. 生成相关问题。</think>在WPF中实现文件夹选择对话框主要有两种主流方案,以下是具体实现方法和对比分析: ### 一、传统方案(Windows Forms组件) ```csharp // 在项目引用中添加 System.Windows.Forms 和 WindowsFormsIntegration using System.Windows.Forms; private void SelectFolder_WinForms() { var dialog = new FolderBrowserDialog { Description = "选择目标文件夹", UseDescriptionForTitle = true, SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) }; if (dialog.ShowDialog() == DialogResult.OK) { string selectedPath = dialog.SelectedPath; // 处理选择的路径 } } ``` **优点**:兼容性好,支持.NET Framework 3.0+[^3] **缺点**:界面老旧,不支持多选[^2] ### 二、现代方案(UWP FolderPicker) ```csharp // 需要安装 Microsoft.Windows.SDK.Contracts NuGet包 using Windows.Storage; using Windows.Storage.Pickers; using WinRT.Interop; private async void SelectFolder_UWP() { var picker = new FolderPicker { ViewMode = PickerViewMode.List, SuggestedStartLocation = PickerLocationId.Desktop }; picker.FileTypeFilter.Add("*"); // 关联窗口句柄 var hwnd = new WindowInteropHelper(Application.Current.MainWindow).Handle; InitializeWithWindow.Initialize(picker, hwnd); StorageFolder folder = await picker.PickSingleFolderAsync(); if (folder != null) { string selectedPath = folder.Path; // 处理选择的路径 } } ``` **优点**:现代界面,支持多选(需设置`picker.AllowMultipleSelection = true`) **缺点**:需要Windows 10 1809+,需处理XAML Islands兼容性[^2] ### 三、方案对比 | 特性 | WinForms方案 | UWP方案 | |---------------------|-------------------|-------------------| | 系统要求 | Windows XP+ | Windows 10 1809+ | | 界面风格 | 传统 | Fluent设计 | | 多选支持 | ❌ | ✔️ | | 依赖项 | System.Windows.Forms | Windows SDK | | 异步操作 | ❌ | ✔️ |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值