WPF ListBox.ItemsSource = ObservableCollection - 加载时间过长

WPF ListBox.ItemsSource = ObservableCollection - takes a long time to load

我有这样的代码: (将自定义对象的集合加载到内存和列表框项中)

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 正在创建并且它正在做一些事情。我无法弥补任何更快的方式。

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

默认情况下,ListBox 使用 VirtualizingStackPanel 作为 ItemsPanel,这意味着 ItemsSource 实际上可以包含 无限数量的项目而不会影响性能

在不修改列表框的干净解决方案中试试这个。它显示百万项没有问题

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

VirtualizingStackPanel 仅为那些当前在滚动查看器中可见的项目实例化 DataTemplate。这叫虚拟化

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

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

您是否在使用任何 wpf 主题或列表框的某些隐式样式?

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

只是为了确定,这是虚拟化问题,尝试用最简单的可能替换您的数据模板 - 空矩形,甚至删除它。 希望这有帮助。