WPF ComboBox通过绑定大型集合来解决性能问题

时间:2011-11-20 01:01:12

标签: wpf data-binding combobox wpf-controls

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

这是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,因此弹出窗口第一次打开非常快,然后,每次绑定更改后,它都非常慢。

UPDATE :我想过每次都不绑定新的集合,但是绑定ObservableCollection一次,然后只更改其内容。同样的事情,一旦收集内容发生变化,打开弹出窗口仍需要几秒钟:(

3 个答案:

答案 0 :(得分:97)

根据此博客: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>

第一次和下次都能正常工作。没有必要对这些行进行编码:

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

我希望这会对你有所帮助。

答案 1 :(得分:9)

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

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

答案 2 :(得分: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>
相关问题