프로그램 개발/WPF: Style&Template

DataGrid④

(ㅇㅅㅎ) 2022. 5. 17. 19:30
728x90
반응형

 안녕하세요, 이번 글에서는 지난 [Microsoft Control Style & Template 톺아보기 - DataGrid③]을 이어서 WPF [DataGrid의 스타일 및 템플릿] 예제 중 DataGridRow와 DataGridCell에 사용된 Style을 톺아보도록 하겠습니다.

⭐ [Microsoft Control Style & Template 톺아보기 - DataGrid] 편은 총 4편(DataGrid, Button/DataGridColumnHeadersPresenter, DataGridColumnHeader/DataGridRowHeader, DataGridRow/DataGridCell)으로 구성되어있습니다.

 

[ DataGridRow Style ]

 예제에 사용된 DataGridRow Style은 DataGrid의 Row 부분을 Style로 미리 정의해둔 것입니다.

 

 

DataGridRow 속성

<Style TargetType="{x:Type DataGridRow}">
  <Setter Property="Background">
    <Setter.Value>
      <SolidColorBrush Color="{DynamicResource ControlLightColor}" />
    </Setter.Value>
  </Setter>
  <Setter Property="SnapsToDevicePixels" Value="true" />
  <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
  <Setter Property="ValidationErrorTemplate">
    <Setter.Value>
      <ControlTemplate>
        <TextBlock Foreground="Red" Margin="2,0,0,0" Text="!" VerticalAlignment="Center" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Setter Property="Template">
    <Setter.Value>
      ...
    </Setter.Value>
  </Setter>
</Style>

TargetType

 이 Style을 적용할 형식을 설정합니다. 예제에서는 "{x:Type DataGridColumnHeader}"로 설정했습니다.

 

 

Background

 DataGridRow의 배경색을 설정합니다. 예제에서는 미리 정의한 ControlLightColor로 설정했습니다.

⭐ 사실 이 Background는 예제에서 필요 없는 속성입니다. Template에서 Border를 이용하여 배경색을 지정하고 있기 때문입니다. 만약 여러분이 배경색을 변경하고 싶으시면 Border의 Background 값을 변경하셔야 합니다.

 

 

SnapsToDevicePixels

 렌더링 하는 동안 DataGridRow의 렌더링에 디바이스 관련 픽셀 스냅(PixelSnap)을 사용할지 여부를 설정합니다. 픽셀 스냅을 사용하면 값을 true로 설정하고, 그렇지 않으면 false(기본값)로 설정합니다.

⭐ 픽셀 스냅(Pixel Snap)을 사용하는 이유

더보기

 WPF에서는 시스템 DPI 설정에 맞게 자동으로 크기를 조정하게 됩니다. 이러한 조정을 할 때 가장자리가 흐려지거나 반투명하게 표시되는 문제가 발생하게 됩니다. 이 문제를 해결하기 위해서 픽셀 스냅 기능을 사용하여 객체의 가장자리를 픽셀에 맞추어 고정시키는 기능을 제공합니다. 픽셀 스냅을 사용하면 객체에 작은 단위의 offset을 적용하여 객체의 크기를 장치 픽셀에 맞추거나 일부분을 랜더링 시점에서 제거하여 해결하는 방법입니다.


 

 

Validation.ErrorTemplate

 표시기(Adorner) 계층에서 유효성 검사 오류 피드백을 생성하는 데 사용되는 ControlTemplate를 설정합니다. 예제에서는 ValidationErroTemplate을 사용하여 오류 항목을 설정하기 위해서 "{x:Null}" 값으로 설정했습니다.

 

 

ValidationErrorTemplate

 ValidationError의 ControlTemplate를 설정합니다. 예제에서는 Validation 오류 발생 시 RowHeader 부분에 빨간색 느낌표(!)를 표시합니다.

ValidationErrorTemplate

 

 

Template

<Setter Property="Template">
  <Setter.Value>
    <ControlTemplate TargetType="{x:Type DataGridRow}">
      <Border x:Name="DGR_Border"... >
        <Border.Background>
          ...
        </Border.Background>
        
        <VisualStateManager.VisualStateGroups>
          ...
        </VisualStateManager.VisualStateGroups>

        <SelectiveScrollingGrid>
          ...
          <DataGridCellsPresenter ... />
          <DataGridDetailsPresenter ... />
          <DataGridRowHeader ... />
        </SelectiveScrollingGrid>
      </Border>
    </ControlTemplate>
  </Setter.Value>
</Setter>

 예제에서 사용되는 Template는 Control의 외형을 지정해줄 수 있는 ControlTemplate입니다.

