首页 > 解决方案 > GetGeotagAsync 对通过 Folder.CreateFileQueryWithOptions w/ OrderByName 创建的列表中的文件失败

问题描述

目标:从用户指定的文件夹中获取图像文件列表,并检索每个文件的纬度/经度元数据(如果可用)。

该方法是使用带有选项的文件夹查询来返回文件列表,然后对其进行迭代以获取地理标记信息。作为一个简单的测试,我只是在 MS 提供的 Geotag 示例中添加了一些代码;添加了 ChooseFolderButton_Click 方法。它使用 FolderPicker 然后简单地从查询中选择第一个文件(就像一个测试)并像原始演示一样处理它来显示地理标记信息。

问题似乎在于如何从查询中返回 StorageFile 项,并且仅在使用 CommonFileQuery.OrderByName 时。如果使用 DefaultQuery 则一切正常。

下面是添加到 MS Samples Geotag 的代码(在 XAML 中添加了一个按钮):

private async void ChooseFolderButton_Click()
{
    FolderPicker picker = new FolderPicker
    {
        SuggestedStartLocation = PickerLocationId.PicturesLibrary,
        CommitButtonText = "Select",
        ViewMode = PickerViewMode.Thumbnail,
    };
    picker.FileTypeFilter.Add("*");
    StorageFolder Folder = await picker.PickSingleFolderAsync();

    if (Folder != null) { 
        // Get the files and sort them myself
        IReadOnlyList<StorageFile> files = await Folder.GetFilesAsync();
        List<StorageFile> sortedList = files.Where(f => string.Compare(f.FileType,".jpg", ignoreCase: true) == 0 )
                                                .OrderBy(f => f.DisplayName)
                                                .Select(f => f)
                                                .ToList();
        file = sortedList.FirstOrDefault();
    }

    if (Folder != null) {
        // Use Folder GetFiles with query options to get sorted list
        var queryOptions = new QueryOptions(CommonFileQuery.DefaultQuery, new List<string> { ".jpg" })
        {
            FolderDepth = FolderDepth.Shallow
        };
            //queryOptions.SetPropertyPrefetch(PropertyPrefetchOptions.ImageProperties, null);
        IReadOnlyList<StorageFile> files2 = await Folder.CreateFileQueryWithOptions(queryOptions).GetFilesAsync();
        var file2 = files2[0];
    }

    if (Folder != null && file != null)
    {
        FileDisplayName.Text = file.DisplayName;
        FileOperationsPanel.Visibility = Visibility.Visible;
    }
    else
    {
        FileOperationsPanel.Visibility = Visibility.Collapsed;
    }
}

从 sortedList 中选择文件可以正常工作。如图所示,当使用 DefaultQuery 时,使用来自 files2 的结果也将起作用。将其更改为 OrderByName,GetGeotagAsync 调用将失败,返回 null。

仔细研究它,在最后一种情况下,返回的 StorageFile 实例似乎不同。FolderRelativeId 的文件扩展名重复;数字\文件名.ext.ext;但是,通过 StorageFile 实例的访问似乎可以正常工作......除了 GetGeotagAsync() 至少。这让我想知道是否正在创建文件的副本并且不包括元数据。

我对 C# 和 UWP 比较陌生,这是我的第一个问题帖子,所以我希望这是足够的细节......问题基本上是:我在这里遗漏了什么吗?在文件夹查询中做错了什么?我可以像在示例代码中那样使用 linq 来解决它,甚至只使用 DefaultQuery;但这很不舒服,因为我确实在其他几件事上使用了文件夹查询方法。查询 OrderByName 是否重复或做一些不受欢迎的事情?

标签: c#uwpwindows-10-universal

解决方案


我的假设是这些获取的文件将显示到 ui,如果是这种情况,您可以使用作为 Windows 社区工具包一部分的漂亮的AdvancedCollectionView

AdvancedCollectionView 允许基于它们的属性对包含的项目进行持久排序和过滤,这一过程使其对于现代绑定密集型应用程序非常有用。

这是一个例子:

List<StorageFile> FileList = New List<StorageFile>();

Microsoft.Toolkit.Uwp.UI.AdvancedCollectionView ObservableFileList
        {
            get; set;
        }




void InitializeList(){

//here we pass the backing list as an argument, 
//any changes on the filelist will be directly reflected on our new observablelist, and vice versa

ObservableFileList = new Microsoft.Toolkit.Uwp.UI.AdvancedCollectionView(FileList);

//here we add sorting definitions, 
//"DisplayName" is the current property we choose to sort against

ObservableFileList.SortDescriptions.Add(new SortDescription("DisplayName",SortDirection.Descending)); 

}


void AcquireNewDataSet(){    
//GetFiles should return your files with no particular order.    
List<StorageFile>tmp = GetFiles();    

//always prefer ReplaceRange
FileList.ReplaceRange(tmp);    
}

在此过程之后,您的可观察列表将始终按字母顺序排序,即使将其用作各种 UI 项目容器上的ItemSource


推荐阅读