2

我的图像加载阻塞 UI 线程时遇到问题,因此我的 gridview 在我的 Windows 商店应用程序中没有响应。

我想要做的是让 gridview 中的图像绑定到我的视图模型中的图像属性。image 属性的值由异步方法设置。当应用程序启动时,它会加载所有对象,但不会加载实际的图像数据。当 UI 虚拟化启动并通过绑定到 xaml 中的图像控件的图像属性请求图像数据时,将加载图像数据。

所有这些都在 observablecollection 中完成。

这是一些代码:

    private ImageSource _image = null;
    private String _imagePath = null;
    public ImageSource Image
    {
        get
        {
            SetImageFromStorageFile().ContinueWith(OnAsyncFail, TaskContinuationOptions.OnlyOnFaulted);
            return this._image;
        }
    }

    private async Task SetImageFromStorageFile()
    {
        this.IsLoading = true;
        if (this._image == null && this._imagePath != null)
        {
                this._image = await BitmapLoader.GetPreviewImageFromStorageFile(this.StorageFile); //getting the actual data here
                this.OnPropertyChanged("Image");
        }
        this.IsLoading = false;
    }

除了访问图像数据时 UI 变得无响应之外,这一切都很好。

如您所见,我正在从属性调用异步方法,我只是在重用从其他地方调用的代码。当从其他地方调用时,我可以使用 await 并且 UI 是响应式的。问题是,当使用 gridviews UI 虚拟化时,我不知道如何在不阻塞 UI 的情况下运行此异步方法,因为属性无法运行异步(据我所知)。

所以我只想让gridview异步运行这个属性(或方法)而不是同步,但不知道该怎么做。

请帮忙 :)

4

2 回答 2

1
private ImageSource _image = null;
private String _imagePath = null;
public ImageSource Image
{
    get
    {
        if (_image != null)
          return _image;
        if (_imagePath != null && !IsLoading)
          SetImageFromStorageFile();
        return null;
    }
}

private async void SetImageFromStorageFile()
{
    if (this.IsLoading || this._image != null || this._imagePath == null)
      return;
    this.IsLoading = true;
    try
    {
      this._image = await BitmapLoader.GetPreviewImageFromStorageFile(this.StorageFile); //getting the actual data here
      this.IsLoading = false;
      this.OnPropertyChanged("Image");
    }
    catch 
    {
      OnAsyncFail();
    }
}
于 2013-11-13T02:54:11.420 回答
0

无论您选择哪种策略,您都需要先返回一些东西,然后再填充它。这是一个在 vanilla WinRT 页面中测试过的示例;您可以通过将其拖放到具有ImagenamedimageTextBlocknamed的页面上来复制它status。这个可以进去OnNavigatedTo,或者其他合适的地方。

BitmapImage imgsrc = new BitmapImage();
Task.Run(async () =>
    {
        await Task.Delay(10000);
        await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
            new Windows.UI.Core.DispatchedHandler(() =>
                {
                    imgsrc.UriSource = new Uri("http://www.gratuit-en-ligne.com/telecharger-gratuit-en-ligne/telecharger-image-wallpaper-gratuit/image-wallpaper-animaux/img/images/image-wallpaper-animaux-autruche.jpg");
                }));
    });
image.Source = imgsrc;
status.Text = "Done";

我“返回”的东西是 a BitmapImage,它是 的子类ImageSource,所以它接近你想要使用的东西。这Task.Delay()只是为了在启动和图像填充之间引入明显的延迟,以便您可以看到状态文本在图像加载之前就已经设置好了。

要使此操作与您的样本一起使用,您需要ImageSource在您的属性中创建(或访问)一个并立即返回,而无需等待它被填充。然后您开始一个分配实际源数据的后台任务。

实际的因果链可能与我在这里展示的不同。例如,您可以从预先创建的图像源集合中访问图像源。这将允许您在调用该属性之前开始加载图像。但听起来这将是一个让你朝着正确方向前进的开始。

于 2013-11-13T02:16:07.960 回答