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

DataGrid③

(ㅇㅅㅎ) 2022. 5. 16. 21:02
728x90
반응형

 

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

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

 

 

[ DataGridColumnHeader Style ]

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

 

 

DataGridColumnHeader 속성

<Style TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Template">
        <Setter.Value>
            ...
        </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>

TargetType

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

 

 

VerticalContentAlignment

 DataGridColumnHeader Content의 세로 맞춤을 설정합니다.

 

 

Background

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

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

 

 

Tempalte

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
            <Grid>
                <Border x:Name="columnHeaderBorder" BorderThickness="1" Padding="3,0,3,0">
                    <Border.BorderBrush>
                        ...
                    </Border.BorderBrush>

                    <Border.Background>
                        ...
                    </Border.Background>

                    <ContentPresenter ... />
                </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>

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

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

 

 

DataGridColumnHeader 구성

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

 

Grid

 열 및 행으로 구성되는 유연한 모눈 영역을 정의합니다.

 

Border(columnHeaderBorder)

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

Border 속성

더보기
<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 ... />
</Border>

x:Name

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

 

BorderThickness

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

 

Padding

 Border의 윤곽선 두께와 자식 요소 사이의 간격을 설정합니다. 예제에서는 좌, 우의 간격만 3으로 설정했습니다.

 

BorderBrush

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

 

Background

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

 

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


 

 

ContentPresenter

 ContentControl의 내용을 표시합니다.

ContentPresenter 속성

더보기
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />

HorizontalAlignment

 ContentPresenter의 가로 정렬 위치를 설정합니다. 기본값은 Stretch이며, 다른 값으로는 Center, Left, Right가 있습니다. 예제에서는 TemplateBinding을 사용하여 부모의 HorizontalAlignment 값으로 설정했습니다.

 

SnapsToDevicePixels

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

 

VerticalAlignment

 ContentPresenter의 세로 정렬 위치를 설정합니다. 기본값은 Stretch이며, 다른 값으로는 Top, Center, Bottom이 있습니다. 예제에서는 TemplateBinding을 사용하여 부모의 VerticalContentALignment 값으로 설정했습니다.


 

 

Thumb(PART_LeftHeaderGripper, PART_RightHeaderGripper)

 사용자가 끌어올 수 있는 Control를 나타냅니다.

Thumb 속성

더보기
<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}" />
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}" />

x:Name

 Thumb에 이름을 붙입니다. 이름을 붙이는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다. 예제에서는 "PART_LeftHeaderGripper"와 "PART_RightHeaderGripper"라는 이름을 각각 붙였습니다. 2개의 이름은 DataGridColumnHeader에 명명된 파트입니다.

🌟 PART_LeftHeaderGripper : 왼쪽에서 열 머리글의 크기를 조정하는 데 사용되는 요소입니다.

🌟 PART_RightHeaderGripper : 오른쪽에서 열 머리글의 크기를 조정하는 데 사용되는 요소입니다.

 

HorizontalAlignment

 Thumb의 가로 정렬 위치를 설정합니다. 기본값은 Stretch이며, 다른 값으로는 Center, Left, Right가 있습니다.

 

Style

 렌더링 될 때 이 요소에서 사용할 Style을 설정합니다. 예제에서는 미리 정의한 "ColumnHeaderGripperStyle"로 설정했습니다.


 

 


 

 

[ DataGridRowHeader Style ]

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

 

 

DataGridRowHeader 속성

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

TargetType

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

 

 

Template

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type DataGridRowHeader}">
            <Grid>
                <VisualStateManager.VisualStateGroups>
                    ...
                </VisualStateManager.VisualStateGroups>
                <Border x:Name="rowHeaderBorder" ...>

                    <StackPanel Orientation="Horizontal">
                        <ContentPresenter ... />
                        <Control ... />
                    </StackPanel>
                </Border>

                <Thumb x:Name="PART_TopHeaderGripper" ... />
                <Thumb x:Name="PART_BottomHeaderGripper" ... />
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>

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

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

 

 

