2016-01-19 15 views
9

Ho un datagrid personalizzato la cui cella è designato come di seguitoprestazioni mentre LayoutTransform viene applicata ai contenuti DataGridCell

<Style x:Key="CellStyleBase" 
      TargetType="{x:Type DataGridCell}"> 
     <Setter Property="Visibility" 
       Value="Visible" /> 
     <Setter Property="Background" 
       Value="{Binding RelativeSource={RelativeSource Self}, Path=Column.Header.CellBackground}" /> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type DataGridCell}"> 
        <Grid x:Name="BackgroundGrid" 
          Background="{TemplateBinding Background}"> 
         <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Content.Text}" 
            HorizontalAlignment="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Column.Header.CellHorzontalAlignment}" 
            VerticalAlignment="Center" 
            FontWeight="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Column.Header.CellFontWeight}" 
            Margin="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Content.Margin}" 
            Padding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Content.Padding}" /> 
         <Grid.LayoutTransform> 
          <TransformGroup> 
           <RotateTransform Angle="-90" /> 
          </TransformGroup> 
         </Grid.LayoutTransform> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

il DataGrid è in stile, come di seguito

<Style TargetType="{x:Type local:CustomDataGrid}"> 
     <Setter Property="BorderThickness" 
       Value="1" /> 
     <!-- This is needed to force DG to have a non-default value. Otherwise the DGR.DetailsVisibility cannot have a value of VisibleWhenSelected by default. --> 
     <Setter Property="RowDetailsVisibilityMode" 
       Value="VisibleWhenSelected" /> 
     <Setter Property="ScrollViewer.CanContentScroll" 
       Value="true" /> 
     <Setter Property="VirtualizingPanel.IsVirtualizing" 
       Value="True" /> 
     <Setter Property="VirtualizingPanel.VirtualizationMode" 
       Value="Recycling" /> 
     <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" 
       Value="True" /> 
     <Setter Property="EnableColumnVirtualization" 
       Value="True" /> 
     <Setter Property="EnableRowVirtualization" 
       Value="True" /> 
     <Setter Property="LayoutTransform"> 
      <Setter.Value> 
       <TransformGroup> 
        <RotateTransform Angle="90" /> 
       </TransformGroup> 
      </Setter.Value> 
     </Setter> 
     <Setter Property="CellStyle" 
       Value="{StaticResource CellStyleBase}" /> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type local:CustomDataGrid}"> 
        <Border Background="{TemplateBinding Background}" 
          BorderBrush="{TemplateBinding BorderBrush}" 
          BorderThickness="{TemplateBinding BorderThickness}" 
          SnapsToDevicePixels="True" 
          Padding="{TemplateBinding Padding}"> 
         <ScrollViewer Focusable="false" 
             Name="DG_ScrollViewer"> 
          <ScrollViewer.Template> 
           <ControlTemplate TargetType="{x:Type ScrollViewer}"> 
            <Grid> 
             <Grid.RowDefinitions> 
              <RowDefinition Height="Auto" /> 
              <RowDefinition Height="Auto" /> 
              <RowDefinition Height="*" /> 
              <RowDefinition Height="Auto" /> 
             </Grid.RowDefinitions> 
             <Grid.ColumnDefinitions> 
              <ColumnDefinition Width="Auto" /> 
              <ColumnDefinition Width="*" /> 
              <ColumnDefinition Width="Auto" /> 
             </Grid.ColumnDefinitions> 

             <!--Left Column Header Corner --> 
             <Border BorderBrush="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:CustomDataGrid}}, Path=HeaderBorderBrush}" 
               BorderThickness="0,0,1,0" 
               Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:CustomDataGrid}}, Path=HeaderBackground}" 
               Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=CellsPanelHorizontalOffset}" 
               Visibility="Collapsed" /> 
             <!--Column Headers--> 
             <DataGridColumnHeadersPresenter Grid.Column="1" 
                     Name="PART_ColumnHeadersPresenter" 
                     Visibility="Visible"> 
              <DataGridColumnHeadersPresenter.Style> 
               <Style TargetType="{x:Type DataGridColumnHeadersPresenter}"> 
                <Setter Property="Template"> 
                 <Setter.Value> 
                  <ControlTemplate TargetType="{x:Type DataGridColumnHeadersPresenter}"> 
                   <Border Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:CustomDataGrid}}, Path=NameHeaderBackground}"> 
                    <ItemsPresenter /> 
                   </Border> 
                  </ControlTemplate> 
                 </Setter.Value> 
                </Setter> 
               </Style> 
              </DataGridColumnHeadersPresenter.Style> 
             </DataGridColumnHeadersPresenter> 

             <!--Column Header Splitter--> 
             <GridSplitter Grid.Row="1" 
                 Grid.Column="0" 
                 Grid.ColumnSpan="2" 
                 Height="4" 
                 HorizontalAlignment="Stretch" 
                 Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:CustomDataGrid}}, Path=NameHeaderBackground}" 
                 Foreground="Transparent" 
                 Cursor="SizeWE" /> 

             <!-- Line separates the column header with the content--> 
             <Canvas Grid.Row="1" 
               Grid.Column="0" 
               Grid.ColumnSpan="2" 
               Height="1.5" 
               HorizontalAlignment="Stretch" 
               VerticalAlignment="Bottom" 
               Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:CustomDataGrid}}, Path=HorizontalGridLinesBrush}" /> 


             <!--DataGrid content--> 
             <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" 
                   Grid.Row="2" 
                   Grid.ColumnSpan="2" 
                   CanContentScroll="{TemplateBinding CanContentScroll}" /> 

             <ScrollBar Grid.Row="0" 
                Grid.RowSpan="3" 
                Grid.Column="2" 
                Name="PART_VerticalScrollBar" 
                Orientation="Vertical" 
                Maximum="{TemplateBinding ScrollableHeight}" 
                ViewportSize="{TemplateBinding ViewportHeight}" 
                Value="{Binding Path=VerticalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" 
                Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" 
                Style="{StaticResource ScrollBarStyle}" /> 

             <Grid Grid.Row="3" 
               Grid.Column="1"> 
              <Grid.ColumnDefinitions> 
               <ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=NonFrozenColumnsViewportHorizontalOffset}" /> 
               <ColumnDefinition Width="*" /> 
              </Grid.ColumnDefinitions> 
              <ScrollBar Grid.Column="1" 
                 Name="PART_HorizontalScrollBar" 
                 Orientation="Horizontal" 
                 Maximum="{TemplateBinding ScrollableWidth}" 
                 ViewportSize="{TemplateBinding ViewportWidth}" 
                 Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" 
                 Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" 
                 Style="{StaticResource ScrollBarStyle}" /> 
             </Grid> 
            </Grid> 
           </ControlTemplate> 
          </ScrollViewer.Template> 
          <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 
         </ScrollViewer> 
        </Border> 
        <ControlTemplate.Triggers> 
         <Trigger SourceName="DG_ScrollViewer" 
           Property="ComputedVerticalScrollBarVisibility" 
           Value="Visible"> 
          <Setter Property="IsShowingHorizontalScrollBar" 
            Value="True" /> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

