在 WinUI 中使用选取器打开文件和文件夹

使用 Windows 应用 SDK 文件和文件夹选取器允许用户浏览和选择 WinUI 应用中的文件或文件夹。 选取器 API 提供熟悉的 Windows 体验,可帮助用户导航其设备和云存储位置。 本文介绍如何实现文件打开选取器和文件夹选取器、自定义其行为以及处理应用中所选结果。

Windows App SDK FileOpenPickerFileSavePicker 类创建一个选取器对话框,允许用户指定要打开或保存的文件的名称和位置。 FolderPicker 类允许你选择文件夹。

若要了解如何使用选取器保存文件,请参阅 使用 Windows 应用 SDK 选取器保存文件

重要 API

本文使用以下 API:

文件选择界面

文件选取器显示面向用户的信息,并在打开或保存文件时提供一致的体验。

这些信息包括:

  • 当前位置
  • 用户选取的项目
  • 用户可以浏览到的位置树。 这些位置包括文件系统位置(如音乐或下载文件夹)以及实现文件选取器协定的应用(如相机、照片和Microsoft OneDrive)。

你可能有一个应用,允许用户打开或保存文件。 当用户执行该操作时,你的应用会调用文件选取器,以显示文件选取器用户界面。

打开的文件选取器的屏幕截图,其中选择了一个筛选器以显示 .txt、.pdf、.doc和 .docx 文件。

选取器如何在你的应用中工作

使用选取器,你的应用可以访问、浏览和保存用户系统上的文件和文件夹。 你的应用接收这些选取作为轻型 PickFileResultPickFolderResult 对象,这些对象提供所选文件或文件夹的路径。

选取器使用单个统一界面,让用户从文件系统或其他应用中选取文件和文件夹。 从其他应用选取的文件类似于文件系统中的文件。 一般情况下,你的应用可以像其他对象一样对它们进行作。 其他应用通过参与文件选取器协定来提供文件。

例如,可以在应用中调用文件选取器,以便用户可以打开文件。 此操作会使您的应用成为呼叫应用。 文件选取器与系统和其他应用交互,以便用户导航和选取文件。 当用户选择文件时,文件选取器会返回该文件的应用路径。

选择要打开示例的文件

以下代码演示如何使用 FileOpenPicker 类让用户选取单个文件,例如照片。 代码设置选取器的属性以自定义其外观和行为,然后使用 PickSingleFileAsync 方法向用户显示选取器。 如果用户选取文件,应用将读取文件的内容并将其存储在变量中。

using Microsoft.Windows.Storage.Pickers;

var openPicker = new FileOpenPicker(this.AppWindow.Id)
{
    // (Optional) Specify the initial location for the picker. 
    //     If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
    //     If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
    SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
    
    // (Optional) specify the text displayed on the commit button. 
    //     If not specified, the system uses a default label of "Open" (suitably translated).
    CommitButtonText = "Choose selected files",

    // (Optional) specify file extension filters. If not specified, defaults to all files (*.*).
    FileTypeFilter = { ".txt", ".pdf", ".doc", ".docx" },

    // (Optional) specify the view mode of the picker dialog. If not specified, defaults to List.
    ViewMode = PickerViewMode.List,
};

var result = await openPicker.PickSingleFileAsync();
if (result is not null)
{
    var content = System.IO.File.ReadAllText(result.Path);
}
else
{
    // Add your error handling here.
}

这与C++中的示例相同:

#include <winrt/Microsoft.Windows.Storage.Pickers.h>
#include <fstream>
#include <string>

using namespace winrt::Microsoft::Windows::Storage::Pickers;

FileOpenPicker openPicker(this->AppWindow().Id());

// (Optional) Specify the initial location for the picker. 
//     If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
//     If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
openPicker.SuggestedStartLocation(PickerLocationId::DocumentsLibrary);

// (Optional) specify the text displayed on the commit button. 
//     If not specified, the system uses a default label of "Open" (suitably translated).
openPicker.CommitButtonText(L"Choose selected files");

// (Optional) specify file extension filters. If not specified, defaults to all files (*.*).
openPicker.FileTypeFilter().ReplaceAll({ L".txt", L".pdf", L".doc", L".docx" });

// (Optional) specify the view mode of the picker dialog. If not specified, defaults to List.
openPicker.ViewMode(PickerViewMode::List);

