考虑以下示例XAML文件,其中显示Facebook的前1000人,以markz作为第4人开始。请注意,这只是一个示例。任何有1000个元素的窗口,无论你如何构建它,都是一个很好的示范。为什么<Image Source ='...'>这么慢,我能做些什么呢?
<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;
}
}
在一个非常合理的台式机和高速连接,程序是极其缓慢。试图用ScrollBar滚动...说到中间,将需要30秒。点击“主页”和“结束”键将花费大量时间。
这不是第一次得到图像到缓存问题。来回看看已经呈现的图片比较快,但通常非常慢。看起来没有任何东西存储在缓存中,关闭应用程序并重新启动它,一切都很慢。
等效的HTML代码快速流血。第一次有些缓慢,但一切都很快。
这是怎么回事?元素是否使用任何缓存?该列表是否对当前未呈现的图像进行预取?无论如何要告诉它做?我真的唯一的解决方案是自己管理Bitmap对象,还有缓存和预取逻辑?如果是这样,以前的任何工作我可以合并?
EDIT(摘要):
- @ H.B。答案关闭虚拟化会给你最好的结果。整个列表框会在窗口加载后立即生成,并且不会重新计算图像
- @Pil代码效果很好,它可以提高性能,特别是在来回时。
- 没有任何额外的代码,WPF不会在调用之间缓存图像。 WinINET缓存使用的是而不是。尽管请求在HTTP Header中带有Cache指令,但WPF并没有执行任何操作。
谢谢H.B. +1并接受。 – Uri 2012-02-26 06:52:28