在 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的主要内容,如果未能解决你的问题,请参考以下文章