WinRT preload images

2019-05-24 18:01发布

I have a Windows 8.1 XAML app where I'd like to preload images before navigating between pages.

The naive code I have now is:

// Page1.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
  Frame.Navigate(typeof(Page2));
}

And on the second page:

// Page2.xaml.cs
this.image1.Source = new BitmapImage(new Uri("ms-appx:///Assets/image1.jpg"));
this.image2.Source = new BitmapImage(new Uri("ms-appx:///Assets/image2.jpg"));

Now, when I click the button to navigate, I can see the images being loaded and showing up one at the time. I would like to pre-load the images on the button click and only navigate after the images have been loaded.

Unfortunately, just creating the BitmapImage objects and waiting for the ImageOpened events doesn't work. It appears that the images aren't loaded if they aren't rendered to the screen.

Is there a way to force loading of the images from code without adding them to the visual tree?

(Note: a workaround would be to actually add all the images to the Window in some invisible way, but I'd like to avoid that if at all possible)


Final solution:

This is what I've come up with using SetSourceAsync, as suggested by Filip Skakun:

// Page1.xaml.cs
private async void Button_Click(object sender, RoutedEventArgs e)
{
  bitmapImage1 = new BitmapImage();
  bitmapImage2 = new BitmapImage();

  // Load both images in parallel
  var task1 = loadImageAsync(bitmapImage1, "image1.jpg");
  var task2 = loadImageAsync(bitmapImage2, "image2.jpg");
  await Task.WhenAll(task1, task2);

  Frame.Navigate(typeof(Page2));
}

private Task loadImageAsync(BitmapImage bitmapImage, string path)
{
  var filePath = ApplicationData.Current.LocalFolder.Path + "\\" + path;
  var file = await StorageFile.GetFileFromPathAsync(filePath);
  var stream = await file.OpenAsync(FileAccessMode.Read);
  await bitmapImage.SetSourceAsync(stream);
}
// Page2.xaml.cs
this.image1.Source = bitmapImage1;
this.image2.Source = bitmapImage2;

1条回答
欢心
2楼-- · 2019-05-24 18:55

WinRT XAML Toolkit's AlternativeFrame control and AlternativePage one have a ShouldWaitForImagesToLoad property that when you set to true and navigate to a page - will only display the page when the images have loaded. AlternativePage has a Preload() method you can also override to add more things to await before displaying the page. The way it is implemented though is the page is first added to an invisible container in the visual tree, so loading of those BitmapImages gets triggered.

Another option might be to use SetSourceAsync() which you can await and I think it starts loading before you use the BitmapImage in the UI, but then you need to download the file yourself.

查看更多
登录 后发表回答