Slow performance with WPF DataGrid and ScrollViewer

I have this style for a data grid:

<Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type DataGrid}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True"> <ScrollViewer x:Name="DG_ScrollViewer" Focusable="false"> <ScrollViewer.Template> <ControlTemplate TargetType="{x:Type ScrollViewer}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/> <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" Grid.Row="1" /> <ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="2" Maximum="{TemplateBinding ScrollableHeight}" Orientation="Vertical" Grid.Row="1" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/> <Grid Grid.Column="1" Grid.Row="2"> <Grid.ColumnDefinitions> <ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Column="1" Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/> </Grid> </Grid> </ControlTemplate> </ScrollViewer.Template> <Grid> <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Grid.Row="0" /> <Canvas Width="128" VerticalAlignment="Stretch" HorizontalAlignment="Left" Grid.Row="0" x:Name="Image" /> </Grid> </ScrollViewer> </Border> </ControlTemplate> </Setter.Value> </Setter> 

I know that if you load a large amount of data into a data grid, performance suffers. However, I can use virtualization to reduce this performance improvement, as soon as I drop the grid in the user scroll viewer, virtualization is lost.

I am trying to return it, but I do not know how to do this by storing an element named Image in my XAML.

Basically, I want to have a scrolling image with the contents of the data grid, and the above code works fine, I just don’t know how to enable virtualization. Is it possible?

Update: Looks like I found a problem. The last Grid in the template causes a problem:

 <Grid> <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Grid.Row="0" /> <Canvas Width="128" VerticalAlignment="Stretch" HorizontalAlignment="Left" Grid.Row="0" x:Name="Image" /> </Grid> 

As soon as I select Canvas and Grid , leaving only ItemsPresenter , then it will start again. How can I get it fast and save this Canvas ?

Update 2:. How can I apply this ( ScrollViewer slow work with DataGrid ) to my Grid shown above? I tried this:

 <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Rectangle Name="sizingElement" Grid.Row="0" Fill="Transparent" Margin="1"/> <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Grid.Row="0" Height="{Binding ElementName=sizingElement, Path=ActualHeight, FallbackValue=1}" /> <Canvas Width="128" VerticalAlignment="Stretch" HorizontalAlignment="Left" Grid.Row="0" x:Name="Image" /> </Grid> 

However, now have the scroll bars disappeared?

I understand that I can not virtualize Canvas , and I do not need it. In fact, all of the Canvas text is drawn, and I don’t have the logic to split it into smaller parts. It is quite normal to make the image complete while I can support string virtualization.

+7
source share
2 answers

My virtualization works for my custom TreeView-based control (.Net 4.0). I changed the style a bit to fit the DataGrid, hope it works for your case:

  <Style TargetType="{x:Type DataGrid}"> <Setter Property="OverridesDefaultStyle" Value="True" /> <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True" /> <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling" /> <Setter Property="BorderThickness" Value="1" /> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <VirtualizingStackPanel IsItemsHost="True" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" /> </ItemsPanelTemplate> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type DataGrid}"> <Border x:Name="Border" Grid.Column="0" Background="{TemplateBinding Background}" BorderBrush="{StaticResource SolidBorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"> <DockPanel> <ScrollViewer x:Name="PART_Body_Scroll" Background="White" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True"> <ItemsPresenter x:Name="ItemsHost" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" /> </ScrollViewer> </DockPanel> </Border> </ControlTemplate> </Setter.Value> </Setter> 

+2
source

the problem is that virtualization only works if the contents of scrollviewer supports IScrollInfo / VirtualizingPanel.

As far as I can see, you want your stuff with a canvas with something below it - all inside your scroll pane. Is this really the special kind of string you want? If so, can you go there and insert a special line instead? Or you can just push this outside the datagrid - or try using RowDetails - this is not the same as I know, but it is much easier to use.

For virtualization to work with what you have, your canvas must be inside the virtualization panel.

+1
source

All Articles