2016-04-29 100 views
1

相对于UWP和XAML而言,我并不确定如何进行调试。带有网格视图的UWP应用程序在滚动时丢失图像

我有一个基于Template10汉堡包模板和Tem​​plate10增量加载示例的UWP应用程序,以及来自示例照片查看器(Windows 8: Making a Simple Photo Viewer in C# and XAML)的一些位。

我修改了主页面以显示来自图片文件夹的图像的Gridview,图像被逐步加载。我也从一个样本照片浏览器中拉出了一些(Windows 8: Making a Simple Photo Viewer in C# and XAML)。

当应用程序启动时,图像按预期显示,当向下滚动时,图像将按需加载和显示。问题是,当我向后滚动列表时,图像不再显示。我的gridview项目仍然显示文件名称和彩色项目背景,但图像不再绘制。

为了保持我的记忆足迹小,我没有将实际的位图图像存储为我的集合的一部分,而是存储了一个StorageItemThumbnail。我原本想存储图像路径,但不适用于图片库中的任何内容。

public class Picture 
{ 
    public StorageItemThumbnail ImageThumbNail {get; set;} 
    public string Name {get; set;} 
} 

要显示此,我用一个转换器类来创建一个流,设置图片来源:

public object Convert(object value, Type targetType, object parameter, string language) 
{ 

    BitmapImage image = null; 

    if (value != null) 
    { 
     if (value.GetType() != typeof(StorageItemThumbnail)) 
     { 
      throw new ArgumentException("Expected a StorageItemThumbnail as binding input."); 
     } 
     if (targetType != typeof(ImageSource)) 
     { 
      throw new ArgumentException("Expected ImageSource as binding output."); 
     } 

     if (Windows.ApplicationModel.DesignMode.DesignModeEnabled) 
     { 
      image = new BitmapImage(); 
      image.UriSource = new Uri("ms-appx:///Assets/DesignModeThumbnailPlaceholder.png"); 
     } 
     else 
     { 
      StorageItemThumbnail ThumbNailFile = (StorageItemThumbnail)value; 

      if (ThumbNailFile == null) 
       return image; 

      image = new BitmapImage(); 
      IRandomAccessStream thumbnailStream = ThumbNailFile as IRandomAccessStream; 
      image.SetSource(thumbnailStream); 
     } 

    } 

    return (image); 

} 

,这是我的XAML的约束如下:

<DataTemplate x:Name="PictureGridTemplate2"> 
    <Grid Height="150" Width="150"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <Border Grid.RowSpan="2" Background="Black" Opacity="0.8" /> 
     <Image Width ="130" HorizontalAlignment="Center" 
       Stretch="Uniform" Source="{Binding ImageThumbNail, Converter={StaticResource ThumbnailFileToImageSourceConverter}}"/> 
     <TextBlock Grid.Row="1" MaxHeight="30" Text="{Binding Name}" 
        Foreground="White" TextTrimming="CharacterEllipsis"/> 
    </Grid> 
</DataTemplate> 

任何人都可以指出我出错的方向吗?

社日

*解决*

我终于能找出是什么造成了这个问题。

这是Gridview虚拟化,我的数据模型和我如何通过转换器提供图像的副作用。

作为一个测试,我删除了转换器,改变了我的数据模型以存储缩略图的BitmapImage实例(小于存储整个图像)并直接绑定到该属性。这工作,通过我的GridView上下滚动屏幕上显示的图像。

然后,我改变了我的数据模型,使BitmapImage属性获取器从StorageItemThumbnail属性即时返回BitmapImage构建 - 与使用转换器时相同的问题。

通过在getter中添加一些调试语句,我看到第二个请求上的BitmapImage的高度和宽度为0. Aha!那么为什么是0?

查看第二个请求上的StorageItemThumbnail属性,我看到Stream位置在EOF(不像第一个请求那样是0) - 所以这解释了0宽度和高度,这解释了图像上的空图像控制屏幕。

我更改了我的代码以使用StorageItemThumbnail.CloneStream,现在显示所有图像。

这里现在是转换器的方法:

public object Convert(object value, Type targetType, object parameter, string language) 
    { 

     BitmapImage image = null; 

     if (value != null) 
     { 
      if (value.GetType() != typeof(StorageItemThumbnail)) 
      { 
       throw new ArgumentException("Expected a StorageItemThumbnail as binding input."); 
      } 
      if (targetType != typeof(ImageSource)) 
      { 
       throw new ArgumentException("Expected ImageSource as binding output."); 
      } 

      if ((StorageItemThumbnail)value == null) 
      { 
       System.Diagnostics.Debug.WriteLine("Thumbnail is null."); 
       return image; 
      } 

      image = new BitmapImage(); 

      using (var thumbNailClonedStream = ((StorageItemThumbnail)value).CloneStream()) 
      { 
       System.Diagnostics.Debug.WriteLine("Setting image source from cloned stream."); 
       image.SetSource(thumbNailClonedStream); 
      } 
     } 

     return (image); 

    } 

谢谢大家谁花时间来回答和帮助点我在正确的方向。

+0

转换器的原因。每次当您每次滚动创建图像时都会调用它。而是存储BitMapImage本身。 – Archana

+0

我不这么认为,如果我在Convert方法中放置了一个断点,它只会在每个图像被增量加载时被命中一次。一旦它全部加载完毕,我可以根据需要上下滚动,并且不会触发断点。不存储BitmapImage背后的原因是保持内存占用低。 – SheriSteeves

回答

0

您可以尝试使用编译结合X:绑定,而不是绑定
在这种情况下,你的应用程序性能比较会更加快捷。

优化您的DataTemplate与阶段逐步更新GridView的项目:

<Grid Height="150" Width="150"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Border Grid.RowSpan="2" Background="Black" Opacity="0.8" /> 
    <Image Width ="130" HorizontalAlignment="Center" 
      Stretch="Uniform" Source="{Binding ImageThumbNail, Converter={StaticResource ThumbnailFileToImageSourceConverter}}" x:Phase="2"/> 
    <TextBlock Grid.Row="1" MaxHeight="30" Text="{Binding Name}" x:Phase="1" 
       Foreground="White" TextTrimming="CharacterEllipsis"/> 
    </Grid> 

阅读本主题:
ListView and GridView UI optimization
ListView and GridView data virtualization

+0

现在我的问题不是速度,图像或实际缩略图的加载速度相当快。我将查看x:绑定并在稍后的资源字典日期模板中使用它。 问题是Image控件停止显示它们。 当应用第一次打开时,我的图像显示在屏幕上显示的gridview项目中,当向下滚动时,我看到所有其他图像。但是 - 如果我向后滚动,在某些时候图像不再显示,只有黑色gridview项目和名称作为文本框。 – SheriSteeves

+0

这看起来像数据虚拟化问题 –

+0

这是因为我能够在Template10增量示例代码中通过向列表视图模板添加图像来重现我的应用程序不良行为。这就像它不知道它已被视图卸载,所以它不知道何时重新加载它。我是一个完整的新手,所以我不确定我错过了什么,但我正在看你的建议和其他样本。 – SheriSteeves