2016-01-19 16 views
9

Tôi có một DataGrid tùy chỉnh mà tế bào được theo kiểu như sauPerformance vấn đề trong khi LayoutTransform được áp dụng cho nội dung 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> 

Các DataGrid được theo kiểu như sau

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

Trong DataGrid, hàng sẽ được được thêm động bằng cách sử dụng chuỗi nền và có thể chứa hàng nghìn dữ liệu. Có một vấn đề hiệu suất với DataGrid. Việc sử dụng CPU tiếp tục tăng lên.

Tôi phát hiện ra lý do là LayoutTransform. Nếu tôi đặt Height của DataGridCell hoặc Width của Grid là nội dung của ô, việc sử dụng CPU sẽ bị giảm. Nhưng tôi không thể mã hóa như cũ. Chiều rộng phải được đặt dựa trên độ dài của nội dung.

Thiết chiều cao hardcoded:

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

Thiết rộng 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> 

Trước tiên, tôi đã cố gắng ràng buộc một chuyển đổi mà nội dung được thông qua và chiều rộng được tính toán và trở lại Width tài sản của Grid. Điều này gây ra một nhấp nháy trong khi dữ liệu mới được thêm vào và việc sử dụng CPU sẽ được tăng lên.

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

Thứ hai, tôi thay thế LayoutTransform bằng RenderTransform. Chiều rộng của ô sẽ không tăng dựa trên nội dung sẽ dẫn đến chỉ hiển thị một phần dữ liệu.

Thứ ba, tôi đã thử ràng buộc thuộc tính là Height của DataGridCell được cập nhật động với độ rộng cao nhất của giá trị trong DataGridCell. Điều này cũng tiêu thụ việc sử dụng CPU.

Có phương án nào khác để đạt được kết quả của LayoutTransform ngoài RenderTransform không?

Mong mọi loại đầu vào/đề xuất. Cảm ơn.

+0

Nhận văn bản ô ở mức 90deg tất cả những gì bạn đang cố gắng làm ở đây phải không? Nếu vậy, tại sao không áp dụng một biến đổi cho toàn bộ lưới thay vì mỗi ô riêng lẻ? –

+0

@ Chris W: Đánh giá cao phản hồi của bạn. Nếu bạn nhìn vào phong cách của DataGrid, bạn có thể thấy rằng nó được biến đổi. Yêu cầu có thể đạt được chỉ khi tôi chuyển đổi cả dữ liệu và ô. – Subru

+1

Lý do tại sao LayoutTransform gây ra CPU cao là do bất kỳ thay đổi nào trong bố cục đều yêu cầu toàn bộ bố cục vượt qua - tất cả các ô sẽ phải tính toán lại chiều rộng và chiều cao của chúng. Nếu bạn sửa chiều rộng/chiều cao thành một kích thước cụ thể, thì có ít tính toán hơn (không phải đo nội dung, v.v.). DataGrid impelementation là mega chậm liên quan đến việc bố trí vượt qua.RenderTransform sẽ chỉ hiển thị các pixel khác nhau, không có thay đổi bố cục nào có liên quan, do đó hiệu suất tốt hơn. Đối với câu hỏi thực tế của bạn - làm cách nào để đạt được kết quả tương tự - mà tôi không biết ... – Marko

Trả lời

0

Tôi sẽ thử thực hiện biến đổi xảy ra trong chính logic kết xuất. Tôi đã không cố gắng này bản thân mình nhưng tôi nghĩ rằng nó là giá trị một shot để xem nếu điều này sẽ cho hiệu suất tương tự để sử dụng RenderTransform trong khi cũng cho bạn kết quả mà bạn đang tìm kiếm nếu bạn sử dụng RotatedText thay cho TextBlock của bạn với 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; 
    } 
} 
Các vấn đề liên quan