DataGridRowHeader 구성

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

 

Grid

 열 및 행으로 구성되는 유연한 모눈 영역을 정의합니다.

 

Border(rowHeaderBorder)

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

Border 속성

더보기
<!-- <Border x:Name="rowHeaderBorder" MinWidth="10" Width="{TemplateBinding Width}" BorderThickness="1"> -->
<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">
        ...    
    </StackPanel>
</Border>

x:Name

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

 

Width

 Border의 너비를 설정합니다. 예제에서는 10으로 설정되어있지만 10으로 설정할 경우 DataGridSelectAllButtonStyle의 Polygon이 보이지 않는 문제가 있습니다. 그래서 Polygon을 표시하고 싶을 경우 주석 처리한 윗줄처럼 변경한 뒤 사용하시면 됩니다.

👀 DataGridSelectAllButtonStyle 부분은 [Microsoft Control Style & Template 톺아보기 - DataGrid②]에서 확인하시면 됩니다.

 

BorderThickness

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

 

BorderBrush

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

 

Background

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


 

 

StackPanel

 가로 또는 세로 방향으로 한 줄로 자식 요소를 정렬합니다.

StackPanel 속성

더보기
<StackPanel Orientation="Horizontal">
    <ContentPresenter ... />
    <Control ... />
</StackPanel>

Orientation

 Control 또는 Layout에 있을 수 있는 다른 방향을 정의합니다. 기본값은 Vertical(세로 방향)이며, 다른 값으로 Horizontal(가로 방향)이 있습니다.


 

 

ContentPresenter

 ContentControl의 내용을 표시합니다.

ContentPresenter 속성

더보기
<ContentPresenter VerticalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />

VerticalAlignment

 ContentPresenter의 세로 정렬 위치를 설정합니다. 기본값은 Stretch이며, 다른 값으로는 Top, Center, Bottom이 있습니다.

 

SnapsToDevicePixels

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


 

 

Control

 ControlTemplate을 사용하여 모양을 정의하는 UI(사용자 인터페이스) 요소에 대한 기본 클래스를 나타냅니다.

Control 속성

더보기
<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}}}" />

SnapsToDevicePixels

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

 

Template

 ControlTemplate을 설정합니다. 예제에서는 Binding을 사용하여 DataGridRow의 ValidationErrorTemplate 값으로 설정했습니다.

🌟 ValidationErrorTemplate : 행 유효성 검사 시 오류를 시각적으로 나타내는 데 사용되는 템플릿입니다.

 

Visibility

 Control의 표시 유형을 설정합니다. 예제에서는 Binding을 사용하여 DataGridRow의 Validation.HasError 값으로 설정했습니다. 하지만 Validation.HasError 값은 true/false 값만 존재하기 때문에 미리 정의해둔 "bool2VisibilityConverter"라는 이름을 가진 BooleanToVisibilityConverter를 사용하여 변환해줍니다.


 

 

Thumb(PART_TopHeaderGripperPART_BottomHeaderGripper)

 사용자가 끌어올 수 있는 Control를 나타냅니다.

Thumb 속성

더보기
<Thumb x:Name="PART_TopHeaderGripper" Style="{StaticResource RowHeaderGripperStyle}" VerticalAlignment="Top" />
<Thumb x:Name="PART_BottomHeaderGripper" Style="{StaticResource RowHeaderGripperStyle}" VerticalAlignment="Bottom" />

x:Name

 Thumb에 이름을 붙이는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다. 예제에서는 "PART_TopHeaderGripper"와 "PART_BottomHeaderGripper"라는 이름을 각각 붙였습니다. 2개의 이름은 DataGridRowHeader에 명명된 파트입니다.

🌟 PART_TopHeaderGripper : 맨 위에서 행 머리글의 크기를 조정하는 데 사용되는 요소입니다.

🌟 PART_BottomHeaderGripper : 맨 아래에서 행 머리글의 크기를 조정하는 데 사용되는 요소입니다.

 

