Problemas de rendimiento de WPF ComboBox mediante la unión de grandes colecciones


Estoy tratando de vincular una gran colección a un ComboBox y me enfrenté a problemas de rendimiento al abrir la ventana emergente de ComboBox. Busqué en Internet y descubrí que usar VirtualizingStackPanel como una plantilla de panel de elementos podría ayudar, pero solo ayudó parcialmente. Si ato una colección grande a un ComboBox, podría abrir popup muy rápidamente, eso está bien, pero si después de eso ato otra colección a un ComboBox y trato de abrir popup de nuevo, se vuelve muy lento. Lo mismo está sucediendo si abre una ventana emergente para un vacía el ComboBox, luego enlaza una colección grande e intenta abrir la ventana emergente de nuevo-toma algunos segundos antes de que se abra la ventana emergente.

Aquí está el XAML:

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

Y el código de ejemplo para la unión para reproducir el problema:

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

Traté de hacer que el panel de pila virtualizado se viera así:

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

Pero no ayuda, parece que VirtualizationMode se ignora por lo que popup se abre muy rápido solo la primera vez y luego, cada vez después de los cambios de enlace, es muy lento.

UPDATE: Pensé en no enlazar una nueva colección cada vez, sino enlazar una ObservableCollection una vez y luego simplemente cambiar su contenido. Lo mismo, tan pronto como el contenido de la colección cambia, abrir una ventana emergente todavía toma varios segundos : (

Author: Alexey, 2011-11-20

3 answers

Según este blog: http://vbcity.com/blogs/xtab/archive/2009/12/15/wpf-using-a-virtualizingstackpanel-to-improve-combobox-performance.aspx

Lo he probado con este código:

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

Funciona bien para la primera vez y las próximas veces. No es necesario codificar estas líneas:

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

Espero que esto te ayude.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-19 14:30:24

También tuve el problema con el rendimiento lento. Pero había creado una clase que heredó formulario Combobox, por lo tanto me gustaría hacer esto programáticamente. Así que aquí está esa solución para otros googlers por ahí.

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-20 07:48:05

Acabo de encontrarme con este asunto también. Estoy usando este código en un cuadro combinado personalizado con una plantilla de estilo. Cuando ejecuté mi código en modo de depuración VS, la virtualización no funcionó correctamente. Una vez que lo ejecuté fuera de la depuración, puedo cambiar el contenido de ObservableCollection sin bloquear la interfaz de usuario. También podría ayudar si establece una altura máxima y una anchura máxima.

<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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-11 10:34:17