【问题标题】:populate images from picture library to ListView in Windows 10 App在 Windows 10 App 中将图片从图片库填充到 ListView
【发布时间】: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 编辑检查以上

标签: c# xaml listview windows-store-apps uwp


【解决方案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 中问后续问题。而是在 StackOverflow 上提出一个新问题。
【解决方案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。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-02
  • 2014-09-23
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多