使用WPF DataGrid和ScrollViewer降低性能

Tow*_*wer 8 .net c# wpf performance

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

<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>
Run Code Online (Sandbox Code Playgroud)

我知道如果你在数据网格上加载大量数据,性能会受到影响.我可以使用虚拟化来减轻性能损失,但是,只要我在自定义滚动查看器中抛出网格,虚拟化就会丢失.

我试图让它回来,但我不确定如何 - 同时仍然保留Image我的XAML中命名的元素.

基本上,我想让图像滚动数据网格内容,上面的代码工作正常,只是我不知道如何启用虚拟化.它甚至可能吗?

更新:看起来我发现了一个问题.Grid模板中的最后一个导致问题:

<Grid>
    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                    Grid.Row="0" />

    <Canvas Width="128"
            VerticalAlignment="Stretch"
            HorizontalAlignment="Left"
            Grid.Row="0"
            x:Name="Image" />
</Grid>
Run Code Online (Sandbox Code Playgroud)

当我走CanvasGrid了,只有留下ItemsPresenter,那么它再快的.我怎样才能快速得到它并仍然保留它Canvas

更新2:我如何应用这个(ScrollViewer缓慢性能与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>
Run Code Online (Sandbox Code Playgroud)

但是,现在滚动条已经消失了?

我意识到我无法虚拟化Canvas,而且我不需要.实际上,整体Canvas都被吸引了,我没有把它分成更小部分的逻辑.只要我可以保持行虚拟化,完全渲染图像就完全没问题了.

Run*_*sen 1

问题是虚拟化仅在滚动查看器的内容支持 IScrollInfo / VirtualizingPanel 时才起作用。

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

为了使虚拟化能够与您拥有的画布一起工作,您的画布必须位于虚拟化面板内。