【问题标题】:Slow performance with WPF DataGrid and ScrollViewerWPF DataGrid 和 ScrollViewer 性能下降
【发布时间】:2012-06-23 01:25:14
【问题描述】:

我有这种风格的数据网格:

<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>

只要我把CanvasGrid 拿出来,只留下ItemsPresenter,然后它又很快了。我怎样才能快速获得它并且仍然保留这个Canvas

更新 2:如何将这个 (ScrollViewer slow perfomance with DataGrid) 策略应用于上面显示的 Grid?我试过这个:

<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 都被绘制出来了,我没有逻辑将它分成更小的部分。完全渲染图像是完全可以的,只要我可以保持行虚拟化。

【问题讨论】:

  • 我不知道 Grid 支持虚拟化。 ¿ 你是如何实现它的?
  • 我的意思是 DataGrid 支持虚拟化。
  • 我记得 DataGrid 中的 ScrollViewer 破坏了 DataGrid 虚拟化,但我找不到它。是只读的吗。如果是这样,试试 GridView - 它会快得多。
  • @Blam 如果我删除多余的Canvas 元素,我对DataGrid 没有任何问题。因此,DataGrid 本身没有问题,实际上即使在这种情况下 ListView 也很慢。
  • @Blam 显然,滚动查看器会导致虚拟化问题,因为它要求孩子占据全高,以便查看器可以测量其大小并相应地显示滚动条,但只要孩子(数据网格) 高度化,虚拟化消失了。

标签: c# .net wpf performance


【解决方案1】:

问题是虚拟化只有在滚动查看器的内容支持 IScrollInfo / VirtualizingPanel 时才有效。

据我所知,您希望您的项目带有画布,其下方有一些东西 - 全部在您的滚动区域内。它实际上是你想要的一种特殊的行吗?如果是这样,您可以那样做并插入一个特殊的行吗? 或者您可以将其移到数据网格之外 - 或尝试使用 RowDetails - 这与我所知道的外观不同 - 但更容易使用。

要让虚拟化与您的画布一起工作,您的画布必须位于虚拟化面板中。

【讨论】:

    【解决方案2】:

    我已经为基于 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>
    

    【讨论】:

      猜你喜欢
      • 2011-11-07
      • 1970-01-01
      • 2014-10-05
      • 1970-01-01
      • 2013-11-24
      • 1970-01-01
      • 2018-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多