8

私はデータグリッドにこのスタイルを持っています:

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

データ グリッドに大量のデータをロードすると、パフォーマンスが低下することはわかっています。仮想化を使用してパフォーマンスへの影響を軽減することはできますが、カスタム スクロール ビューアでグリッドをスローするとすぐに、仮想化が失われます。

私はそれを取り戻そうとしていますが、方法がわかりません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>

Canvasと をGrid取り出し、 だけを残すとすぐに、ItemsPresenter再び高速になります。どうすればそれを速く取得し、これを保持できCanvasますか?

更新 2:この ( DataGrid を使用した ScrollViewer の遅いパフォーマンス) 戦略を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が描画され、それを小さなパーツに分割するロジックがありません。行の仮想化を維持できる限り、画像全体をレンダリングしてもまったく問題ありません。

4

2 に答える 2

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>

于 2012-06-30T00:06:11.143 に答える
1

問題は、スクロールビューアのコンテンツが IScrollInfo / VirtualizingPanel をサポートしている場合にのみ仮想化が機能することです。

私が見る限り、アイテムの下に何かがあるキャンバスを持ちたいと思っています-すべてスクロール領域内にあります。それは実際にあなたが望む特別な種類の行ですか?もしそうなら、そのようにして、代わりに特別な行を挿入できますか? または、それをデータグリッドの外に移動することもできます-またはRowDetailsを使用してみてください-それは私が知っているのと同じ外観ではありません-しかし、はるかに使いやすいです。

持っているもので仮想化を機能させるには、キャンバスが仮想化パネル内にある必要があります。

于 2012-06-27T09:21:05.473 に答える