0

Microsoft.Win32.OpenFileDialog我们在 WPF 应用程序(针对 .NET Framework 4.7.2)中使用时遇到问题。

我们希望能够从通过 USB 连接到计算机的智能手机导入多个文件。但是,使用 似乎不可能这样做OpenFileDialog,因为它会触发消息框“无法从该位置打开多个项目。请尝试选择单个项目。” . 您可以使用这个简单的代码复制它,并从您的智能手机中选择至少 2 张图片:

var openFileDialog = new Microsoft.Win32.OpenFileDialog();
openFileDialog.Multiselect = true;
openFileDialog.ShowDialog();

这个问题是已知的(参见此处此处)并且与 MTP 协议有关。使用替代“USB Mas Storage”(UMS)连接的智能手机不会出现此问题,但现代智能手机上不提供此选项。

UWPFileOpenPicker似乎可以更好地处理多个项目的选择(请参阅此处了解如何在 WPF 应用程序中使用它),但我们InvalidCastException在使用PickMultipleFilesAsync. 此处描述了该问题,并且答案表明该问题FileOpenPicker不能在 WPF .NET Framework 应用程序中使用。

正如评论中所说,实现此目的的另一种方法是使用智能手机设备的 MTP 协议从 skratch 实现文件选择器。这种方法的缺点是 .NET 和 UWP 文件选择器提供了许多很棒的功能并且完全集成到操作系统中。

我们已经没有解决这个问题的想法了,所以我的问题是:

有没有办法在面向 .NET Framework 的 WPF 应用程序中使用 Windows 文件选择器从智能手机导入多个文件?

Microsoft Q&A上也提出了同样的问题。

4

1 回答 1

0

我回复有点晚了,但由于微软问答线程,我找到了解决方案。

据我所知,使用 无法从 MTP 设备中选择多个文件,Microsoft.Win32.OpenFileDialog因为您无法设置所有IFileOpenDialog选项。

因此,您需要使用自己IFileOpenDialog的选项来设置选项:请务必添加FOS_ALLOWMULTISELECT选项并删除FOS_FORCEFILESYSTEM

ComFileDialog.IFileOpenDialog fileOpenDialog = null;
ComFileDialog.IShellItemArray shellItemArray = null;
ComFileDialog.IShellItem shellItem = null;
try
{
    // Set options
    fileOpenDialog = (ComFileDialog.IFileOpenDialog)new ComFileDialog.FileOpenDialogRCW();
    fileOpenDialog.GetOptions(out var options);
    options |= ComFileDialog.FOS_ALLOWMULTISELECT | ComFileDialog.FOS_FILEMUSTEXIST | ComFileDialog.FOS_PATHMUSTEXIST;
    fileOpenDialog.SetOptions(options);

    // Show window
    if (fileOpenDialog.Show() != ComFileDialog.S_OK)
    {
        return;
    }

    // Get results
    if (fileOpenDialog.GetResults(out shellItemArray) != ComFileDialog.S_OK)
    {
        return;
    }

    uint items = 0;
    if (shellItemArray.GetCount(out items) != ComFileDialog.S_OK)
    {
        return;
    }

    // Result loop
    for (uint item = 0; item < items; item++)
    {
        try
        {
            if (shellItemArray.GetItemAt(item, out shellItem) != ComFileDialog.S_OK)
            {
                continue;
            }

            // Use the IShellItem
        }
        finally
        {
            if (shellItem != null)
            {
                Marshal.ReleaseComObject(shellItem);
                shellItem = null;
            }
        }
    }
}
finally
{
    if (fileOpenDialog != null)
    {
        Marshal.ReleaseComObject(fileOpenDialog);
    }
    if (shellItemArray != null)
    {
        Marshal.ReleaseComObject(shellItemArray);
    }
    if (shellItem != null)
    {
        Marshal.ReleaseComObject(shellItem);
    }
}

您可以在 pinvoke.net 上找到 Window Shell API 接口:

于 2021-09-02T12:32:03.390 回答