Reputation: 1897
I have a WPF application built using MVVM; one of the Views contains a collection of models that can be between 200-500 in length, each of the models are mapped to a RepositoryViewModel and bound to the 'Repository.xaml' view in a stack panel.
The top level View (Main.xaml) is as follows:
<Window.Resources>
<DataTemplate DataType="{x:Type home:RepositoryViewModel}">
<vw:Repository />
</DataTemplate>
<Window.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Margin="5 40 5 5">
<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True">
<ItemsControl ItemsSource="{Binding Repositories}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</ScrollViewer>
Repository.xaml UserControl is as follows:
<Grid Margin="5" Visibility="{Binding Model.Visibility}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition SharedSizeGroup="WrapPanelGroup" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1">
<!--Textbox is used to allow user to select the text. Changing to Label does not help with rendering issues-->
<TextBox Background="Transparent" BorderThickness="0" Text="{Binding Model.Name}" IsReadOnly="True"
TextWrapping="Wrap" FontSize="18" MaxWidth="300" />
<TextBox Background="Transparent" BorderThickness="0" Text="{Binding Model.Url}" IsReadOnly="True"
TextWrapping="Wrap" FontSize="8" MaxWidth="300" Foreground="DarkGray" />
</StackPanel>
<Button Grid.Column="2" Content="Checkout" Command="{Binding CheckoutCommand}" Visibility="{Binding Model.SingleCheckoutVisible}"/>
<CheckBox Grid.Column="2" IsChecked="{Binding Model.IsChecked}" Visibility="{Binding Model.BulkCheckoutVisible}"/>
</Grid>
The above works perfectly as I require, the issue is the time WPF takes to render the controls- once each of the RepositoryViewModel
's are added to the RepositoryViewModel
ObservableCollection
the entire UI freezes for 3-5 seconds whilst the controls are rendered.
Whilst trying to isolate the issue I noticed that by removing the textbox's the render time dramatically decreases but removing the binding on the textbox's does not make a noticeable difference. Swapping the textbox's for labels made little difference.
Is the collection size simply to large to expect WPF to handle quickly or am I missing something that is increasing the render time? I did consider having a SharedSizeGroup
with a MaxWidth may be the culprit but removing did not improve performance.
Thanks.
Upvotes: 1
Views: 616
Reputation: 1118
Look into adding virtualization to your ItemsControl. This way it only renders the items in view rather than all of them.
<ItemsControl VirtualizingStackPanel.IsVirtualizing="True"
ScrollViewer.CanContentScroll="True">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
I believe you'd also need to remove the ItemsControl from the StackPanel and ScrollViewer, as they'll give the ItemsControl infinite space to render, and render the virtualization useless.
I see you're using a WrapPanel for your ItemsPanelTemplate, so you may need to roll your own virtualized panel, or check out some other controls (haven't used these myself).
Upvotes: 3