ListBox虚拟化不卸载项目

时间:2017-07-10 15:03:38

标签: wpf listbox virtualization

我在列表框中加载了大量图片。 在我尝试虚拟化之前有一个合理的加载时间。

现在我只使用虚拟化,只是按照我想要的方式加载落入视图的元素; 但是一旦他们落在视图之外他们似乎没有卸载所以如果我一直向下滚动到底部所有项目都被加载,我失去了虚拟化的优势。

在显示任何图像之前,我的应用程序消耗140MB,然后我显示10张图像,我的内存使用量等于161MB,如果我滚动到最后一张图像,则使用量为300MB。如果10个图像使用21 MB,则必须加载300MB所有图像。

通过使用Snoop检查加载的ListBoxItems的数量,进一步确认了此行为。

代码没什么特别之处,我只是确保CanContentScroll启用不是禁用虚拟化。我自定义ItemContainerStyleListBox的模板,但它不应该影响虚拟化(或者至少不仅仅是卸载部分),不是吗?

<ListBox ItemsSource="{Binding myItems}"  CanContentScroll="True"/>

我错过了什么吗?

结论

虚拟化显然有效。每个ItemContainer都会在它们落在视图之外的某个时刻卸载。

问题可能是BitmapImage如何缓存。事实上,我使用以下DataTemplate来显示图像:

 <Image>
     <Image.Source>
         <BitmapImage UriSource="{Binding}" />
     </Image.Source>
 </Image>

1 个答案:

答案 0 :(得分:1)

此处发生的是BitmapImageStream的内存泄漏问题。 问题描述为here

解决方案是通过WrappingStream阅读图片,如上所述并实施here

阅读这样的图像并将其分配给Image.Source

  BitmapImage bitmap = new BitmapImage();

  using( var stream = new FileStream( uri, FileMode.Open ) )
  using( WrappingStream wrapper = new WrappingStream( stream ) )
  {
      bitmap.BeginInit();
      bitmap.CacheOption = BitmapCacheOption.OnLoad;
      bitmap.StreamSource = stream;
      bitmap.EndInit();
      bitmap.Freeze();
 }

  return bitmap;