I've been listing a relatively large number of items in a ListView (8000+) and it is great in terms of performance, fills in less than a second.
I've tried the same with a ListBox and it takes a lot more time. Even if I set the ItemsPanelTemplate to a VirtualStackPanel.
I'm using a (not default) DataTemplate for the items.
I'm very happy to continue to use a ListView instead of a ListBox, I'm just curious about the difference in performance.
Does anyone know why there's such a big difference? What am I missing?
===
ListBox already uses a VirtualizingStackPanel by default.
What do the items look like?
Are you using the same DataTemplate in the ListView?
Could you show us the DataTemplate?
==
The DataTemplate is this:
<ListView.ItemTemplate> <DataTemplate> <Grid Margin="0" Background="White"> <Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue" CornerRadius="4" Background="{Binding Path=Background, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}"> <Grid Margin="3"> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition Width="70"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Path=OutrosNomes}"></TextBlock> <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="0"> <TextBlock Margin="0,5,0,5" FontWeight="Bold" Text="BI: "></TextBlock> <TextBlock Margin="0,5,0,5" Text="{Binding Path=N_BI,Converter={StaticResource NumeroDefinidoConverter}}"></TextBlock> <TextBlock Margin="0,5,0,5" FontWeight="Bold" Text=" NIF: "></TextBlock> <TextBlock Margin="0,5,0,5" Text="{Binding Path=NIF,Converter={StaticResource NumeroDefinidoConverter}}"></TextBlock> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Column="1" Grid.RowSpan="2" VerticalAlignment="Center"> <StackPanel.Style> <Style> <Style.Triggers> <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}}" Value="False"> <Setter Property="StackPanel.Visibility" Value="Collapsed" /> </DataTrigger> </Style.Triggers> </Style> </StackPanel.Style> <Button Grid.Column="0" Tag="{Binding .}" Width="20" Margin="5,0,0,0" ToolTip="Seleccionar" Click="SeleccionarButton_Click"> <Image Width="15" Height="15" Source="/UI/Imagens/CheckIcon.png" /> </Button> </StackPanel> </Grid> </Border> </Grid> </DataTemplate> </ListView.ItemTemplate>
I'm also using the following "style" that changes the default ControlTemplate for the ListBox:
<Style TargetType="{x:Type ListBox}"> <Setter Property="SnapsToDevicePixels" Value="true" /> <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" /> <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" /> <Setter Property="ScrollViewer.CanContentScroll" Value="True" /> <Setter Property="HorizontalContentAlignment" Value="Stretch" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="FontFamily" Value="Trebuchet MS" /> <Setter Property="FontSize" Value="12" /> <Setter Property="BorderBrush" Value="{DynamicResource ControlBorderBrush}" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="Padding" Value="1" /> <Setter Property="IsTabStop" Value="False" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBox}"> <Grid> <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1" Background="{DynamicResource ControlBackgroundBrush}"> <ScrollViewer Margin="1" Focusable="false" Foreground="{TemplateBinding Foreground}"> <StackPanel Margin="2" IsItemsHost="true" /> </ScrollViewer> </Border> <Border x:Name="DisabledVisualElement" I****TestVisible="false" Background="#A5FFFFFF" BorderBrush="#66FFFFFF" BorderThickness="1" Opacity="0" /> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Opacity" TargetName="DisabledVisualElement" Value="1" /> </Trigger> <Trigger Property="IsGrouping" Value="true"> <Setter Property="ScrollViewer.CanContentScroll" Value="false" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
Is there something in that Style that makes the VirtualizingStackPanel not work as expected?
===
Yeah, the censoring stuff on this forum is a bit naive.
First thing I notice is that in your Style for re-templating the ListBox, you have a normal StackPanel inside the ScrollViewer rather than a VirtualizingStackPanel. They're different classes. Switching that out might help you.
So instead of this...
<StackPanel Margin="2" IsItemsHost="true" />
You need this...
<VirtualizingStackPanel Margin="2" IsItemsHost="true" />
Let's see if that works.
==
Sorry for the late reply, I was on vacations :P
That was it, thanks!
I didn't expect that it was a problem with the template because, even when I set the ListBox.ItemsPanel's ItemsPanelTemplate as a VirtualizingStackPanel it didn't improve performance.
Probably that happens because the default template uses that property (ItemsPanel) and the overrinding ControlTemplate does not...