UWP 使用 DataTemplate 在 GridView 中显示图像

UWP Displaying images in GridView with DataTemplate

上下文

我正在尝试将用户本地图片文件夹(例如 C:\Users\Username\Pictures\The 文件夹)中目录中的图像显示到 GridView 中。

我正在为图像使用 class(这是 GridView 的来源):

public class SpotlightImage
    {
        public string ID { get; set; }

        public string Name { get; set; }

        public string FileSource { get; set; }
    }

GridView 的 XAML 如下:

<GridView
            Padding="{StaticResource MediumLeftRightMargin}"
            animations:Connected.ListItemElementName="thumbnailImage"
            animations:Connected.ListItemKey="galleryAnimationKey"
            IsItemClickEnabled="True"
            ItemClick="ImagesGridView_ItemClick"
            ItemsSource="{x:Bind Source, Mode=OneWay}"
            RightTapped="ImagesGridView_RightTapped"
            SelectionMode="None">
            <GridView.ItemTemplate>
                <DataTemplate x:DataType="models:SpotlightImage">
                    <Image
                        x:Name="thumbnailImage"
                        AutomationProperties.Name="{x:Bind Name}"
                        Source="{x:Bind FileSource}"
                        Style="{StaticResource ThumbnailImageStyle}"
                        ToolTipService.ToolTip="{x:Bind Name}" />
                </DataTemplate>
            </GridView.ItemTemplate>
        </GridView>

用于填充源代码的 C# 如下(我意识到很可能没有必要使用并行 foreach,但是,我使用它是为了与项目中的其他代码保持一致):

private async void ImagesPage_OnLoaded(object sender, RoutedEventArgs e)
        {
            Source.Clear();

            storageFiles = new List<Windows.Storage.StorageFile>();

            List<string> SavedWallpapers = await RetrieveAllSavedWallpapers.Main(); //Retrieves image names

            galleryData = new List<SpotlightImage>();

            Parallel.ForEach(SavedWallpapers, spotlightFile =>
            {
                imgFileFunction(spotlightFile);
            });

            async void imgFileFunction(string spotlightFile)
            {
                try
                {
                    //StorageReferences.WallpaperSaveStorage is a StorageFolder variable for the images directory being accessed
                    Windows.Storage.StorageFile file = await StorageReferences.WallpaperSaveStorage.GetFileAsync(spotlightFile);

                    storageFiles.Add(file);

                    var img = new SpotlightImage()
                    {
                        ID = file.DisplayName,
                        FileSource = file.Path,
                        Name = file.DisplayName
                    };

                    galleryData.Add(img);

                    await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                    () =>
                    {
                        Source.Add(img);

                        Debug.WriteLine("IMAGE ADDED: " + img.Name);
                    }
                    );
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("MULTITHREADED ERROR: " + ex.Message);
                }
            }
        }

问题

GridView 显示空方块而不是图像。 'images' 出现了正确的数目,但它们是空白的。

我试过的

我在 Whosebug 上查看了类似的问题并尝试了以下方法:

  1. 使用 UriSource 而不是源(同样的问题仍然存在)
  2. 查看了代码(我在项目的其他地方使用了完全相同的代码并且它在那里工作。唯一的区别是正在访问不同的文件夹)
  3. 检查权限(我在之前的代码中使用了这个目录没有问题)

备注:

我的 UWP 应用程序已经有 broadFileSystemAccess(这对我的应用程序来说是必要的)。

我有一个 FlipView,它正在访问相同的文件并遇到完全相同的问题。

我已经有完全相同的代码 运行 在我的项目的其他地方完全没问题,唯一的区别是正在访问的文件夹。这使我相信问题出在权限上,但我的应用程序具有 broadFileSystemAccess。所以这不应该是问题 (?)

如您所知,我对 UWP 比较陌生。因此,如果存在一些明显的权限问题或类似问题,请对我放轻松 :)

在互联网上搜索了几个小时后,我发现了 9 年前的 this post。改装相关代码以使用位图而不是 jpg 后,一切正常。唯一的缺点是位图图像在 GridView 中显示时出现不寻常的锯齿(锯齿状边缘)。至少它是有效的。

有一件事我永远不会理解:到底为什么我必须使用位图?

无论如何,希望这能帮助一些可怜的随机程序员,他们将在 9 年后看到这个答案。

编辑: Roy Li 的回答很好地解释了我遇到这个问题的原因,以及为什么手动制作位图可以解决它。

尝试使用 UWP CommunityToolkit 中的 ImageEx 组件。它将为您处理所有加载和缓存内容

  1. 这是文档 https://docs.microsoft.com/en-us/windows/communitytoolkit/getting-started
  2. 这是示例应用 https://aka.ms/windowstoolkitapp

这是 ImageEx 控件示例应用程序的屏幕截图

基于Image.Source property,在文档的Setting Source in XAML部分,它提到当你设置Source property 值作为描述源图像文件位置的 URI 字符串,实际上,它调用等效于 BitmapImage(Uri) 构造函数来创建 BitmapImage Image.Source property.

的对象

我做了一个简单的测试,直接从文件路径(应用程序外的文件)创建一个 BitmapImage 对象。如果 BitmapImage 对象设置为图像控件,则不显示任何内容。这与您得到的行为相同。如果文件是应用程序包的一部分,则它可以正常工作。

正如您提到的,您正在使用 full file system access,我想这意味着 broadFileSystemAccess 功能,对吗?此功能仅适用于 Windows.Storage namespace 中的 API,不适用于 BitmapImage(URI).

等 API

所以该行为的原因应该是当应用程序使用不属于应用程序包的文件路径作为 BitmapImage 对象的 URI 时,BitmapImage 对象不是正确创建。尝试以 Steam 方式打开文件并将其设置为 BitmapImage 对象是打开位于应用程序包之外的图像文件的正确方法。