👀 Template에 대해서 좀 더 아시고 싶으신 분은 이 페이지를 참고하시길 바랍니다.

 

 

DataGridRow 구성

 예제의 Template에서 구성한 DataGridRow는 위의 이미지와 같이 Border이 SelectiveScrollingGrid를 감싸는 형태로 구성되어있습니다. 그리고 SelectiveScrollingGrid 안에는 DataGridRowHeader, DataGridCellsPresenter와 DataGridDetailsPresenter가 구성되어있습니다.

 

Border(DGR_Border)

 다른 요소의 주위에 윤곽선, 배경 또는 둘 다를 그립니다.

Border 속성

더보기
<Border x:Name="DGR_Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
  <Border.Background>
    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
      <GradientStop Color="Transparent" Offset="0" />
      <GradientStop Color="{DynamicResource ControlLightColor}" Offset="1" />
    </LinearGradientBrush>
  </Border.Background>
  ...
</Border>

x:Name

 Border에 이름을 붙입니다. 이름을 붙이는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.

 

BorderBrush

 Border의 윤곽선 색을 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 BorderBrush 값으로 설정했습니다.

 

BorderThickness

 Border의 윤곽선 두께를 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 BorderThickness 값으로 설정했습니다.

 

SnapsToDevicePixels

 렌더링 하는 동안 이 Border의 렌더링에 디바이스 관련 픽셀 스냅(Pixel Snap)을 사용할지 여부를 설정합니다. 픽셀 스냅을 사용하면 값을 true로 설정하고, 그렇지 않으면 false(기본값)로 설정합니다.

 

Background

 Border의 배경색을 설정합니다. 예제에서는 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.

 

👀 그라데이션 색에 관해서 궁금하신 분은 이 페이지를 참고하시기 바랍니다.


 

SelectiveScrollingGrid

 View가 Scroll 될 때 지정된 Cell을 보유할 수 있는 Panel입니다.

SelectiveScrollingGrid 속성

더보기
<SelectiveScrollingGrid>
  <SelectiveScrollingGrid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="*" />
  </SelectiveScrollingGrid.ColumnDefinitions>

  <SelectiveScrollingGrid.RowDefinitions>
    <RowDefinition Height="*" />
    <RowDefinition Height="Auto" />
  </SelectiveScrollingGrid.RowDefinitions>
  ...
</SelectiveScrollingGrid>

ColumnDefinitions

 SelectiveScrollingGrid에 ColumnDefinition을 사용하여 ColumnDefinitionCollection(ColumnDefinition 개체의 순서가 지정된 컬렉션)을 설정합니다. 

 

ColumnDefinition

 SelectiveScrollingGrid 요소에 적용되는 열 별 속성을 정의합니다.

 

RowDefinitions

 SelectiveScrollingGrid에 RowDefinition을 사용하여 RowDefinitionCollection(RowDefinition 개체의 순서가 지정된 컬렉션)을 설정합니다. 

 

RowDefinition

 SelectiveScrollingGrid 요소에 적용되는 행 별 속성을 정의합니다.


 

DataGridRowHeader

 개별 DataGrid 행 머리글을 나타냅니다.

👀 DataGridRowHeader의 Style 내용은 편에서 참고하시면 됩니다.

DataGridRowHeader 속성

더보기
<DataGridRowHeader Grid.RowSpan="2" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                   Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />

Grid.RowSpan

 Grid에서 자식 Content를 채울 전체 행 수를 나타내는 값을 설정합니다.

 

SelectiveScrollingGrid.SelectiveScrollingOrientation

 Cell이 Scroll 할 수 있는 방향을 설정합니다.

 

Visibility

 DataGridRowHeader의 표시 유형을 설정합니다. 예제에서는 Binding을 사용하여 DataGrid의 HeadersVisibility 값으로 설정했습니다. 이 값의 경우 Visibility로 바로 사용할 수 없기 때문에 DataGridHeadersVisibility.Row값을 Converter(DataGrid.HeadersVisibilityConverter)를 사용하여 변환합니다.

🌟 HeadersVisibility는 총 4가지 값(All, Column, None, Row)으로 가져오는 것이 가능하기에 예제에서는 4가지 중에서 Row 값을 사용합니다. 


 

DataGridCellsPresenter

 DataGrid의 템플릿 내에서 Cell을 추가할 Control의 시각적 트리 내 위치를 지정하는 데 사용됩니다.

DataGridCellsPresenter 속성

더보기
<DataGridCellsPresenter Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />

Grid.Column

 표시할 Grid의 열 자식 Content를 나타내는 값을 설정합니다.

 

ItemsPanel

 항목의 레이아웃을 제어하는 패널을 정의하는 템플릿을 가져오거나 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 ItemsPanel 값으로 설정했습니다.

 