in DataGrid, le righe saranno aggiunto dinamicamente utilizzando un thread in background e può contenere migliaia di dati. C'è un problema di prestazioni con il datagrid. L'utilizzo della CPU continua ad aumentare.

Ho scoperto che il motivo è LayoutTransform. Se imposto lodello DataGridCell o Width dello Grid, ovvero il contenuto della cella, l'utilizzo della CPU verrà ridotto. Ma non posso hardcode lo stesso. La larghezza deve essere impostata in base alla lunghezza del contenuto.

Ambito altezza hardcoded:

<Setter Property="Height" 
      Value="50" /> 

Ambito larghezza hardcoded:

<Grid x:Name="BackgroundGrid" 
    Background="{TemplateBinding Background}" 
    Width="50"> 
    <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Content.Text}" 
     HorizontalAlignment="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Column.Header.CellHorzontalAlignment}" 
     VerticalAlignment="Center" 
     FontWeight="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Column.Header.CellFontWeight}" 
     Margin="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Content.Margin}" 
     Padding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Content.Padding}" /> 
    <Grid.LayoutTransform> 
     <TransformGroup> 
      <RotateTransform Angle="-90" /> 
     </TransformGroup> 
    </Grid.LayoutTransform> 
</Grid> 

Innanzitutto, ho provato associazione di un convertitore a cui viene fatto passare contenuti e la larghezza viene calcolato e restituito Width proprietà di Grid. Ciò provoca uno sfarfallio mentre vengono aggiunti nuovi dati e l'utilizzo della CPU aumenta.

