it-swarm.com.de

WPF ComboBox-Leistungsprobleme durch das Binden einer großen Sammlung

Ich versuche, eine große Sammlung an eine ComboBox zu binden, und beim Öffnen der ComboBox-Popup-Seite kam es zu Leistungsproblemen. Ich durchsuchte das Internet und stellte fest, dass die Verwendung von VirtualizingStackPanel als Vorlage für das Elementfenster hilfreich sein könnte, aber es half nur teilweise. Wenn ich eine große Sammlung an eine ComboBox binde, könnte ich Popup sehr schnell öffnen, das ist in Ordnung, aber wenn ich danach eine andere Sammlung an eine ComboBox binde und versuche, Popup erneut zu öffnen, wird es sehr langsam. Dasselbe passiert, wenn Sie das Popup für eine leere ComboBox öffnen, dann eine große Sammlung binden und versuchen, das Popup erneut zu öffnen. Es dauert einige Sekunden, bis das Popup geöffnet wird.

Hier ist die XAML:

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

und den Beispielcode für die Bindung, um das Problem zu reproduzieren:

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

Ich habe versucht, das Virtualisierungs-Stack-Panel so aussehen zu lassen:

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

aber es hilft nicht, VirtualizationMode wird ignoriert, so dass sich das Popup-Menü beim ersten Mal sehr schnell öffnet und dann jedes Mal, wenn die Bindung geändert wird, sehr langsam ist.

UPDATE: Ich habe mir überlegt, nicht jedes Mal eine neue Sammlung zu binden, sondern eine ObservableCollection einmal zu binden und dann nur den Inhalt zu ändern. Dasselbe gilt, sobald sich der Inhalt der Sammlung ändert, dauert das Öffnen eines Popups noch einige Sekunden :(

41
Alexey

Laut diesem Blog: http://vbcity.com/blogs/xtab/archive/2009/12/15/wpf-using-a-virtualizingstackpanel-to-improve-combobox-performance.aspx

Ich habe es mit diesem Code getestet:

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

Es funktioniert gut für das erste Mal und das nächste Mal. Es ist nicht notwendig, diese Zeilen zu codieren: 

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

Ich hoffe das hilft dir.

91
Miguel

Ich hatte auch das Problem mit langsamer Leistung. Ich hatte jedoch eine Klasse erstellt, die von Combobox übernommen wurde, deshalb möchte ich dies programmgesteuert machen. Also hier ist diese Lösung für andere Googler da draußen.

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

Ich bin auch auf dieses Thema gestoßen. Ich verwende diesen Code in einem benutzerdefinierten Kombinationsfeld mit einer Stilvorlage. Wenn ich meinen Code im VS-Debugging-Modus ausgeführt habe, funktionierte die Virtualisierung nicht ordnungsgemäß. Sobald ich es außerhalb des Debugging ausgeführt habe, kann ich den Inhalt der ObservableCollection wechseln, ohne die Benutzeroberfläche zu blockieren. Es kann auch hilfreich sein, wenn Sie eine maximale Höhe und eine maximale Breite einstellen.

<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>
0
Phillip