-2

We wrote a new project using WPF, but after the first few tests I noticed poor performance of ComboBox elements when there are thousands of objects in their datasource. I solved using:

<ComboBox.ItemsPanel>   
    <ItemsPanelTemplate>
        <VirtualizingStackPanel />  
    </ItemsPanelTemplate>
</ComboBox.ItemsPanel>

I was wondering if the StackPanel control will be prone to this kind of problem with a few hundred custom elements (UserControl with only one label and two buttons). UserControl(s) are added in code in this way in two/tree places in the app:

foreach (var obj in myList)
{
    MyUserControl muc = new MyUserControl(obj);
    myStackPanel.Add(muc);
}

Can anyone tell me if we will run into problems and/or if there is a way to tell the StackPanel to reuse cached objects?

Mike97
  • 596
  • 5
  • 20
  • 1
    You already ran into problems. To get a definitive answer to your question I suggest that you test it yourself. Even if somebody had an opinion about what is possible it might not apply to your case anyway. – Martin Liversage Nov 15 '21 at 19:28
  • @MartinLiversage yes I know, but at home I don't even had a pc.. Just a M1 Mac.. – Mike97 Nov 15 '21 at 19:33

1 Answers1

1

I assume when you talk about displaying "a few hundred custom elements" in a StackPanel you want to add scroll bars in order to make all elements fit the sceen.

The general problem is that rendering many items (or their containers) at once will impact the rendering performance as one can expect. You already ran into this issue with your ComboBox.

What you want is to only create containers for the visible items and not for all the hundreds or thousands items. This is called UI virtualization. The core of UI virtualization is a ScrollViewer and a VirtualizingStackPanel (or VirtualizingPanel in general), where the ScrollViewer defines the visible area and the VirtualizingPanel controls the container generation/recycling based on the scroll input.

You most likely want to replace the StackPanel with a ListBox.
ListBox stacks items vertically and has a ScrollViewer by default (a StackPanel does not). Since the default Panel of the ListBox is VirtualizingStackPanel, it supports UI virtualization (which is enabled by default) and therefore let's you display "unlimited" items without impacting the rendering performance (as long the visual tree of those item containers is not overly complex). Also, try not to add items one by one. This will trigger complete rendering passes, especially for controls that don't support UI virtualization like the StackPanel. Try to add all items at once or at least in batches, which is not possible with the StackPanel. Another reason why it is the wrong host. Optimizing performance: Controls

BionicCode
  • 1
  • 4
  • 28
  • 44
  • you got the point (and I accepted your answer). The StackPanel is already a child of a Scroller. Due to lack of my knoledge of this platform (in macOS I'll never done that with NSTableView objects) I was wondering if this approach which I suffering, is due to some sort of ignorance and it's really hard for me to convince the boss. In the meantime I discover something intresting solution here: https://stackoverflow.com/a/1525874/3123201 – Mike97 Nov 15 '21 at 20:12
  • 1
    The link you have posted is exactly the right way to go. The "normal" WPF approach would be to create a list of data models. If this list is changing dynamically, you would use a ObservableCollection. Then with the help of data binding you would bind this collection of data models to the ListBox (to the ItemsSource property). Then you would define a DataTemplate for the data models. This template could contain a the UserControl that relates to the data models. This way WPF will generate the containers and UserControls for you. The loop in your question would be redundant then. – BionicCode Nov 15 '21 at 20:29
  • [Data binding overview (WPF .NET)](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/?view=netdesktop-6.0), [Data Templating Overview](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/data-templating-overview?view=netframeworkdesktop-4.8). – BionicCode Nov 15 '21 at 20:29
  • 1
    In regards to your posted link: don't use the ItemsControl, but use the ListBox. ListBox extends ItemsControl but adds scroll and UI virtualization support by default. It's more advanced. – BionicCode Nov 15 '21 at 20:31
  • WPF is data driven. You always want to focus on data models and let WPF create UI elements dynamically based on DataTemplates. – BionicCode Nov 15 '21 at 20:33