How to display images from the Picture Directory?

I want to display images in the Pictures library. I receive photos and link data.

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;

      

This is the getImage () method for setting the BitmapImage.

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;
 }

      

But the pictures are not displayed. I think it is because of the async function, but I don't know the solution. could you help me?

+3


source to share


2 answers


I'm not sure how you are using the data that is set to DefaultViewModel

, but yes, it looks like the method async

is your problem.

What you need to do is await

each challenge one way or another getImage()

. One way to do this is to use async

lambda in select

. But you need to use method syntax for this.

When you do this, you have IEnumerable<Task<a>>

(where a

is your anonymous type), but you only need IEnumerable<a>

. To get this use Task.WhenAll()

(which will return Task<a[]>

) and then await

its result:



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

      

This will do everything at getImage()

once, which may not be the most efficient solution. If you don't want this, you will need a different solution.

+2


source


Svick's solution seems to work, but as he said it might not be the most efficient solution. The best solution for a folder with an unknown number of files is to use data virtualization with FileInformationFactory.GetVirtualizedFilesVector()

. This works best with a converter.

Something I used:

Getting list of virtualized files and binding to 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;
    }
}

      

+1


source







All Articles