SnapsToDevicePixels

 렌더링 하는 동안 이 DataGridCellsPresenter의 렌더링에 디바이스 관련 픽셀 스냅(Pixel Snap)을 사용할지 여부를 설정합니다. 픽셀 스냅을 사용하면 값을 true로 설정하고, 그렇지 않으면 false(기본값)로 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 SnapsToDevicePixels 값으로 설정했습니다.


 

 

DataGridDetailsPresenter

 DataGrid의 템플릿 내에서 행 정보를 추가할 Control의 시각적 트리 내 위치를 지정하는 데 사용됩니다.

DataGridDetailsPresenter 속성

더보기
<DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" 
                          Visibility="{TemplateBinding DetailsVisibility}" 
                          SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>

Grid.Column

 표시할 Grid의 열 자식 Content를 나타내는 값을 설정합니다.

 

Grid.Row

 표시할 Grid의 행 자식 Content를 나타내는 값을 설정합니다.

 

Visibility

 DataGridDetailsPresenter의 표시 유형을 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 DetailsVisibility 값으로 설정했습니다.

 

SelectiveScrollingGrid.SelectiveScrollingOrientation

 Cell이 Scroll 할 수 있는 방향을 설정합니다. 예제에서는 Binding을 사용하여 DataGrid의 AreRowDetailsFrozen 값으로 설정했습니다. 하지만 이 값을 바로 적용할 수 없기 때문에 AreRowDetailsFrozen에서 Converter(DataGrid.RowDetailsScrollingConverter)를 사용하여 변환합니다.

🌟 AreRowDetailsFrozen : 행 세부 정보가 가로로 scroll 될 수 있는지 여부를 나타내는 값을 가져오거나 설정합니다.

🌟 SelectiveScrollingOrientation의 경우 4가지의 값(Both, None, Vertical, Horizontal)을 가지고 있기 때문에 어떤 값으로 설정할지 ConverterParameter로 정해줍니다.


 

 

DataGridRow 이벤트

MouseOver과 Normal(Default)

 예제에서는 DataGridRow 이벤트로 Normal_AlternatingRow, Normal_Selected, Unfocused_Selected, Normal_Editing와 MouseOver_Editing 등 변화를 VisualStateManager로 표현하였습니다.

 

VisualStateManager

<VisualStateManager.VisualStateGroups>
  <VisualStateGroup x:Name="CommonStates">
    ...
  </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

 VisualState는 Control의 시각적 상태를 나타냅니다. 예제의 이벤트에서 시각적 변화를 주기 위해서 VisualStateGroup의 x:Name을 CommonStates로 설정했습니다.

⭐ DataGridRow는 2개(CommonStates와 ValidationStates)의 VisualStateGroup을 가지고 있습니다.

 

CommonStates

<VisualStateGroup x:Name="CommonStates">
  <VisualState x:Name="Normal" />
  <VisualState x:Name="Normal_AlternatingRow">
    <Storyboard>
      <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                    Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
        <EasingColorKeyFrame KeyTime="0" Value="{StaticResource ContentAreaColorLight}" />
      </ColorAnimationUsingKeyFrames>
      <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                    Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
        <EasingColorKeyFrame KeyTime="0" Value="{StaticResource ContentAreaColorDark}" />
      </ColorAnimationUsingKeyFrames>
    </Storyboard>
  </VisualState>
  ...
</VisualStateGroup>

 모든 Storyboard의 내용을 풀어보면 ["DGR_Border"라는 이름을 가진 Control의 Background GradientStops 묶음 중 0번과 1번의 색을 미리 정의한 색 A와 B로 바꾸는 것]입니다. 이 A와 B색은 이벤트 별로 4가지로 나뉩니다.

1. A : ContentAreaColorLight B : ContentAreaColorDark
 - Normal_AlternatingRow : 행은 대체 행인 상태입니다.

2. A : ControlMediumColor B : ControlDarkColor
 - Normal_Selected : 행이 선택된 상태입니다.
 - Unfocused_Selected : 행이 선택되어 있으며 포커스가 없는 상태입니다.
 - Normal_Editing : 행이 편집 모드인 상태입니다.
 - MouseOver_Editing : 마우스 포인터가 행 위에 배치되고 행이 편집 모드에 있는 상태입니다.
 - MouseOver_Unfocused_Editing : 마우스 포인터가 행 위에 배치되고 행이 편집 모드에 있으며 포커스가 없는 상태입니다.
 - Unfocused_Editing : 행이 편집 모드에 있으며 포커스가 없는 상태입니다.

3. A : ControlMediumColor B : ControlMouseOverColor
 - MouseOver : 마우스 포인터가 행 위에 있는 상태입니다.

