C# WPF DataGrid和ScrollViewer的性能较慢
对于数据网格,我有以下样式:C# WPF DataGrid和ScrollViewer的性能较慢,c#,.net,wpf,performance,C#,.net,Wpf,Performance,对于数据网格,我有以下样式: <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type DataGrid}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThick
<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>
只要我把画布
和网格
拿出来,只留下itemsresenter
,它就又快了。我怎样才能快速获得它,并且仍然保留此画布
更新2:如何将此()策略应用于上面显示的网格?我试过这个:
<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
都被画出来了,我没有逻辑把它分成更小的部分。只要我可以保持行虚拟化,就可以完整地渲染图像。问题是,只有当scrollviewer的内容支持IScrollInfo/virtualzingPanel时,虚拟化才起作用
据我所知,你希望你的物品有一个画布,下面有一些东西-所有这些都在你的滚动区域内。这真的是你想要的一种特殊的划船吗?如果是这样,您可以这样做,并插入一个特殊的行代替?
或者你可以把它移到datagrid之外——或者尝试使用RowDetails——我知道它的外观不同——但使用起来更容易
要使虚拟化与您的画布一起工作,您的画布必须位于虚拟化面板内。我已经让虚拟化用于基于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>
我不知道网格支持虚拟化。?您是如何实现的?我是说DataGrid支持虚拟化。我记得DataGrid中的ScrollViewer破坏了DataGrid虚拟化,但我找不到它。它是只读的吗。如果是这样的话,请尝试一下GridView,它会快得多。@bum如果我删除额外的Canvas
元素,我对DataGrid
没有问题。因此,DataGrid
本身并没有问题,事实上,在这种情况下,即使是ListView
也很慢。@显然,滚动查看器会导致虚拟化问题,因为它要求子对象占据全高,以便查看器可以测量其大小并相应地显示滚动条,但只要子对象(数据网格)高度化,虚拟化消失。
<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>