<Grid x:Name="BackgroundGrid" 
    Background="{TemplateBinding Background}" 
    Width="{Binding Path=Content.Text,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Converter={StaticResource WidthConverter}}"> 
    <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Content.Text}" 
     HorizontalAlignment="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Column.Header.CellHorzontalAlignment}" 
     VerticalAlignment="Center" 
     FontWeight="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Column.Header.CellFontWeight}" 
     Margin="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Content.Margin}" 
     Padding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}},Path=Content.Padding}" /> 
    <Grid.LayoutTransform> 
     <TransformGroup> 
      <RotateTransform Angle="-90" /> 
     </TransformGroup> 
    </Grid.LayoutTransform> 
</Grid> 

In secondo luogo, ho sostituito con LayoutTransformRenderTransform. La larghezza della cella non aumenterà in base al contenuto, il che comporterà la visualizzazione di parte dei dati.

In terzo luogo, ho provato a legare una proprietà a Height di DataGridCell che viene aggiornata dinamicamente con la larghezza massima del valore nello DataGridCell. Questo sta consumando anche l'utilizzo della CPU.

Esistono altre alternative per ottenere il risultato di LayoutTransform diverso da RenderTransform?

In attesa di qualsiasi tipo di input/suggerimenti. Grazie.

+0

Sta ottenendo il testo della cella a 90 gradi tutto quello che stai cercando di fare qui? In tal caso, perché non applicare una trasformazione all'intera griglia invece di ogni singola cella? –

+0

@ Chris W: Apprezzo la tua risposta. Se guardi lo stile del datagrid, puoi vedere che anche questo è stato trasformato. Il requisito può essere raggiunto solo se trasformo sia datagrid che cella. – Subru

+1

Il motivo per cui LayoutTransform causa una CPU elevata dipende dal fatto che qualsiasi modifica nel layout richiede un intero passaggio di layout: tutte le celle dovranno ricalcolare la larghezza e l'altezza. Se si corregge la larghezza/altezza in base a una dimensione specifica, è necessario un calcolo inferiore (non è necessario misurare il contenuto, ecc.). L'impelementazione di DataGrid è mega-lenta rispetto al passaggio di layout.RenderTransform renderà semplicemente i pixel in modo diverso, senza modifiche del layout coinvolte, quindi le prestazioni migliori. Per quanto riguarda la tua domanda reale - come ottenere in alternativa lo stesso risultato - che non conosco ... – Marko

risposta

0

Proverei a fare in modo che la trasformazione avvenga nella logica di rendering stessa. Non l'ho provato da solo, ma penso che valga la pena di vedere se questo darebbe prestazioni simili all'utilizzo di RenderTransform e allo stesso tempo di darti il ​​risultato che stai cercando se usi RotatedText al posto del tuo TextBlock con il LayoutTransform:

public class RotatedText : FrameworkElement 
{ 
    public string Text { get; set; } 

    protected override void OnRender(DrawingContext drawingContext) 
    { 
     base.OnRender(drawingContext); 

     var ft = new FormattedText(Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Calibri"), 12, Brushes.Black); 

     drawingContext.PushTransform(new RotateTransform(-90, 0, ft.Width)); 
     drawingContext.DrawText(ft, new Point(0, ft.Width)); 
     drawingContext.Pop(); 

     Width = ft.Height; 
     Height = ft.Width; 
    } 
} 
Problemi correlati