如何显示图片目录中的图像?

时间:2013-01-20 00:01:21

标签: c# windows-8 windows-runtime async-await

我想在图片库中显示图片。我得到图片并绑定数据。

StorageFolder picturesFolder = KnownFolders.PicturesLibrary;
IReadOnlyList<StorageFile> myPictures = await picturesFolder.GetFilesAsync();
var mydata = from file in myPictures select new { Subtitle = "subtitle", Title = "title", Image = this.getImage(file.Path) };

this.DefaultViewModel["Items"] = mydata;

这是设置BitmapImage的getImage()。

private async Task<BitmapImage> getImage(string finename)
{
    StorageFolder picturesFolder = KnownFolders.PicturesLibrary;
    StorageFile file = await picturesFolder.GetFileAsync(fileName);
    var stream = await file.OpenReadAsync();

    var bitmap = new BitmapImage();
    bitmap.SetSource(stream);

    return bitmap;
 }

但是没有显示图片。我认为这是因为异步功能,但我不知道解决方案。你能帮帮我吗?

2 个答案:

答案 0 :(得分:2)

我不确定您如何使用设置为DefaultViewModel的数据,但是,看起来async方法似乎是您的问题。

您需要做的是以await每次调用getImage()。一种方法是在async中使用select lambda。但要做到这一点,您需要使用方法语法。

当您这样做时,您将拥有IEnumerable<Task<a>>(其中a是您的匿名类型),但您只需要IEnumerable<a>。为此,请使用Task.WhenAll()(将返回Task<a[]>),然后使用await结果:

var tasks = myPictures.Select(
    async file => new { Subtitle = "subtitle", Title = "title", Image = await getImage(file.Path) });
var data = await Task.WhenAll(tasks);

这将立即执行所有getImage(),这可能不是最有效的解决方案。如果你不想那样,你需要不同的解决方案。

答案 1 :(得分:1)

svick的解决方案似乎应该可行,但正如他/她所说 - 它可能不是最有效的解决方案。对于文件数量未知的文件夹,更好的解决方案是使用FileInformationFactory.GetVirtualizedFilesVector()的数据虚拟化。这对转换器最有效。

我用过的东西:

获取虚拟化文件列表并绑定到ListView

private async void GetPicturesFromGalleryFolder()
{
    var queryOptions = new QueryOptions();
    queryOptions.FolderDepth = FolderDepth.Shallow;
    queryOptions.IndexerOption = IndexerOption.UseIndexerWhenAvailable;
    queryOptions.SortOrder.Clear();

    var sortEntry = new SortEntry {PropertyName = "System.DateModified", AscendingOrder = false};
    queryOptions.SortOrder.Add(sortEntry);
    queryOptions.FileTypeFilter.Add(".png");

    var fileQuery = KnownFolders.PicturesLibrary.CreateFileQueryWithOptions(queryOptions);
    var fileInformationFactory =
        new FileInformationFactory(
            fileQuery,
            ThumbnailMode.PicturesView,
            0,
            ThumbnailOptions.None,
            true);

    MyListView.ItemsSource = fileInformationFactory.GetVirtualizedFilesVector();
}

<强> XAML

<ListView.ItemTemplate>
    <DataTemplate>
        <Image
            Source="{Binding Converter={StaticResource converters:IStorageItemInformationToBitmapImageConverter}"/>
    </DataTemplate>
</ListView.ItemTemplate>

<强> IStorageItemInformationToBitmapImageConverter

public class IStorageItemInformationToBitmapImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var fileInfo = value as FileInformation;

        if (fileInfo != null)
        {
            var bi = new BitmapImage();

            // The file is being opened asynchronously but we return the BitmapImage immediately.
            SetSourceAsync(bi, fileInfo);
            return bi;

        }

        return null;
    }

    private async void SetSourceAsync(BitmapImage bi, FileInformation fi)
    {
        try
        {
            using (var stream = await fi.OpenReadAsync())
            {
                await bi.SetSourceAsync(stream);
            }
        }
        catch
        {
            // ignore failure
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return null;
    }
}