4. A : ControlMouseOverColor B : ControlMouseOverColor
 - MouseOver_Selected : 마우스 포인터가 행 위에 배치되고 행이 선택된 상태입니다.
 - MouseOver_Unfocused_Selected : 마우스 포인터가 행 위에 배치되고 행이 선택되며 포커스가 없는 상태입니다.

🌟 Normal의 경우 Storyboard가 존재하지 않지만 명시해주지 않으면 상태가 Normal로 변할 때 외형이 바뀌지 않습니다.

ColorAnimationUsingKeyFrames
 KeyFrames 집합을 따라 Color 속성 값에 EasingColorKeyFrame의 애니메이션 효과를 줍니다.

 

 


 

 

[ DataGridCell Style ]

 예제에 사용된 DataGridCell Style은 DataGrid의 Cell 부분을 Style로 미리 정의해둔 것입니다.

 

 

DataGridCell 속성

<Style TargetType="{x:Type DataGridCell}">
  <Setter Property="Template">
    <Setter.Value>
      ...
    </Setter.Value>
  </Setter>
</Style>

TargetType

 이 Style을 적용할 형식을 설정합니다. 예제에서는 "{x:Type DataGridCell}"로 설정했습니다.

 

 

Template

<Setter Property="Template">
  <Setter.Value>
    <ControlTemplate TargetType="{x:Type DataGridCell}">
      <Border x:Name="border" BorderBrush="Transparent" BorderThickness="1" Background="Transparent" SnapsToDevicePixels="True">

        <VisualStateManager.VisualStateGroups>
          ...
        </VisualStateManager.VisualStateGroups>

        <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
      </Border>
    </ControlTemplate>
  </Setter.Value>
</Setter>

 예제에서 사용되는 Template는 Control의 외형을 지정해줄 수 있는 ControlTemplate입니다.

👀 Template에 대해서 좀 더 아시고 싶으신 분은 이 페이지를 참고하시길 바랍니다.

 

 

DataGridCell 구성

 예제의 Template에서 구성한 DataGridCell은 위의 이미지와 같이 Border가 ContentPresenter를 감싸는 형태로 구성되어있습니다.

 

Border(border)

 다른 요소의 주위에 윤곽선, 배경 또는 둘 다를 그립니다.

Border 속성

더보기

x:Name

 Border에 이름을 붙입니다. 이름을 붙이는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.

 

BorderBrush

 Border의 윤곽선 색을 설정합니다. 예제에서는 Transparent(투명)으로 설정했습니다.

 

BorderThickness

 Border의 윤곽선 두께를 설정합니다.

 

Background

 Border의 배경 색을 설정합니다. 예제에서는 Transparent(투명)으로 설정했습니다.

 

SnapsToDevicePixels

 렌더링 하는 동안 Border의 렌더링에 디바이스 관련 픽셀 스냅(Pixel Snap)을 사용할지 여부를 설정합니다. 픽셀 스냅을 사용하면 값을 true로 설정하고, 그렇지 않으면 false(기본값)로 설정합니다.


 

ContentPresenter

 ContentControl의 내용을 표시합니다.

ContentPresenter 속성

더보기

SnapsToDevicePixels

 렌더링 하는 동안 ContentPresenter의 렌더링에 디바이스 관련 픽셀 스냅(Pixel Snap)을 사용할지 여부를 설정합니다. 픽셀 스냅을 사용하면 값을 true로 설정하고, 그렇지 않으면 false(기본값)로 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 SnapsToDevicePixels 값으로 설정했습니다.


 

 

 

DataGridCell 이벤트

Current : 윤곽선이 검정색이다

 예제에서는 DataGridCell 이벤트로 Current변화를 VisualStateManager로 표현하였습니다.

 

VisualStateManager

<VisualStateManager.VisualStateGroups>
  <VisualStateGroup x:Name="FocusStates">
    <VisualState x:Name="Unfocused" />
    <VisualState x:Name="Focused" />
  </VisualStateGroup>
  <VisualStateGroup x:Name="CurrentStates">
    <VisualState x:Name="Regular" />
    <VisualState x:Name="Current">
      <Storyboard>
        <ColorAnimationUsingKeyFrames Storyboard.TargetName="border"
                                      Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)">
          <EasingColorKeyFrame KeyTime="0" Value="{StaticResource DatagridCurrentCellBorderColor}" />
        </ColorAnimationUsingKeyFrames>
      </Storyboard>
    </VisualState>
  </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

 VisualState는 Control의 시각적 상태를 나타냅니다. 예제의 이벤트에서 시각적 변화를 주기 위해서 VisualStateGroup의 x:Name을 FocusStates와 CurrentStates로 설정했습니다. 하지만 FocusStates의 경우 아무런 설정을 해주지 않았기 때문에 삭제해도 무관합니다.

