2011-11-20 146 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