在 Windows 10 App 中将图片从图片库填充到 ListView

Posted

技术标签:

【中文标题】在 Windows 10 App 中将图片从图片库填充到 ListView【英文标题】:populate images from picture library to ListView in Windows 10 App 【发布时间】:2017-04-30 08:17:36 【问题描述】:

我正在尝试在 Windows 应用程序中将默认图片库中的所有图像显示到 ListView,但我只能显示图像的名称而不是文件夹中的所有图像,这是我的代码。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Media.Imaging;
using Windows.Storage.Streams;
using Windows.Storage;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace ListView

/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page

    public MainPage()
    
        this.InitializeComponent();
        showall();
    

    public async void showall()
    
        IReadOnlyList<StorageFile> file = await KnownFolders.PicturesLibrary.GetFilesAsync();

        foreach (StorageFile file1 in file)
        
            list.Items.Add(file1.Name);
        

    

这里是 xaml 代码...

<Page
x:Class="ListView.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ListView"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="ThemeResource ApplicationPageBackgroundThemeBrush">

    <StackPanel>
        <StackPanel HorizontalAlignment="Left" Width="350" Height="350">
            <ListView Width="300" Height="300" Name="list" SelectionChanged="list_SelectionChanged">
                <Image Width="200" Height="200" Name="img"></Image>
            </ListView>
        </StackPanel>
        <StackPanel VerticalAlignment="Top">

            <Image Width="300" Height="300" Name="img1" />
            <TextBlock Width="300" Height="30" Name="txt1" />

        </StackPanel>
    </StackPanel>


</Grid>

【问题讨论】:

这里是listView设计的图片链接:prntscr.com/djhu3f 那么问题出在哪里?用于绑定此的 xaml 在哪里? @AVKNaidu 编辑检查以上 【参考方案1】:

没有从 StorageFile 名称到图像的自动转换。

您需要两件事,首先是在 ListView 中带有 Image 控件的 DataTemplate:

<ListView x:Name="list">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Image Source="Binding"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

第二,从StorageFiles创建的BitmapImages,添加到Items集合而不是文件名:

public MainPage()

    InitializeComponent();

    Loaded += OnLoaded;


private async void OnLoaded(object sender, RoutedEventArgs e)

    list.Items.Clear();

    var files = await KnownFolders.PicturesLibrary.GetFilesAsync();

    foreach (var file in files)
    
        var bitmap = new BitmapImage();

        using (var stream = await file.OpenReadAsync())
        
            await bitmap.SetSourceAsync(stream);
        

        list.Items.Add(bitmap);
    

还要注意,加载是在Loaded 事件处理程序中完成的,而不是直接调用异步方法而不等待它。事件处理程序是唯一可以安全地成为 async void 且无需等待的方法。

【讨论】:

每张图片加载2次,如何设置这些图片的像素? Loaded 处理程序可能被调用了两次(不知道为什么)。我已经对其进行了更改,以便它最初清除列表。除此之外,如何设置像素数据是一个完全不同的问题。请不要在 cmets 中问后续问题。而是在 *** 上提出一个新问题。【参考方案2】:

虽然 Clemens 的方法适合您,但我想向您展示一种不同的方法。使用 ViewModel。

这是一个 PicturesViewModel:

public class PicturesViewModel

    public ObservableCollection<ImageSource> MyImages  get; 
        = new ObservableCollection<ImageSource>();

    public async Task GetImages()
    
        var files = await KnownFolders.PicturesLibrary.GetFilesAsync();
        foreach (var file in files)
        
            using (var stream = await file.OpenReadAsync())
            
                BitmapImage image = new BitmapImage();
                await image.SetSourceAsync(stream);
                MyImages.Add(image);
            
        
    

通常如果它是一个同步活动,你可以在构造函数中编写你的逻辑。由于这是异步的,我在我的视图模型中使用另一种方法来加载 ListBitmapImages

现在在您的MainPage_Loaded(MainPage 的Loaded 事件的处理方法,如另一个答案所示)中,您需要这样做:

private async void MainPage_Loaded(object sender, RoutedEventArgs e)

    var viewModel = new PicturesViewModel();
    DataContext = viewModel;

    await viewModel.GetImages();

而您的 ListView 只是 Binding

<ListView ItemsSource="Binding MyImages">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Image Source="Binding"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

【讨论】:

修复了 XAML 并更改了视图模型以使用广泛接受的属性名称命名约定。关于 DataContext 的代码注释也是错误的。 ListView从Page继承DataContext,所以设置list.DataContext还是this.DataContext都没有关系。后者更好,因为 Page 中的其他元素可以绑定到同一个视图模型。此外,从 GetImages() 方法返回视图模型实例没有意义。 在 Loaded 处理程序中实例化视图模型也不是严格要求的。您也可以在 MainPage 构造函数中执行此操作。重要的是在 Loaded 处理程序中调用异步 GetImages() 方法。 在我们进行改进的同时,我还将 MyImages 集合更改为只读,并将元素类型更改为 ImageSource,这是 BitmapImage 的一个基类,它提供了更大的灵活性您可以传递给集合的位图类型的数量,例如WriteableBitmap 而不是 BitmapImage。

以上是关于在 Windows 10 App 中将图片从图片库填充到 ListView的主要内容,如果未能解决你的问题,请参考以下文章

如何在应用程序中将所选图片从图片库动态复制到图片文件夹中?

Windows 10使用Windows7图片查看器浏览图片

文件用啥软件打开

如何在 Scriptable App 中将 Base64 转换为图像

如何使用 javascript/node js 从数据库中将图片动态加载到网页上

在“多对多关系”环境中将图片保存在 Core Data 中