Problemy z wydajnością WPF ComboBox poprzez wiązanie dużych zbiorów

Próbuję powiązać dużą kolekcję z Comboboxem i napotkałem problemy z wydajnością podczas otwierania wyskakującego okienka ComboBox. Przeszukałem internet i stwierdziłem, że użycie VirtualizingStackPanel jako szablonu panelu items może pomóc, ale pomogło tylko częściowo. Jeśli związać dużą kolekcję do ComboBox, mogę otworzyć popup bardzo szybko, to jest ok, ale jeśli po tym związać inną kolekcję do ComboBox i spróbować otworzyć popup ponownie, staje się bardzo powolny. To samo dzieje się, jeśli otworzysz wyskakujące okienko dla opróżnij ComboBox, następnie bind large collection i spróbuj ponownie otworzyć popup - to trwa kilka sekund zanim popup się otworzy.

Oto XAML:

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

I przykładowy kod wiązania do odtworzenia problemu:

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

Starałem się aby wirtualizujący panel stosu wyglądał tak:

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

Ale to nie pomaga, wygląda na to, że VirtualizationMode jest ignorowany, więc popup otwiera się bardzo szybko tylko za pierwszym razem i za każdym razem po związaniu zmian jest bardzo powoli.

UPDATE : myślałem o nie wiązaniu nowej kolekcji za każdym razem, ale związaniu Obserwowalnej kolekcji raz, a potem tylko zmianie jej zawartości. To samo, gdy tylko zawartość kolekcji się zmieni, otwarcie wyskakującego okienka trwa jeszcze kilka sekund : (

Author: Alexey, 2011-11-20

3 answers

Według tego bloga: http://vbcity.com/blogs/xtab/archive/2009/12/15/wpf-using-a-virtualizingstackpanel-to-improve-combobox-performance.aspx

Przetestowałem go z tym kodem:

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

Działa dobrze za pierwszym i następnym razem. Nie jest konieczne kodowanie tych linii:

<VirtualizingStackPanel VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" />
Mam nadzieję, że to ci pomoże.
 86
Author: Miguel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-19 14:30:24

Miałem też problem z powolną wydajnością. Ale stworzyłem klasę, która odziedziczyła Combobox, dlatego chciałbym to zrobić programowo. Oto rozwiązanie dla innych googlerów.

ItemsPanel = new ItemsPanelTemplate();
var stackPanelTemplate = new FrameworkElementFactory(typeof (VirtualizingStackPanel));
ItemsPanel.VisualTree = stackPanelTemplate;
 9
Author: jonas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-20 07:48:05

Właśnie natknąłem się na ten problem. Używam tego kodu w niestandardowym polu combo z szablonem stylu. Kiedy uruchomiłem mój kod w trybie debugowania VS wirtualizacja nie działała poprawnie. Po uruchomieniu go poza debugowaniem mogę przełączać zawartość ObservableCollection bez blokowania interfejsu użytkownika. Może to również pomóc, jeśli ustawisz maksymalną wysokość i maksymalną szerokość.

<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
Author: Phillip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-11 10:34:17