⭐ DataGridCell은 6개(CommonStates, FocusStates, CurrentStates, InteractionStates, SelectionStates, ValidationStates)의 VisualStateGroup을 가지고 있습니다.

 

CurrentStates

Current
 Storyboard의 내용을 풀어보면 ["border"라는 이름을 가진 Control의 BorderBrush를 미리 정의해둔 DatagridCurrentCellBorderColor로 바꾸는 것]입니다.​
🌟 Regular의 경우 Storyboard가 존재하지 않지만 명시해주지 않으면 Current에서 Regular로 상태가 변할 때 외형이 바뀌지 않습니다. ​


ColorAnimationUsingKeyFrames
 KeyFrames 집합을 따라 Color 속성 값에 EasingColorKeyFrame의 애니메이션 효과를 줍니다.​

 

 


 

 

전체 코드

더보기

<BooleanToVisibilityConverter x:Key="bool2VisibilityConverter" />

<!--Style and template for the button in the upper left corner of the DataGrid.-->
<Style TargetType="{x:Type Button}"
       x:Key="{ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, 
  TypeInTargetAssembly={x:Type DataGrid}}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Grid>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="MouseOver">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Shape.Fill).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Pressed">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Shape.Fill).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlPressedColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                 Storyboard.TargetName="Arrow">
                    <DiscreteObjectKeyFrame KeyTime="0"
                                            Value="{x:Static Visibility.Collapsed}" />
                  </ObjectAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <Rectangle x:Name="Border"
                     SnapsToDevicePixels="True">
            <Rectangle.Stroke>
              <LinearGradientBrush EndPoint="0.5,1"
                                   StartPoint="0.5,0">
                <GradientStop Color="{DynamicResource BorderLightColor}"
                              Offset="0" />
                <GradientStop Color="{DynamicResource BorderMediumColor}"
                              Offset="1" />
              </LinearGradientBrush>
            </Rectangle.Stroke>
            <Rectangle.Fill>
              <LinearGradientBrush EndPoint="0.5,1"
                                   StartPoint="0.5,0">
                <GradientStop Color="{DynamicResource ControlLightColor}"
                              Offset="0" />
                <GradientStop Color="{DynamicResource ControlMediumColor}"
                              Offset="1" />
              </LinearGradientBrush>
            </Rectangle.Fill>
          </Rectangle>
          <Polygon x:Name="Arrow"
                   HorizontalAlignment="Right"
                   Margin="8,8,3,3"
                   Opacity="0.15"
                   Points="0,10 10,10 10,0"
                   Stretch="Uniform"
                   VerticalAlignment="Bottom">
            <Polygon.Fill>
              <SolidColorBrush Color="{DynamicResource GlyphColor}" />
            </Polygon.Fill>
          </Polygon>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!--Style and template for the DataGrid.-->
<Style TargetType="{x:Type DataGrid}">
  <Setter Property="Foreground"
          Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
  <Setter Property="BorderBrush">
    <Setter.Value>
      <LinearGradientBrush EndPoint="0.5,1"
                           StartPoint="0.5,0">
        <GradientStop Color="{DynamicResource BorderLightColor}"
                      Offset="0" />
        <GradientStop Color="{DynamicResource BorderDarkColor}"
                      Offset="1" />
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>
  <Setter Property="BorderThickness"
          Value="1" />
  <Setter Property="RowDetailsVisibilityMode"
          Value="VisibleWhenSelected" />
  <Setter Property="ScrollViewer.CanContentScroll"
          Value="true" />
  <Setter Property="ScrollViewer.PanningMode"
          Value="Both" />
  <Setter Property="Stylus.IsFlicksEnabled"
          Value="False" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type DataGrid}">
        <Border x:Name="border"
                SnapsToDevicePixels="True"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Padding="{TemplateBinding Padding}">
          <Border.Background>
            <SolidColorBrush Color="{DynamicResource ControlLightColor}" />
          </Border.Background>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (SolidColorBrush.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{DynamicResource ControlLightColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Normal" />
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <ScrollViewer x:Name="DG_ScrollViewer"
                        Focusable="false"
                        Background="Black">
            <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>

                  <Button Focusable="false"
                          Command="{x:Static DataGrid.SelectAllCommand}"
                          Style="{DynamicResource {ComponentResourceKey 
                      ResourceId=DataGridSelectAllButtonStyle, 
                      TypeInTargetAssembly={x:Type DataGrid}}}"
                          Visibility="{Binding HeadersVisibility, 
                      ConverterParameter={x:Static DataGridHeadersVisibility.All}, 
                      Converter={x:Static DataGrid.HeadersVisibilityConverter}, 
                      RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                          Width="{Binding CellsPanelHorizontalOffset, 
                      RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />

                  <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"
                                          Grid.ColumnSpan="2"
                                          Grid.Row="1"
                                          CanContentScroll="{TemplateBinding CanContentScroll}" />

                  <ScrollBar x:Name="PART_VerticalScrollBar"
                             Grid.Column="2"
                             Grid.Row="1"
                             Orientation="Vertical"
                             ViewportSize="{TemplateBinding ViewportHeight}"
                             Maximum="{TemplateBinding ScrollableHeight}"
                             Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
                             Value="{Binding VerticalOffset, Mode=OneWay, 
                      RelativeSource={RelativeSource TemplatedParent}}"/>

                  <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"
                               Orientation="Horizontal"
                               ViewportSize="{TemplateBinding ViewportWidth}"
                               Maximum="{TemplateBinding ScrollableWidth}"
                               Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
                               Value="{Binding HorizontalOffset, Mode=OneWay, 
                        RelativeSource={RelativeSource TemplatedParent}}"/>
                  </Grid>
                </Grid>
              </ControlTemplate>
            </ScrollViewer.Template>
            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
          </ScrollViewer>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Style.Triggers>
    <Trigger Property="IsGrouping"
             Value="true">
      <Setter Property="ScrollViewer.CanContentScroll"
              Value="false" />
    </Trigger>
  </Style.Triggers>
