【发布时间】:2017-07-27 03:24:48
【问题描述】:
我以前使用后面的代码手动将项目添加到我的 ListBox,但速度非常慢。我听说通过 XAML 进行数据绑定在性能方面是可行的方法。
所以我设法让数据绑定工作(绑定的新手),但令我沮丧的是,性能并不比我以前的非数据绑定方法好。
我的想法是我的 ListBox 包含一个带有名称的图像。我做了一些基准测试,54 个项目需要整整 8 秒才能显示。这对于用户来说自然是等待太久了。
源图像最大:2100x1535px,范围为 400kb>4mb/文件。
可以在此处找到重现此问题所需的图像:链接已删除,因为问题已得到解答,并且我的服务器没有太多的带宽余量。其他图片来源:https://imgur.com/a/jmbv6
我为以下问题制作了一个可重现的示例。我做错了什么让这变得如此缓慢?
谢谢。
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="800" WindowState="Maximized">
<Grid>
<ListBox x:Name="listBoxItems" ItemsSource="{Binding ItemsCollection}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<VirtualizingStackPanel>
<Image Width="278" Height="178">
<Image.Source>
<BitmapImage DecodePixelWidth="278" UriSource="{Binding ImagePath}" CreateOptions="IgnoreColorProfile" />
</Image.Source>
</Image>
<TextBlock Text="{Binding Name}" FontSize="16" VerticalAlignment="Bottom" HorizontalAlignment="Center" />
</VirtualizingStackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
背后的代码:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Threading;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
internal class Item : INotifyPropertyChanged
{
public Item(string name = null)
{
this.Name = name;
}
public string Name { get; set; }
public string ImagePath { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ObservableCollection<Item> ItemsCollection;
List<Item> data;
public MainWindow()
{
InitializeComponent();
this.data = new List<Item>();
this.ItemsCollection = new ObservableCollection<Item>();
this.listBoxItems.ItemsSource = this.ItemsCollection;
for (int i = 0; i < 49; i ++)
{
Item newItem = new Item
{
ImagePath = String.Format(@"Images/{0}.jpg", i + 1),
Name = "Item: " + i
};
this.data.Add(newItem);
}
foreach (var item in this.data.Select((value, i) => new { i, value }))
{
Dispatcher.Invoke(new Action(() =>
{
this.ItemsCollection.Add(item.value);
}), DispatcherPriority.Background);
}
}
}
}
【问题讨论】:
-
刚刚用 50 张 300-900kb 范围内的图像对其进行了测试,它几乎立即显示出来......但是,我不得不复制一些图像并重命名它们,没有足够的可用测试材料。
-
小图像可以,是的。正是大而详细的图像让它爬行
-
@PeterDuniho Aha,看起来 imgur 正在压缩它们。这是全部下载的链接:s.imgur.com/a/jmbv6/zip - 我也会将其添加到 OP
-
@PeterDuniho 是的,我也在这里验证了自己。好吧,这简直是疯了。我比较了两张图片(我的源图片和来自 zip 的一张),文件大小有 3mb 的差异)。看起来图像在上传到 Imgur 时被压缩到了一定程度;/
-
@PeterDuniho 我将不得不将图像上传到我的站点并提供直接下载,以防止图像完整性。我现在就这样做
标签: c# wpf xaml data-binding listbox