.NET Blazor Desktop(WPF BlazorWebView)如何实现原生文件夹选择器
WPF BlazorWebView 原生文件夹选择器实现方案
BlazorWebView 属于.NET Blazor Desktop 混合开发场景,Blazor 代码和 WPF 宿主运行在同一个进程内,可直接通过依赖注入复用 WPF 原生系统能力,不需要受浏览器沙箱限制,也不需要用Process.Start启动独立 explorer.exe 进程(该方式无法回传用户选择结果)。
具体实现步骤
1. 定义文件夹选择服务契约与原生实现
首先在 WPF 宿主项目中定义服务接口,后续 Blazor 侧只依赖该接口即可,不需要感知原生实现细节:
public interface IFolderPicker { /// <summary> /// 弹出系统原生文件夹选择对话框 /// </summary> /// <param name="title">对话框标题</param> /// <returns>选中的文件夹完整路径,用户取消选择时返回null</returns> string? PickFolder(string? title = null); }
基于系统内置对话框实现该接口,不需要引入任何第三方NuGet包:
public class WindowsNativeFolderPicker : IFolderPicker { public string? PickFolder(string? title = null) { using var dialog = new System.Windows.Forms.FolderBrowserDialog { UseDescriptionForTitle = true, ShowNewFolderButton = true }; if (!string.IsNullOrWhiteSpace(title)) { dialog.Description = title; } string? selectedPath = null; // 系统对话框必须在STA主线程弹出,调度到WPF UI线程执行避免线程异常 System.Windows.Application.Current.Dispatcher.Invoke(() => { if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { selectedPath = dialog.SelectedPath; } }); return selectedPath; } }
若项目目标框架为.NET 6及以上版本,只需在WPF项目的.csproj文件的
<PropertyGroup>节点下添加配置<UseWindowsForms>true</UseWindowsForms>,即可直接使用上述内置的FolderBrowserDialog控件,无需额外安装依赖。
2. 注册服务到DI容器
找到你项目中BlazorWebView的服务配置位置(即XAML中Services="{DynamicResource services}"对应的服务集合初始化代码,一般在App.xaml.cs或MainWindow.xaml.cs中),将文件夹选择服务注册为单例:
// 其他原有服务注册逻辑,例如services.AddBlazorWebView()等 services.AddSingleton<IFolderPicker, WindowsNativeFolderPicker>();
3. Blazor侧注入服务直接调用
替换你之前Razor组件中启动explorer.exe的逻辑,直接注入服务调用即可:
@* 注入文件夹选择服务 *@ @inject IFolderPicker FolderPicker <button @onclick="HandlePickFolderClick">选择文件夹</button> @if (!string.IsNullOrEmpty(_selectedFolderPath)) { <p>已选择文件夹路径:@_selectedFolderPath</p> } @code { private string? _selectedFolderPath; private void HandlePickFolderClick() { _selectedFolderPath = FolderPicker.PickFolder("请选择目标存储文件夹"); // 后续可直接用该路径做本地文件读写操作,无沙箱限制 } }
方案说明
- 该方案调用的是Windows系统原生文件夹选择对话框,交互和系统体验完全一致,返回的是真实的本地磁盘完整路径,没有浏览器沙箱的路径篡改问题。
- 之前使用
Process.Start("explorer.exe")的方案本质是启动独立的资源管理器进程,和当前应用无进程间通信关联,无法捕获用户的选择结果,不满足交互需求。 - 浏览器端
<input webkitdirectory>的方案仅能获取沙箱内的文件虚拟路径,无法拿到真实本地磁盘路径,不适合桌面端本地文件操作场景。
内容的提问来源于stack exchange,提问作者David Randoll
相关产品推荐
相关产品推荐