</Style>

<!--Style and template for the DataGridCell.-->
<Style TargetType="{x:Type DataGridCell}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type DataGridCell}">
        <Border x:Name="border"
                BorderBrush="Transparent"
                BorderThickness="1"
                Background="Transparent"
                SnapsToDevicePixels="True">
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="FocusStates">
              <VisualState x:Name="Unfocused" />
              <VisualState x:Name="Focused" />
            </VisualStateGroup>
            <VisualStateGroup x:Name="CurrentStates">
              <VisualState x:Name="Regular" />
              <VisualState x:Name="Current">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="border"
                                                Storyboard.TargetProperty="(Border.BorderBrush).
                      (SolidColorBrush.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DatagridCurrentCellBorderColor}" />
                  </ColorAnimationUsingKeyFrames
                                                >
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!--Style and template for the DataGridRow.-->
<Style TargetType="{x:Type DataGridRow}">
  <Setter Property="Background">
    <Setter.Value>
      <SolidColorBrush Color="{DynamicResource ControlLightColor}" />
    </Setter.Value>
  </Setter>
  <Setter Property="SnapsToDevicePixels"
          Value="true" />
  <Setter Property="Validation.ErrorTemplate"
          Value="{x:Null}" />
  <Setter Property="ValidationErrorTemplate">
    <Setter.Value>
      <ControlTemplate>
        <TextBlock Foreground="Red"
                   Margin="2,0,0,0"
                   Text="!"
                   VerticalAlignment="Center" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type DataGridRow}">
        <Border x:Name="DGR_Border"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                SnapsToDevicePixels="True">
          <Border.Background>
            <LinearGradientBrush EndPoint="0.5,1"
                                 StartPoint="0.5,0">
              <GradientStop Color="Transparent"
                            Offset="0" />
              <GradientStop Color="{DynamicResource ControlLightColor}"
                            Offset="1" />
            </LinearGradientBrush>
          </Border.Background>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />

              <!--Provide a different appearance for every other row.-->
              <VisualState x:Name="Normal_AlternatingRow">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ContentAreaColorLight}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">

                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ContentAreaColorDark}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>

              <!--In this example, a row in Editing or selected mode has an
              identical appearances. In other words, the states 
              Normal_Selected, Unfocused_Selected, Normal_Editing, 
              MouseOver_Editing, MouseOver_Unfocused_Editing,
              and Unfocused_Editing are identical.-->
              <VisualState x:Name="Normal_Selected">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMediumColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>

              <VisualState x:Name="Unfocused_Selected">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMediumColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>

              <VisualState x:Name="Normal_Editing">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMediumColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>

              <VisualState x:Name="MouseOver_Editing">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMediumColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>

              <VisualState x:Name="MouseOver_Unfocused_Editing">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMediumColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>

              <VisualState x:Name="Unfocused_Editing">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMediumColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>

              <VisualState x:Name="MouseOver">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMediumColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>

              <!--In this example, the appearance of a selected row 
              that has the mouse over it is the same regardless of
              whether the row is selected.  In other words, the states 
              MouseOver_Editing and MouseOver_Unfocused_Editing are identical.-->
              <VisualState x:Name="MouseOver_Selected">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>

              <VisualState x:Name="MouseOver_Unfocused_Selected">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>

          <SelectiveScrollingGrid>
            <SelectiveScrollingGrid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" />
              <ColumnDefinition Width="*" />
            </SelectiveScrollingGrid.ColumnDefinitions>
            <SelectiveScrollingGrid.RowDefinitions>
              <RowDefinition Height="*" />
              <RowDefinition Height="Auto" />
            </SelectiveScrollingGrid.RowDefinitions>
            <DataGridCellsPresenter Grid.Column="1"
                                    ItemsPanel="{TemplateBinding ItemsPanel}"
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
            <DataGridDetailsPresenter Grid.Column="1"
                                      Grid.Row="1"
                                      Visibility="{TemplateBinding DetailsVisibility}"
                                      SelectiveScrollingGrid.SelectiveScrollingOrientation=
                "{Binding AreRowDetailsFrozen, 
                ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical},
                Converter={x:Static DataGrid.RowDetailsScrollingConverter}, 
                RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
            <DataGridRowHeader Grid.RowSpan="2"
                               SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                               Visibility="{Binding HeadersVisibility, 
                ConverterParameter={x:Static DataGridHeadersVisibility.Row}, 
                Converter={x:Static DataGrid.HeadersVisibilityConverter}, 
                RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          </SelectiveScrollingGrid>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!--Style and template for the resize control on the DataGridRowHeader.-->
