2011-11-20 5 views
36

Sto cercando di associare una grande raccolta a un ComboBox e ho riscontrato problemi di prestazioni all'apertura del popup di ComboBox. Ho cercato su Internet e ho scoperto che l'uso di VirtualizingStackPanel come modello di pannello di elementi poteva essere d'aiuto, ma ha aiutato solo parzialmente. Se lego una grande collezione a un ComboBox, potrei aprire popup velocemente, va bene, ma se poi lego un'altra raccolta a un ComboBox e provo ad aprire nuovamente popup, diventa molto lenta. Lo stesso sta accadendo se apri un popup per un ComboBox vuoto, poi leghi una grossa collezione e tenti di aprire nuovamente il popup - ci vogliono alcuni secondi prima che il popup si apra.Problemi di prestazioni di ComboBox WPF vincolando raccolte di grandi dimensioni

Ecco il codice XAML:

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

e il codice di esempio per il legame per riprodurre il problema:

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

ho cercato di rendere la virtualizzazione pannello stack a questo aspetto:

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

ma non aiuta, sembra VirtualizationMode viene ignorato in modo popup apre molto velocemente solo la prima volta e quindi, ogni volta dopo aver eseguito il binding delle modifiche, è molto lento.

UPDATE: Ho pensato di non legare la nuova raccolta ogni volta, ma di associare una ObservableCollection una volta e poi di cambiarne il contenuto. Stessa cosa, non appena il contenuto delle modifiche di raccolta, l'apertura di un pop-up ancora richiede alcuni secondi :(

+0

un'occhiata a queste domande che ho risposto http://stackoverflow.com/a/8555403/920384 – punker76

risposta

79

Secondo questo blog: http://vbcity.com/blogs/xtab/archive/2009/12/15/wpf-using-a-virtualizingstackpanel-to-improve-combobox-performance.aspx

ho provato con questo codice:

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

funziona bene per la prima volta e prossime volte non è necessario codificare queste righe:..

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

Spero che questo ti aiuta

+0

Così poco codice e funziona come un fascino! – Tafari

+0

Tu, signore, sei un genio! Ciò ha reso ENORME la differenza di prestazioni per me e la correzione è elegante e semplice. Grazie! :) – dbeachy1

+1

È possibile ottenere questo con il codice C#? Sto implementando una classe che deriva da Combobox e vorrei impostarla qui. – jonas

0

Mi sono appena imbattuto in questo problema. Sto usando questo codice in una casella combinata personalizzata con un modello di stile. Quando ho eseguito il mio codice in modalità di debug VS, la virtualizzazione non ha funzionato correttamente. Una volta che l'ho eseguito al di fuori del debug, posso cambiare il contenuto di ObservableCollection senza bloccare l'interfaccia utente. Potrebbe anche essere d'aiuto se si imposta l'altezza massima e la larghezza massima.

<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

ho avuto il problema con un rallentamento delle prestazioni pure. Ma avevo creato una classe che ereditava la forma di Combobox, quindi mi piacerebbe farlo a livello di programmazione. Quindi ecco la soluzione per altri googler là fuori.

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

Fracassato quel codice nel costruttore, ha funzionato magnificamente. Saluti! – Kris

+0

bellissima soluzione :) grazie – HuyNA

+0

Sono consapevole che questo è un vecchio post, ma per gli altri googler, questo qui era una soluzione elegante. Accelera incredibilmente _. – Chris

Problemi correlati