2011-11-20 170 views
36

我试图将大型集合绑定到ComboBox,并在打开ComboBox弹出窗口时遇到性能问题。我搜索了互联网,发现使用VirtualizingStackPanel作为项目面板模板可能会有所帮助,但它只能部分帮助。如果我将大集合绑定到ComboBox,我可以非常快速地打开弹出窗口,没关系,但如果在此之后将另一个集合绑定到ComboBox并尝试再次打开弹出窗口,则会变得非常缓慢。如果您打开空的ComboBox的弹出窗口,然后绑定大集合并尝试再次打开弹出窗口,弹出窗口打开前需要几秒钟,这种情况也会发生。通过绑定大型集合WPF组合框性能问题

这里是XAML:

<ComboBox Name="cbBlah"> 
    <ComboBox.ItemsPanel> 
     <ItemsPanelTemplate> 
      <VirtualizingStackPanel /> 
     </ItemsPanelTemplate> 
    </ComboBox.ItemsPanel> 
</ComboBox> 

,并结合重现问题的示例代码:

var list = new List<string>(); 
for (var i = 0; i < new Random().Next(9000, 10000); i++) 
    list.Add(i.ToString()); 
cbBlah.ItemsSource = list; 

我试图让虚拟化堆栈面板看起来像这样:

<VirtualizingStackPanel VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" /> 

但它并没有帮助,似乎VirtualizationMode被忽略,所以popup只有第一次打开速度非常快,然后,每次绑定更改后,它都非常慢。

UPDATE:我想过每次都不绑定新的集合,而是绑定一次ObservableCollection,然后只是改变它的内容。同样的事情,只要收集的内容改变,打开一个弹出仍然需要几秒钟:(

+0

看一看这些问题,我回答http://stackoverflow.com/a/8555403/920384 – punker76

回答

79

根据这一博客:http://vbcity.com/blogs/xtab/archive/2009/12/15/wpf-using-a-virtualizingstackpanel-to-improve-combobox-performance.aspx

我使用此代码测试它:

<ComboBox Name="cbBlah" ItemsSource="{Binding}"> 
    <ComboBox.ItemsPanel> 
     <ItemsPanelTemplate> 
      <VirtualizingStackPanel /> 
     </ItemsPanelTemplate> 
    </ComboBox.ItemsPanel> 
</ComboBox> 

它工作正常的第一次和今后一段时期这是没有必要将这些线CODE:。

<VirtualizingStackPanel VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" /> 

我希望这有助于你

+0

这么少的代码和工程就像一个魅力! – Tafari

+0

你,先生,是个天才!这为我带来了巨大的性能差异,并且修复非常简洁。谢谢! :) – dbeachy1

+1

是否有可能用C#代码实现这一点?我正在实施一个派生于Combobox的类,我想在此处设置它。 – jonas

0

我刚刚遇到了这个问题。我在带有样式模板的自定义组合框中使用此代码。当我在VS调试模式下运行我的代码时,虚拟化无法正常工作。一旦我在调试之外运行它,我可以在不锁定UI的情况下切换ObservableCollection的内容。如果您设置最大高度和最大宽度,它也可能有所帮助。

<Setter Property="ScrollViewer.CanContentScroll" Value="True"/> 
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/> 
<Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling"/> 
<Popup> 
    <Border/> 
    <ScrollViewer> 
     <VirtualizingStackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/> 
    </ScrollViewer> 
    </Grid> 
</Popup> 
8

我有性能下降的问题也是如此。但是我创建了一个继承自Combobox的类,因此我想以编程方式执行此操作。所以这里有其他Google的解决方案。

ItemsPanel = new ItemsPanelTemplate(); 
var stackPanelTemplate = new FrameworkElementFactory(typeof (VirtualizingStackPanel)); 
ItemsPanel.VisualTree = stackPanelTemplate; 
+0

将代码打包到构造函数中,工作得很好。干杯! – Kris

+0

美丽的解决方案:)谢谢 – HuyNA

+0

我知道这是一个旧的帖子,但对于Google的同伴们来说,这里就是一个优雅的解决方案。极大地加速了事情。 – Chris