<Style x:Key="RowHeaderGripperStyle"
       TargetType="{x:Type Thumb}">
  <Setter Property="Height"
          Value="8" />
  <Setter Property="Background"
          Value="Transparent" />
  <Setter Property="Cursor"
          Value="SizeNS" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Thumb}">
        <Border Background="{TemplateBinding Background}"
                Padding="{TemplateBinding Padding}" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!--Style and template for the DataGridRowHeader.-->
<Style TargetType="{x:Type DataGridRowHeader}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type DataGridRowHeader}">
        <Grid>
          <VisualStateManager.VisualStateGroups>
            <!--This example does not specify an appearance for every
                state.  You can add storyboard to the states that are listed
                to change the appearance of the DataGridRowHeader when it is
                in a specific state.-->
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="Normal_CurrentRow" />
              <VisualState x:Name="Unfocused_EditingRow" />
              <VisualState x:Name="Normal_EditingRow" />
              <VisualState x:Name="MouseOver">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="rowHeaderBorder"
                                                Storyboard.TargetProperty="(Panel.Background).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="MouseOver_CurrentRow" />
              <VisualState x:Name="MouseOver_Unfocused_EditingRow" />
              <VisualState x:Name="MouseOver_EditingRow" />
              <VisualState x:Name="MouseOver_Unfocused_Selected" />
              <VisualState x:Name="MouseOver_Selected" />
              <VisualState x:Name="MouseOver_Unfocused_CurrentRow_Selected" />
              <VisualState x:Name="MouseOver_CurrentRow_Selected" />
              <VisualState x:Name="Unfocused_Selected" />
              <VisualState x:Name="Unfocused_CurrentRow_Selected" />
              <VisualState x:Name="Normal_CurrentRow_Selected" />
              <VisualState x:Name="Normal_Selected" />
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <Border x:Name="rowHeaderBorder"
                  Width="10"
                  BorderThickness="1">
            <Border.BorderBrush>
              <LinearGradientBrush EndPoint="0.5,1"
                                   StartPoint="0.5,0">
                <GradientStop Color="{DynamicResource BorderLightColor}"
                              Offset="0" />
                <GradientStop Color="{DynamicResource BorderDarkColor}"
                              Offset="1" />
              </LinearGradientBrush>
            </Border.BorderBrush>
            <Border.Background>
              <LinearGradientBrush EndPoint="0.5,1"
                                   StartPoint="0.5,0">
                <GradientStop Color="{DynamicResource ControlLightColor}"
                              Offset="0" />
                <GradientStop Color="{DynamicResource ControlMediumColor}"
                              Offset="1" />
              </LinearGradientBrush>
            </Border.Background>
            <StackPanel Orientation="Horizontal">
              <ContentPresenter VerticalAlignment="Center"
                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
              <Control SnapsToDevicePixels="false"
                       Template="{Binding ValidationErrorTemplate, 
                  RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}"
                       Visibility="{Binding (Validation.HasError), 
                  Converter={StaticResource bool2VisibilityConverter}, 
                  RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" />
            </StackPanel>
          </Border>

          <Thumb x:Name="PART_TopHeaderGripper"
                 Style="{StaticResource RowHeaderGripperStyle}"
                 VerticalAlignment="Top" />
          <Thumb x:Name="PART_BottomHeaderGripper"
                 Style="{StaticResource RowHeaderGripperStyle}"
                 VerticalAlignment="Bottom" />
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!--Style and template for the resize control on the DataGridColumnHeader.-->
<Style x:Key="ColumnHeaderGripperStyle"
       TargetType="{x:Type Thumb}">
  <Setter Property="Width"
          Value="8" />
  <Setter Property="Background"
          Value="Transparent" />
  <Setter Property="Cursor"
          Value="SizeWE" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Thumb}">
        <Border Background="{TemplateBinding Background}"
                Padding="{TemplateBinding Padding}" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!--Style and template for the DataGridColumnHeader.-->
