我有这样的代码: (将自定义对象的集合加载到内存和ListBox项中)
public class Product : INotifyPropertyChanged
{
// these four doesn't matter, just Product's simple data
public string nDB_No { get; set; }
public string fdGrp_Cd { get; set; }
public string long_Desc { get; set; }
public int refuse { get; set; }
// I do not load this Collection right away, only after explicit call
public ObservableCollection<Ingredient> ingredients { get; set; }
public Product() {sets all null}
public static ObservableCollection<Product> LoadProductsFromList(List<string> productList) {gets products data from SQLServer DB}
// and other methods irrelevant here
}
private void buttonCreate_Click(object sender, RoutedEventArgs e)
{
ObservableCollection<Product> productCollection = new ObservableCollection<Product>();
List<string> productList = getProductsNamesFromDB();
var watch = Stopwatch.StartNew();
productCollection = LoadProductsFromList(productList);
watch.Stop();
MessageBox.Show(watch.ElapsedMilliseconds);
// At this point there is about 700-800ms - that's ok, there's over 8000 records in DB
watch = Stopwatch.StartNew();
listBox.ItemsSource = productCollection;
watch.Stop();
MessageBox.Show(watch.ElapsedMilliseconds);
// At this point watch shows only about 500ms but it takes over 10 seconds
//to load the ListBox with data and to show the MessageBox.
}
listBox项附加了非常简单的DataTemplate,只有一个Rectangle,几个颜色和一个TextBlock。当我在附加listBox.ItemsSource后放置BreakPoints时,它会立即中断。所以看起来像ListBox正在创建另一个线程并且它正在做某事。我无法以更快的方式弥补。
我做错了什么,但我不知道它是什么。请帮忙;)。
答案 0 :(得分:1)
默认情况下,ListBox使用VirtualizingStackPanel作为ItemsPanel,这意味着ItemsSource几乎可以包含没有性能影响的无限数量的项目。
在没有列表框修改的干净解决方案中尝试此操作。它显示了没有问题的百万项
<ListBox x:Name="listBox" />
listBox.ItemsSource = Enumerable.Range(0, 1000000).ToArray();
VirtualizingStackPanel仅为那些当前在scrollviewer中可见的项实例化DataTemplate。它被称为虚拟化
看来,你已经以某种方式打破了虚拟化。 原因可能是:
您使用的是任何wpf主题,还是列表框的一些隐式样式?
如果是ItemsControl,需要做一些工作才能使虚拟化工作:Virtualizing an ItemsControl?
只是为了确保它是虚拟化问题,尝试用最简单的方法替换你的datatemplate - 空矩形,甚至删除它。 希望这会有所帮助。