Style

 렌더링 될 때 이 요소에서 사용할 Style을 설정합니다. 예제에서는 미리 정의한 "RowHeaderGripperStyle"로 설정했습니다.

 

VerticalAlignment

 Thumb의 세로 정렬 위치를 설정합니다. 기본값은 Stretch이며, 다른 값으로는 Top, Center, Bottom이 있습니다.


 

 

 

DataGridRowHeader 이벤트

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

 

VisualStateManager

<VisualStateManager.VisualStateGroups>
    <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>

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

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

 

CommonStates

MouseOver
 Storyboard의 내용을 풀어보면 ["rowHeaderBorder"라는 이름을 가진 Control의 Background GradientStops 묶음 중 1번(0번부터 시작)에 해당하는 색을 ControlMouseOverColor로 바꾸는 것]입니다.


🌟 MouseOver 외 나머지의 경우 Storyboard가 존재하지 않지만 명시가 되어있는 이유는 Microsoft에서 예제 사용자가 원하는 대로 지정하라고 남겨둔 것입니다. 다른 부분 다 지워도 상관없지만 Normal의 부분은 남겨두는 것이 좋습니다. 만약 남겨두지 않으면 MouseOver에서 Normal로 상태가 변해도 외형이 변하지 않기 때문입니다.

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

 

 


 

 

[ ColumnHeaderGripperStyle & RowHeaderGripperStyle ]

 예제에 사용된 ColumnHeaderGripperStyle과 RowHeaderGripperStyle은 Thumb의 Style로 각각 DataColumnHeader와 RowHeaderGripper에서 사용됩니다. Thumb은 사용자가 끌어올 수 있는 Control를 나타냅니다. 예제에서는 이미지의 화살표 부분입니다. 코드를 살펴보면 2개의 속성(x:Key, Width/Height)만 제외하고 같기 때문에 함께 보도록 하겠습니다.

 

 

ColumnHeaderGripperStyle & RowHeaderGripperStyle 속성

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

x:Key

 XAML 정의 사전에서 만들고 참조하는 요소를 고유하게 식별합니다. 예제에서는 "{x:Type Thumb}"로 설정했습니다.

 

 

TargetType

 이 Style을 적용할 형식을 설정합니다. 예제에서는 "ColumnHeaderGripperStyle"과 "RowHeaderGripperStyle"로 설정했습니다.

 

 

Width

 Thumb의 너비를 설정합니다.

 

 

Height

 Thumb의 높이를 설정합니다.

 

 

Background

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

 

 

Cursor

 마우스 포인터가 Thumb 위에 있을 때 표시되는 커서를 설정합니다. ColumnHeaderGripperStyle의 경우 SizeWE(양방향 동/서 크기 조정 Cursor)로 설정했고 RowHeaderGripperStyle은 SizeNS(양방향 남/북 크기 조정 Cursor)로 설정했습니다.

👀 Cursor의 다른 값들이 궁금하시면 이 페이지에서 확인하시면 됩니다.

 

 

Template

 예제에서 사용되는 Template는 Control의 외형을 지정해줄 수 있는 ControlTemplate입니다. ColumnHeaderGripperStyle과 RowHeaderGripperStyle의 Template의 구성이 같으니 같이 설명하도록 하겠습니다. 

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

 

 

Template 구성

 예제의 Template에서 구성한 Thumb은 Border 1개로 구성되어있습니다.

 

Border

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

⭐ Border 속성

더보기

Background

 Border의 배경색을 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 Background 값으로 설정했습니다.

 

Padding

 Border의 윤곽선 두께와 자식 요소 사이의 간격을 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 Padding 값으로 설정했습니다.


 

 

 

 


 

 

전체 코드

더보기
<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.18
DataGrid④  (0) 2022.05.17
DataGrid②  (0) 2022.05.13
DataGrid①  (2) 2022.05.13
ContextMenu  (0) 2022.05.11