简体   繁体   中英

Binding Images to GridView Windows 8

This question is similar in some regards to this one:

Windows 8 XAML: Displaying a list of images in a GridView through data binding

I followed the instructions listed therein for loading images into my own GridView and I went from having a few images loading of many to only having the very first image load and that's it; the rest don't even show up as blank, whereas before they would all be there if not fully loaded. Here is my code, which utilizes much of the same as is in the aforementioned question:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI.Xaml.Media.Imaging;
using Windows.Storage.Streams;

namespace present50_2
{
    public class SlideData
    {
        // slide collection that will be used to populate app slides page
        public List<Slide> Slides = new List<Slide>();

        // image files that will be asynchronously loaded
        public IReadOnlyList<StorageFile> files;

        public SlideData(IReadOnlyList<StorageFile> files)
        {
            this.files = files;
        }

        public async void loadSlides()
        {
            int counter = 1;
            Slides = new List<Slide>();

            foreach (var file in files)
            {
                using (var stream = await file.OpenAsync(FileAccessMode.Read))
                {
                    Slides.Add(new Slide(stream, counter.ToString()));
                }

                counter++;
            }
        }

        public class Slide
        {
            public Slide()
            {

            }

            public Slide(IRandomAccessStream stream, string name)
            {
                BitmapImage bmp = new BitmapImage();
                bmp.SetSource(stream);
                Image = bmp;
                this.Title = name;
            }

            /*
            public async void LoadImage()
            {
                IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
                BitmapImage bi = new BitmapImage();
                bi.SetSource(fileStream);
                this.Image = bi;
            } */

            public string Title { set; get; }
            public BitmapImage Image { set; get; }
        }
    }
}

That class is what holds the data that will be bound to the grid. This is the code that calls said class:

protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
            var folderPicker = new FolderPicker();
            folderPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
            folderPicker.FileTypeFilter.Add(".png");
            StorageFolder folder = await folderPicker.PickSingleFolderAsync();

            if (folder != null)
            {
                IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
                SlideData slides = new SlideData(files);
                slides.loadSlides();
                this.DefaultViewModel["Items"] = slides.Slides;
            }
        }

I'm using just the following XAML for the actual grid layout and binding:

<!-- Grid-appropriate 125 pixel square item template as seen in the GroupedItemsPage and ItemsPage -->
    <DataTemplate x:Key="Standard125x125ItemTemplate">
        <Grid HorizontalAlignment="Left" Width="125" Height="125">
            <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                <Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
            </Border>
            <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="30" Margin="7,0,7,0"/>
            </StackPanel>
        </Grid>
    </DataTemplate>

That code is merely a modification of the 250x250 template that comes in StandardStyles.xaml.

Originally, I was unable to get any images to load at all on the screen (they just showed up as gray squares). Then with an implementation I saw here (the Kiwi example), I was able to get some of the images to load but most still stayed gray:

http://social.msdn.microsoft.com/Forums/windowsapps/en-US/252d4d14-1db3-4f04-93b6-d2eab2c386bc/c-metro-displaying-images-in-a-listview-or-gridview

Then, with the last solution I posted above, I've been able to get just the very first slide to show up but none of the other slides even show up as gray boxes, let alone loaded. Help would be greatly appreciated!

A Little Background

To start, let's take a look at this line in the LoadState function:

slides.loadSlides();

The way the above is currently written, the call to loadSlides starts to execute. Since it is an asynchronous method, it executes in parallel with the code that follows it:

this.DefaultViewModel["Items"] = slides.Slides;
...

What is happening is that the grid is being bound to the collection prior to the completion of the loadSlides method. This is the reason you may only see one or two images.

The Solution

To resolve this you must fix the way that your are calling the loadSlides function. First, change the function signature from void to Task :

public async Task loadSlides() { ... }

Next, you need to await the call to loadSlides . When you await an asynchronous method, you are in effect waiting for that method to finish prior to continuing execution. Note that only methods that return Task (or some variation of Task<..> ) can be awaited . After you have added the await , the code in your page's LoadState function should look like:

...
SlideData slides = new SlideData(files);
await slides.loadSlides();
this.DefaultViewModel["Items"] = slides.Slides;
...

Now when loadSlides is called, your program will wait until it finishes. Then the next line will be called, which will bind your grid to the complete slide data. This should allow you to see all of the images.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM