Wpf 为什么<;图像源=''&燃气轮机;这么慢,我该怎么办?
考虑下面的XAML示例文件,它显示了Facebook的前1000人,从markz开始是第4人。请注意,这只是一个示例。任何包含1000个元素的窗口,无论您如何构造它,都是一个很好的演示Wpf 为什么<;图像源=''&燃气轮机;这么慢,我该怎么办?,wpf,caching,Wpf,Caching,考虑下面的XAML示例文件,它显示了Facebook的前1000人,从markz开始是第4人。请注意,这只是一个示例。任何包含1000个元素的窗口,无论您如何构造它,都是一个很好的演示 <Window x:Class="SO.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/wi
<Window x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:clr="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
以及背后的代码:
public partial class MainWindow : Window
{
public MainWindow() {
InitializeComponent();
string[] urls = new string[1000];
for (int i = 0; i < 1000; ++i) {
urls[i] = "http://graph.facebook.com/" + i + "/picture";
}
this.DataContext = urls;
}
}
公共部分类主窗口:窗口
{
公共主窗口(){
初始化组件();
字符串[]URL=新字符串[1000];
对于(int i=0;i<1000;++i){
URL[i]=”http://graph.facebook.com/“+i+”/图片”;
}
this.DataContext=URL;
}
}
在一个非常合理的桌面和高速连接上,程序非常慢。正在尝试使用滚动条滚动。。。说中间,需要30秒。按“开始”和“结束”键将花费大量时间
这不是第一次仅将图像获取到缓存的问题。来回观看已经呈现的图片稍微快一些,但通常非常慢。看起来缓存中没有存储任何内容,关闭应用程序并重新启动,一切又变慢了
相当于HTML代码的速度非常快。第一次有些慢,但后来一切都很快
发生了什么事?元素是否使用任何缓存?列表是否对当前未显示的图像进行预取?有什么办法可以告诉它去做吗?我唯一的解决方案是自己管理位图对象,以及缓存和预取逻辑吗?如果是的话,我以前的工作可以合并吗
编辑(摘要):
listboxs
默认情况下虚拟化项目,因此如果向下滚动,项目将动态创建。首先它需要下载图像,然后对其进行解码。如果您已滚动浏览所有图像,它们可能会被缓存,但列表框
仍将重新创建图像
控件,因此每次都需要对图像进行解码
您可以通过将
列表框上的设置为false
来关闭虚拟化,然后立即加载所有内容,或者您可以将更改为回收
,然后是图像
(并包含列表框项
)创建后不会被丢弃。另一种方法是添加自己的图像缓存,这样图像只需下载一次
使用我的示例,您可以将其放入构造函数中
this.DataContext = new ViewModel();
下面的类将存储url,然后在首次访问image属性时下载图像
public class CachingImage
{
private readonly Uri _uri;
public CachingImage(string uriString)
{
_uri = new Uri(uriString, UriKind.RelativeOrAbsolute);
}
private BitmapImage _image;
public ImageSource Image
{
get
{
if (_image == null)
{
_image = new BitmapImage(_uri);
_image.DownloadCompleted += (sender, args) => ((BitmapImage)sender).Freeze();
}
return _image;
}
}
}
这是视图模型
public class ViewModel
{
public ViewModel()
{
Images = Enumerable.Range(1, 1000).Select(i => new CachingImage("http://graph.facebook.com/" + i + "/picture"));
}
public IEnumerable<CachingImage> Images { get; private set; }
...
公共类视图模型
{
公共视图模型()
{
Images=Enumerable.Range(11000)。选择(i=>newcachingimage(“http://graph.facebook.com/“+i+”/图片”);
}
公共IEnumerable映像{get;private set;}
...
当然,您需要稍微更改xaml
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Image}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>