auto result{ co_await openPicker.PickSingleFileAsync() };
if (result)
{
    std::ifstream fileReader(result.Path().c_str());
    std::string text((std::istreambuf_iterator<char>(fileReader)), std::istreambuf_iterator<char>());
    winrt::hstring hText = winrt::to_hstring(text);
}
else
{
    // Add your error handling here.
}

选取多个文件以打开示例

还可以让用户选取多个文件。 以下代码演示如何使用 FileOpenPicker 类让用户选取多个文件,例如照片。 此过程相同,但 PickMultipleFilesAsync 方法返回文件路径的集合,而不是单个路径。

using Microsoft.Windows.Storage.Pickers;

var openPicker = new FileOpenPicker(this.AppWindow.Id);

var results = await openPicker.PickMultipleFilesAsync();
if (results.Count > 0)
{
    var pickedFilePaths = results.Select(f => f.Path);
    foreach (var path in pickedFilePaths)
    {
        var content = System.IO.File.ReadAllText(path);
    }
}
else
{
    // Add your error handling here.
}

若要在C++中执行相同的作,请使用以下代码:

#include <winrt/Microsoft.Windows.Storage.Pickers.h>
#include <fstream>
#include <string>

using namespace winrt::Microsoft::Windows::Storage::Pickers;

FileOpenPicker openPicker(this->AppWindow().Id());
auto results{ co_await openPicker.PickMultipleFilesAsync() };
if (results.Size() > 0)
{
    for (auto const& result : results)
    {
        std::ifstream fileReader(result.Path().c_str());
        std::string text((std::istreambuf_iterator<char>(fileReader)), std::istreambuf_iterator<char>());
        winrt::hstring hText = winrt::to_hstring(text);
    }
}
else
{
    // Add your error handling here.
}

选取文件夹示例

若要使用 FolderPicker 类选取文件夹,请使用以下代码。 此代码创建文件夹选取器,使用 PickSingleFolderAsync 方法向用户显示文件夹,并在 PickFolderResult 对象中检索所选文件夹的路径。 如果用户选取文件夹,应用将检索文件夹的路径,并将其存储在变量中供以后使用。

using Microsoft.Windows.Storage.Pickers;

var folderPicker = new FolderPicker(this.AppWindow.Id)
{
    // (Optional) Specify the initial location for the picker. 
    //     If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
    //     If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
    SuggestedStartLocation = PickerLocationId.DocumentsLibrary,

    // (Optional) specify the text displayed on the commit button. 
    //     If not specified, the system uses a default label of "Open" (suitably translated).
    CommitButtonText = "Select Folder",

    // (Optional) specify the view mode of the picker dialog. If not specified, default to List.
    ViewMode = PickerViewMode.List,
};

var result = await folderPicker.PickSingleFolderAsync();

if (result is not null)
{
    var path = result.Path;
}
else
{
    // Add your error handling here.
}

若要在C++中执行相同的作,请使用以下代码:

#include <winrt/Microsoft.Windows.Storage.Pickers.h>

using namespace winrt::Microsoft::Windows::Storage::Pickers;

FolderPicker folderPicker(this->AppWindow().Id());

// (Optional) Specify the initial location for the picker. 
//     If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
//     If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
folderPicker.SuggestedStartLocation(PickerLocationId::DocumentsLibrary);

// (Optional) specify the text displayed on the commit button. 
//     If not specified, the system uses a default label of "Open" (suitably translated).
folderPicker.CommitButtonText(L"Select Folder");

// (Optional) specify the view mode of the picker dialog. If not specified, default to List.
folderPicker.ViewMode(PickerViewMode::List);

auto result{ co_await folderPicker.PickSingleFolderAsync() };
if (result)
{
    auto path{ result.Path() };
}
else
{
    // Add your error handling here.
}

小窍门

每当应用通过选取器访问文件或文件夹时,请将其添加到应用的 FutureAccessListMostRecentlyUsedList ,以使用 Windows 运行时 (WinRT) API 跟踪它。 有关详细信息,请参阅 如何跟踪最近使用的文件和文件夹

文件夹选取器 UI 如下所示:

查看 C 驱动器的文件夹选取器屏幕截图。

Windows.Storage.Pickers

使用 Windows 应用 SDK 的文件、文件夹和库

Microsoft.Windows.Storage.Pickers 命名空间