WPF ListBox.ItemsSource = ObservableCollection - 需要很长时间才能加载

时间:2015-03-05 10:47:12

标签: c# wpf listbox datatemplate stopwatch

我有这样的代码: (将自定义对象的集合加载到内存和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正在创建另一个线程并且它正在做某事。我无法以更快的方式弥补。

我做错了什么,但我不知道它是什么。请帮忙;)。

1 个答案:

答案 0 :(得分:1)

默认情况下,ListBox使用VirtualizingStackPanel作为ItemsPanel,这意味着ItemsSource几乎可以包含没有性能影响的无限数量的项目

在没有列表框修改的干净解决方案中尝试此操作。它显示了没有问题的百万项

<ListBox x:Name="listBox" />
listBox.ItemsSource = Enumerable.Range(0, 1000000).ToArray();

VirtualizingStackPanel仅为那些当前在scrollviewer中可见的项实例化DataTemplate。它被称为虚拟化

看来,你已经以某种方式打破了虚拟化。 原因可能是:

  • 您修改了列表框的样式或模板,因此它不使用VirtualizingStackPanel
  • 您已设置ScrollViewer.CanContentScroll =“False”
  • 您已设置IsVirtualizing =“False”
  • 有关详细信息,请参阅MSDN文章“Optimizing Performance

您使用的是任何wpf主题,还是列表框的一些隐式样式?

如果是ItemsControl,需要做一些工作才能使虚拟化工作:Virtualizing an ItemsControl?

只是为了确保它是虚拟化问题,尝试用最简单的方法替换你的datatemplate - 空矩形,甚至删除它。 希望这会有所帮助。