2012-06-20 17 views
7

ho questo stile per una griglia di dati:Rallentamento delle prestazioni con WPF DataGrid e 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> 

so che se si carica un sacco di dati su una griglia di dati, le prestazioni soffre. Posso utilizzare la virtualizzazione per mitigare quel risultato di prestazioni, tuttavia, non appena lancio la griglia in un visualizzatore di scorrimento personalizzato, la virtualizzazione viene persa.

Sto cercando di recuperarlo, ma non sono sicuro di come, pur mantenendo l'elemento denominato Image nel mio XAML.

Fondamentalmente, voglio uno scorrimento dell'immagine con il contenuto della griglia di dati e il codice sopra funziona perfettamente, è solo che non so come abilitare la virtualizzazione. È possibile?

Aggiornamento: Sembra che ho trovato un problema. L'ultima Grid nel modello provoca un problema:

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

    <Canvas Width="128" 
      VerticalAlignment="Stretch" 
      HorizontalAlignment="Left" 
      Grid.Row="0" 
      x:Name="Image" /> 
</Grid> 

Appena prendo la fuori Canvas e Grid, lasciando solo il ItemsPresenter, allora è di nuovo veloce. Come posso farlo velocemente e mantenere questo Canvas?

Aggiornamento 2: Come posso applicare questo (ScrollViewer slow perfomance with DataGrid) strategia per la mia Grid mostrato in precedenza? Ho provato questo:

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

Tuttavia, ora le barre di scorrimento sono scomparsi?

Mi rendo conto che non è possibile virtualizzare uno Canvas e non è necessario. Infatti, l'intero Canvas viene disegnato e non ho alcuna logica per separarlo in parti più piccole. È assolutamente perfetto per rendere l'immagine nella sua interezza, purché possa mantenere la virtualizzazione delle righe.

+0

Non ero a conoscenza Griglia supporta la virtualizzazione. Come lo stai implementando? – NestorArturo

+0

Intendevo che DataGrid supporta la virtualizzazione. – Tower

+1

Ricordo qualcosa su ScrollViewer in DataGrid che rompe la virtualizzazione di DataGrid ma non riesco a trovarlo. È solo una lettura. Se è così, prova GridView - è molto più veloce. – Paparazzi

risposta

1

il problema è che la virtualizzazione funziona solo se il contenuto dello scrollviewer supporta IScrollInfo/VirtualizingPanel.

Per quanto posso vedere, vuoi avere i tuoi oggetti con una tela con qualcosa sotto di esso - tutto all'interno dell'area di scorrimento. In realtà è un tipo speciale di riga che vuoi? Se è così potresti andare in quel modo e inserire invece una fila speciale? Oppure puoi spostarlo al di fuori del datagrid - o provare a usare RowDetails - non è la stessa apparenza che conosco - ma è molto più facile da usare.

Per fare in modo che la virtualizzazione funzioni con quello che deve avere la tela nel pannello di virtualizzazione.

2

Ho la virtualizzazione che funziona per il controllo personalizzato basato su TreeView (.Net 4.0). Ho modificato un po 'lo stile per abbinare DataGrid, spero che sta andando a lavorare per il vostro caso:

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