WPF DataGrid和ScrollViewer性能下降
我有一个数据网格的样式:
<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>
我知道,如果你在数据网格上加载大量数据,性能就会受到影响。 我可以使用虚拟化来减轻性能影响,但是,只要我在自定义滚动查看器中抛出网格,虚拟化就会丢失。
我试图恢复它,但我不知道如何 - 虽然仍保留我的XAML中名为Image
的元素。
基本上,我想有一个图像滚动与数据网格内容和上面的代码工作正常,只是我不知道如何启用虚拟化。 它甚至有可能吗?
更新:看起来我发现了一个问题。 模板中的最后一个Grid
会导致问题:
<Grid>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Grid.Row="0" />
<Canvas Width="128"
VerticalAlignment="Stretch"
HorizontalAlignment="Left"
Grid.Row="0"
x:Name="Image" />
</Grid>
只要我把Canvas
和Grid
取出来,只剩下ItemsPresenter
,那么它又快了。 我如何快速获取并保留此Canvas
?
更新2:我如何在上面显示的Grid
中应用此(ScrollViewer与DataGrid的慢速性能)策略? 我试过这个:
<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>
但是,现在滚动条已经消失了?
我意识到我无法虚拟化Canvas
,而且我也不需要。 实际上,整个Canvas
都会被绘制出来,我没有逻辑将它分成更小的部分。 只要我可以保持行虚拟化,渲染图像就完全好了。
我有基于TreeView(.Net 4.0)的自定义控件的虚拟化工作。 我修改了一些与DataGrid匹配的样式,希望它能适用于你的情况:
<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>
问题是只有当scrollviewer的内容支持IScrollInfo / VirtualizingPanel时,虚拟化才有效。
据我所见,你想让你的物品在画布下面有一些东西 - 都在你的滚动区域内。 它实际上是一种特殊的行吗? 如果是这样,你可以这样做,并插入一个特殊的行? 或者你可以在数据网格之外移动它 - 或者尝试使用RowDetails--它与我所知的外观不是一样的 - 但是很容易使用。
要让虚拟化与您的画布一起工作,必须位于虚拟化面板内。
链接地址: http://www.djcxy.com/p/10901.html上一篇: Slow performance with WPF DataGrid and ScrollViewer
下一篇: Class org.datanucleus.api.jdo.PersistenceManagerFactoryClass was not found