<Style TargetType="{x:Type DataGridColumnHeader}">
  <Setter Property="VerticalContentAlignment"
          Value="Center" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
        <Grid>
          <Border x:Name="columnHeaderBorder"
                  BorderThickness="1"
                  Padding="3,0,3,0">
            <Border.BorderBrush>
              <LinearGradientBrush EndPoint="0.5,1"
                                   StartPoint="0.5,0">
                <GradientStop Color="{DynamicResource BorderLightColor}"
                              Offset="0" />
                <GradientStop Color="{DynamicResource BorderDarkColor}"
                              Offset="1" />
              </LinearGradientBrush>
            </Border.BorderBrush>
            <Border.Background>
              <LinearGradientBrush EndPoint="0.5,1"
                                   StartPoint="0.5,0">
                <GradientStop Color="{DynamicResource ControlLightColor}"
                              Offset="0" />
                <GradientStop Color="{DynamicResource ControlMediumColor}"
                              Offset="1" />
              </LinearGradientBrush>
            </Border.Background>
            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
          </Border>

          <Thumb x:Name="PART_LeftHeaderGripper"
                 HorizontalAlignment="Left"
                 Style="{StaticResource ColumnHeaderGripperStyle}" />
          <Thumb x:Name="PART_RightHeaderGripper"
                 HorizontalAlignment="Right"
                 Style="{StaticResource ColumnHeaderGripperStyle}" />
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Setter Property="Background">
    <Setter.Value>
      <LinearGradientBrush EndPoint="0.5,1"
                           StartPoint="0.5,0">
        <GradientStop Color="{DynamicResource ControlLightColor}"
                      Offset="0" />
        <GradientStop Color="{DynamicResource ControlMediumColor}"
                      Offset="1" />
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>
</Style>

<!--Style and template for the DataGridColumnHeadersPresenter.-->
<Style TargetType="{x:Type DataGridColumnHeadersPresenter}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type DataGridColumnHeadersPresenter}">
        <Grid>
          <DataGridColumnHeader x:Name="PART_FillerColumnHeader"
                                IsHitTestVisible="False" />
          <ItemsPresenter />
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>

<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>

<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>

<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>

<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>


<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215, 0.242281124</Color>

<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>

<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>

<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>

<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>

<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>

<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>

<LinearGradientBrush x:Key="MenuPopupBrush"
                     EndPoint="0.5,1"
                     StartPoint="0.5,0">
  <GradientStop Color="{DynamicResource ControlLightColor}"
                Offset="0" />
  <GradientStop Color="{DynamicResource ControlMediumColor}"
                Offset="0.5" />
  <GradientStop Color="{DynamicResource ControlLightColor}"
                Offset="1" />
</LinearGradientBrush>

<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
                     StartPoint="0,0"
                     EndPoint="1,0">
  <LinearGradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#000000FF"
                    Offset="0" />
      <GradientStop Color="#600000FF"
                    Offset="0.4" />
      <GradientStop Color="#600000FF"
                    Offset="0.6" />
      <GradientStop Color="#000000FF"
                    Offset="1" />
    </GradientStopCollection>
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

 

 


 

 

이 글의 내용은 아래의 사이트에서 기초합니다.

https://docs.microsoft.com/ko-kr/dotnet/desktop/wpf/controls/datagrid-styles-and-templates?view=netframeworkdesktop-4.8 

 

DataGrid 스타일 및 템플릿 - WPF .NET Framework

Windows Presentation Foundation DataGrid 컨트롤의 스타일 및 템플릿에 대해 알아봅니다. 컨트롤에 고유한 모양을 부여하도록 ControlTemplate을 수정합니다.

docs.microsoft.com

 

반응형

'프로그램 개발 > WPF: Style&Template' 카테고리의 다른 글

DatePicker②  (0) 2022.05.19
DatePicker①  (0) 2022.05.18
DataGrid③  (0) 2022.05.16
DataGrid②  (0) 2022.05.13
DataGrid①  (2) 2022.05.13