wpf - 为什么 <Image Source ='...' > 这么慢,我该怎么办?

标签 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/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 秒。点击“Home”和“End”键将花费大量时间。

这不是第一次获取图像到缓存的问题。来回查看已经呈现的图片会更快一些,但通常非常慢。似乎没有任何东西存储在缓存中,关闭应用程序并重新启动它,一切又变慢了。

等效的 HTML 代码正在飞速发展。第一次有些慢,但后来一切都很快。

到底是怎么回事?元素是否使用任何缓存?该列表是否对当前未显示的图像进行任何预取?反正有告诉它怎么做吗?真的是我唯一的解决方案是自己管理位图对象,以及缓存和预取逻辑吗?如果是这样,我可以合并以前的任何工作吗?

编辑(摘要):
  • @HB关闭虚拟化的答案会给你最好的结果。加载 Window 后立即渲染整个列表框,并且不会重新计算图像
  • @Phil 代码效果很好,它提高了性能,尤其是在来回运行时。
  • 如果没有任何附加代码,WPF 将不会在调用之间缓存图像。 WinINET 缓存为 不是 用过的。尽管该请求在 HTTP header 中带有 Cache 指令,但 WPF 对此没有任何作用。
  • 最佳答案

    ListBoxes默认情况下对项目进行虚拟化,因此如果您向下滚动,项目将即时创建。首先它需要下载图像,然后对其进行解码。如果您滚动浏览了所有图像,它们可能会被缓存,但 ListBox仍将重新创建 Image控制,因此每次都需要再次解码图像。

    您可以通过设置 VirtualizingStackPanel.IsVirtualizing attached property 来关闭虚拟化。至falseListBox那么所有内容都会立即加载,或者您可以更改 VirtualizationMode Recycling ,然后是 Images (并包含 ListBoxItems )一旦创建就不会被丢弃。

    关于wpf - 为什么 <Image Source ='...' > 这么慢,我该怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9442297/

    相关文章:

    wpf - 当 TextBox 获得焦点时,UserControl 中的 KeyBinding 不起作用

    javascript - 服务调用后删除缓存

    android - 更新用户的个人资料图片

    c# - 具有 XAML 中定义的选项的数据绑定(bind) WPF ComboBox?

    wpf - 有没有办法判断 DependencyProperty 的值是来自绑定(bind)源还是目标?

    WPF - 在 View 模型中处理来自用户控件的事件

    java - 实现缓存 Spring 方法级注解 vs Hibernate 二级缓存

    c# - 在 Web API 使用的域项目中实现服务缓存

    ruby-on-rails - 如何在 Heroku 上刷新 Varnish 缓存

    WPF DataGrid 在 View 模式和编辑模式之间切换模板