안녕하세요, 이번 글에서는 지난 글에 이어서 Microsoft에서 제공하는 WPF [ListView의 스타일 및 템플릿] 예제를 톺아보겠습니다. ListView Style의 경우 Style들이 ScrollViewer, Thumb, GridViewColumnHeader, ListView, ListViewItem 순서로 나눠져 있습니다. 이번 글에서는 ScrollViewer, GridViewColumnHeader와 Thumb에 대해서 보도록 하겠습니다.
[ ScrollViewer Style ]
예제에서 사용된 ScrollViewer는 GridView.GridViewScrollViewerStyleKey에 사용할 Style을 미리 정의해둔 것입니다. 이 GridView.GridViewScrollViewerStyleKey는 ListView의 Scroll에서 사용되기 때문에, 쉽게 생각하면 ListView의 ScrollViewer 부분을 Style로 미리 정의해둔 것입니다.
ScrollViewer 속성
<Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}" TargetType="ScrollViewer">
<Setter Property="Template">
<Setter.Value>
...
</Setter.Value>
</Setter>
</Style>
x:Key
XAML 정의 사전에서 만들고 참고하는 요소를 고유하게 식별합니다.
TargetType
이 Style을 적용할 형식을 설정합니다.
Template
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Grid ... >
...
<DockPanel ... >
<ScrollViewer ... >
<GridViewHeaderRowPresenter ... />
</ScrollViewer>
<ScrollContentPresenter Name="PART_ScrollContentPresenter" ... />
</DockPanel>
<ScrollBar Name="PART_HorizontalScrollBar" ... />
<ScrollBar Name="PART_VerticalScrollBar" ... />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
Control의 템플릿을 설정합니다. 예제에서 사용되는 Template는 Control의 외형을 지정해줄 수 있는 ControlTemplate입니다.
👀 Template에 대해서 좀 더 아시고 싶으신 분은 이 페이지를 참고하시길 바랍니다.
ScrollViewer Template 구성
ScrollViewer Style은 DockPanel으로 ScrollViewer과 ScrollContentPresenter를 구성하였습니다.
Grid
열 및 행으로 구성되는 유연한 모눈 영역을 정의합니다.
⭐ Grid 속성
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
...
</Grid>
Background
Grid의 배경색을 설정합니다. 예제에서는 TemplateBinding을 사용하여 ScrollViewer의 Background 값으로 설정했습니다.
ColumnDefinitions
Grid에 ColumnDefinition을 사용하여 ColumnDefinitionCollection(ColumnDefinition 개체의 순서가 지정된 컬렉션)을 설정합니다.
ColumnDefinition
Grid 요소에 적용되는 열 별 속성을 정의합니다. Width로 너비를 숫자 값, 'Auto' 또는 '*'(기본값)로 설정할 수 있습니다.
RowDefinitions
Grid에 RowDefinition을 사용하여 RowDefinitionCollection(RowDefinition 개체의 순서가 지정된 컬렉션)을 설정합니다.
RowDefinition
Grid 요소에 적용되는 행 별 속성을 정의합니다. Height로 높이를 숫자 값, 'Auto' 또는 '*'(기본값)로 설정할 수 있습니다.
DockPanel
자식 요소를 서로 맞춰 가로 또는 세로로 정렬할 수 있는 영역을 정의합니다.
⭐ DockPanel 속성
<DockPanel Margin="{TemplateBinding Padding}">
...
</DockPanel>
Margin
DockPanel의 외부 여백을 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 Padding 값으로 설정했습니다.
⭐ DocPanel에서 알아두면 좋은 간단한 정보
Doc은 자식 Control에서 DocPanel.Doc을 사용하여 설정합니다. 값으로는 Left, Top, Right, Bottom이 있습니다. Control의 순서에 따라서 구성 유형이 달라질 수 있습니다.
기본 설정인 DockPanel.LastCHildFill 속성을 true(기본값)로 설정하는 경우 DockPanel의 마지막 자식 요소는 마지막 자식 요소에 설정한 다른 dock 값에 관계없이 항상 나머지 공간을 채웁니다.
ScrollViewer
표시 가능한 다른 요소를 포함할 수 있는 Scroll 가능한 영역을 나타냅니다.
⭐ ScrollViewer 속성
<ScrollViewer DockPanel.Dock="Top" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Focusable="false">
...
</ScrollViewer>
DockPanel.Dock
Doc 내에 있는 자식 요소의 DockPanel위치를 지정합니다. 값으로는 Left, Top, Right, Bottom이 있습니다.
HorizontalScrollBarVisibility
가로 ScrollBar를 표시해야 하는지 여부를 설정합니다. 기본값은 Hidden이며 다른 값으로 Auto, Disabled, Visible이 있습니다.
VerticalScrollBarVisibility
세로 ScrollBar를 표시해야 하는지 여부를 설정합니다. 기본값은 Visible이며 다른 값으로 Auto, Disabled, Hidden이 있습니다.
GridViewHeaderRowPresenter
열 헤더 행의 레이아웃을 정의하는 데 사용되는 개체를 나타냅니다.
⭐ GridVIewHeaderRowPresenter 속성
<GridViewHeaderRowPresenter Margin="2,0,2,0"
Columns="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderContainerStyle="{Binding Path=TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderTemplate="{Binding Path=TemplatedParent.View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderTemplateSelector="{Binding Path=TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}"
AllowsColumnReorder="{Binding Path=TemplatedParent.View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderContextMenu="{Binding Path=TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderToolTip="{Binding Path=TemplatedParent.View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
🌟 Margin과 SnapsToDevicePixels를 제외한 모든 속성들은 Binding을 사용하여 TemplatedParent.View.속성의 값들로 설정했습니다. 예제에서 사용된 ColumnHeaderContainerStyle의 경우 예제에서 정의한 GridViewColumnHeader가 사용되었습니다.
Margin
GridViewHeaderRowPresenter의 외부 여백을 설정합니다. 예제에서는 4개(좌, 상, 우, 하)로 나누어서 설정했습니다.
Columns
GridViewColumnCollection을 설정합니다.
ColumnHeaderContainerStyle
열 머리글에 사용할 Style을 설정합니다.
ColumnHeaderTemplate
열 머리글을 표시하는 데 사용할 템플릿을 설정합니다.
ColumnHeaderTemplateSelector
열 머리글을 표시하는 데 사용할 DataTemplateSelector(데이터 개체와 데이터 바인딩된 요소를 기반으로 하여 DataTemplate을 선택하는 방법)를 설정합니다.
AllowsColumnReorder
열의 위치를 변경할 수 있는지 여부를 설정합니다. 열 머리글의 끌어서 놓기 작업으로 열을 이동할 수 있으면 true(기본값)이고, 그렇지 않으면 false입니다.
ColumnHeaderContextMenu
열 머리글의 ContextMenu를 설정합니다.
ColumnHeaderToolTip
열 머리글 행의 도구 설명 내용을 가져오거나 설정합니다.
SnapsToDevciePixels
렌더링 하는 동안 GridViewHeaderRowPresenter의 렌더링에 디바이스 관련 픽셀 스냅(Pixel Snap)을 사용할지 여부를 설정합니다. 픽셀 스냅을 사용하면 값을 true로 설정하고, 그렇지 않으면 false(기본값)로 설정합니다.
ScrollContentPresenter(PART_ScrollContentPresenter)
ScrollViewer Control의 내용을 표시합니다.
⭐ ScrollContentPresenter 속성
<ScrollContentPresenter Name="PART_ScrollContentPresenter" KeyboardNavigation.DirectionalNavigation="Local"
CanContentScroll="True" CanHorizontallyScroll="False" CanVerticallyScroll="False" />
Name
ScrollContentPresenter에 이름을 설정합니다. 이름을 붙이는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.
KeyboardNavigation.DirectionalNavigation
이 속성이 설정된 요소의 자식에 대한 방향 탐색 동작을 설정합니다. 값으로는 Contained, Continue, Cycle, Local, None, Once가 있습니다.
👀 값에 대한 자세한 설명은 이 페이지를 참고하시면 됩니다.
CanContentScroll
IScrollInfo가 지원되는 경우 Content가 Scroll을 제어할 수 있는지 여부를 설정합니다. Content를 Scroll 할 수 있으면 true이고, 그렇지 않으면 false입니다.
CanHorizontallyScroll
가로축에서 Scroll이 가능한지 여부를 설정합니다. Scroll이 가능하면 true이고, 가능하지 않으면 false입니다.
CanVerticallyScroll
세로축에서 Scroll이 가능한지 여부를 설정합니다. Scroll이 가능하면 true이고, 가능하지 않으면 false입니다.
ScrollBar(PART_HorizontalScrollBar, PART_VerticalScrollBar)
값에 따라 위치가 지정되는 이동식 Thumb이 있는 스크롤 막대를 제공하는 Control을 나타냅니다.
⭐ ScrollBar 속성
<ScrollBar Name="PART_HorizontalScrollBar" Orientation="Horizontal" Grid.Row="1" Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}" Value="{TemplateBinding HorizontalOffset}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" />
<ScrollBar Name="PART_VerticalScrollBar" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}" Value="{TemplateBinding VerticalOffset}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
Name
ScrollBar에 이름을 설정합니다. 이름을 붙이는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.
Orientation
ScrollBar가 세로 방향으로 표시될지 가로 방향으로 표시될지를 설정합니다. 기본값은 Vertical(세로 방향)이며 다른 값으로 Horizontal(가로 방향)이 있습니다.
Grid.Row
표시할 Grid의 행 자식 Content를 나타내는 값을 설정합니다.
Grid.Column
표시할 Grid의 열 자식 Content를 나타내는 값을 설정합니다.
Maximum
범위 요소에서 사용 가능한 가장 높은 Value를 설정합니다. 예제에서는 TemplateBinding을 사용하여 각각 부모의 ScrollableWidth와 ScrollableHeight 값으로 설정했습니다.
ViewportSize
현재 볼 수 있는 Scroll 가능한 Content 양을 설정합니다. 예제에서는 TemplateBinding을 사용하여 각각 부모의 ViewportWidth와 ViewportHeight 값으로 설정했습니다.
Value
범위 Control의 현재 크기를 설정합니다. 예제에서는 TemplateBinding을 사용하여 각각 부모의 HorizontalOffset과 VerticalOffset 값으로 설정했습니다.
Visibility
ScorllBar의 표시 유형을 설정합니다. 기본값은 Visible이며, 다른 값으로 Collapsed와 Hidden이 있습니다. 예제에서는 TemplateBinding을 사용하여 각각 부모의 ComputedHorizontalScrollBarVisibility와 ComputedVerticalScrollBarVisibility 값으로 설정했습니다.
[ GridViewColumnHeader Style ]
예제에서 사용된 GridViewColumnHeader는 GridViewColumnHeader에 사용할 Style을 미리 정의해둔 것입니다. 이 GridViewColumnHeader는 ListView에서 사용되기 때문에, 쉽게 생각하면 ListView의 GridViewColumnHeader 부분을 Style로 미리 정의해둔 것입니다.
GridViewColumnHeader 속성
<Style x:Key="{x:Type GridViewColumnHeader}" TargetType="GridViewColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Template">
<Setter.Value>
...
</Setter.Value>
</Setter>
<Style.Triggers>
...
</Style.Triggers>
</Style>
x:Key
XAML 정의 사전에서 만들고 참고하는 요소를 고유하게 식별합니다.
TargetType
이 Style을 적용할 형식을 설정합니다.
HorizontalContentAlignment
Content의 가로 맞춤을 설정합니다. 기본값은 Left이며, 다른 값으로 Stretch, Center, Right가 있습니다.
VerticalContentAlignment
Content의 세로 맞춤을 설정합니다. 기본값은 Top이며, 다른 값으로 Stretch, Center, Bottom이 있습니다.
Foreground
전경색을 설정합니다. 예제에서는 DynamicResource를 사용하여 미리 정의되어 있는 SystemColors.ControlTextBrushKey로 설정했습니다.
Template
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Grid>
...
<Border x:Name="HeaderBorder" ... >
...
<ContentPresenter x:Name="HeaderContent" ... />
</Border>
<Thumb x:Name="PART_HeaderGripper" ... />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
Control의 템플릿을 설정합니다. 예제에서 사용되는 Template는 Control의 외형을 지정해줄 수 있는 ControlTemplate입니다.
👀 Template에 대해서 좀 더 아시고 싶으신 분은 이 페이지를 참고하시길 바랍니다.
GridViewColumnHeader Template 구성
GridViewColumnHeader Style은 ContentPresenter을 Border가 감싼 형태와 Thumb로 구성되어있습니다.
Grid
열 및 행으로 구성되는 유연한 모눈 영역을 정의합니다.
Border(HeaderBorder)
다른 요소의 주위에 윤곽선, 배경 또는 둘 다를 그립니다.
⭐ Border 속성
<Border x:Name="HeaderBorder" BorderThickness="0,1,0,1" Padding="2,0,2,0">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}" Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}" Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource ControlLightColor}" Offset="0.0" />
<GradientStop Color="{DynamicResource ControlMediumColor}" Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
...
</Border>
x:Name
Border에 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.
BorderThickness
Border의 윤곽선 두께를 설정합니다. 예제에서는 4개(좌, 상, 우, 하)의 값으로 나누어서 설정했습니다.
Padding
Border의 윤곽선과 자식 요소 사이의 간격을 설정합니다. 예제에서는 4개(좌, 상, 우, 하)의 값으로 나누어서 설정했습니다.
BorderBrush
Border의 윤곽선 색을 설정합니다. 예제에서는 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.
Background
Border의 배경색을 설정합니다. 예제에서는 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.
👀 그라데이션 색에 대하여 알고 싶으신 분은 이 페이지를 참고하시길 바랍니다.
ContentPresenter(HeaderContent)
모든 유형의 단일 Content로 이루어진 Control을 나타냅니다.
⭐ ContentPresenter 속성
<ContentPresenter x:Name="HeaderContent" Margin="0,0,0,1" RecognizesAccessKey="True"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
x:Name
ContentPresenter에 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.
Margin
ContentPresenter의 외부 여백을 설정합니다. 예제에서는 값을 4개(좌, 상, 우, 하)로 나누어서 설정했습니다.
RecognizesAccessKey
ContentPresenter의 스타일에 AccessText가 사용되는지 여부를 설정합니다. AccessText가 사용되면 true이고, 그렇지 않으면 false(기본값)입니다.
VerticalAlignment
ContentPresenter의 세로 정렬 위치를 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 VerticalAlignment로 설정했습니다,
HorizontalAlignment
ContentPresenter의 가로 정렬 위치를 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 HorizontalContentAlignment로 설정했습니다.
SnapsToDevicePixels
렌더링 하는 동안 ContentPresenter의 렌더링에 디바이스 관련 픽셀 스냅(Pixel Snap)을 사용할지 여부를 설정합니다. 픽셀 스냅을 사용하면 값을 true로 설정하고, 그렇지 않으면 false(기본값)로 설정합니다.
Thumb(PART_HeaderGripper)
사용자가 끌어올 수 있는 Control을 나타냅니다.
⭐ Thumb 속성
<Thumb x:Name="PART_HeaderGripper" HorizontalAlignment="Right" Margin="0,0,-9,0"
Style="{StaticResource GridViewColumnHeaderGripper}" />
x:Name
Thumb의 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.
HorizontalAlignment
Thumb의 가로 정렬 위치를 설정합니다. 기본값은 Stretch이며, 다른 값으로는 Center, Left, Right가 있습니다.
Margin
Thumb의 외부 여백을 설정합니다. 예제에서는 4개(좌, 상, 우, 하)로 나누어서 설정했고 음수 값을 사용하여 Padding 값처럼 내부 여백처럼 설정했습니다.
Style
Style은 Thumb에 속성, 리소스 및 이벤트 처리기를 공유할 수 있게 합니다. 예제에서는 예제에서 정의한 GridViewColumnHeaderGripper로 설정했습니다.
GridViewColumnHeader 이벤트
예제에서는 MouseOver 이벤트를 VisualState 그리고 Role 이벤트를 Trigger로 표현하였습니다.
VisualStateManager
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
...
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
VisualState는 Control의 시각적 상태를 나타냅니다. 예제의 이벤트에서 시각적 변화를 주기 위해서 VisualStateGroup의 x:Name을 CommonStates로 설정했습니다.
⭐ CommonStates Event
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="HeaderBorder">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed" />
<VisualState x:Name="Disabled" />
</VisualStateGroup>
MouseOver
Storyboard의 내용을 풀어보면 ["HeaderBorder"라는 이름을 가진 Control의 Background GradientStops 묶음 중 1번(0번부터 시작)을 ControlMouseOverColor로 바꾸는 것]입니다.
🌟 Normal, Pressed, Disabled의 경우 Storyboard가 존재하지 않지만 명시해주지 않으면 MouseOver에서 각각의 상태로 변할 때 MouseOver에서 외형이 바뀌지 않습니다.
ColorAnimationUsingKeyFrames
KeyFrames 집합을 따라 Color 속성 값에 EasingColorKeyFrame의 애니메이션 효과를 줍니다.
Triggers
<Style.Triggers>
<Trigger Property="Role" Value="Floating">
...
</Trigger>
<Trigger Property="Role" Value="Padding">
...
</Trigger>
</Style.Triggers>
Trigger는 어떤 조건이나 이벤트 등이 주어졌을 때 Control의 상태 또는 이벤트 핸들러 등을 호출하는 기능을 의미합니다. 예제에서는 Role의 값에 따라서 다른 이벤트로 설정했습니다.
Role은 GridViewColumnHeader의 역할을 의미합니다. 값으로는 Floating, Normal, Padding이 있습니다.
Floating
열 머리글이 열을 이동하기 위하여 끌어서 놓는 작업을 의미합니다.
⭐ Floating Event
<Trigger Property="Role" Value="Floating">
<Setter Property="Opacity" Value="0.7" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Canvas Name="PART_FloatingHeaderCanvas">
<Rectangle Fill="#60000000" Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}" />
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
- Opacity(불투명도)의 값을 0.7로 변경합니다.
- Template를 다음과 같이 구성을 변경합니다. 간단히 구성을 설명하면 "PART_FloatingHeaderCanvas"라는 이름을 가진 Canvas 내부에 불투명한(16진수로 60 값) 검은색 Rectangle(사각형)을 구성한 것입니다.
Padding
열 머리글이 열 머리글 행의 마지막 머리글이면 안쪽 여백에 사용하는 것을 의미합니다.
⭐ Padding Event
<Trigger Property="Role" Value="Padding">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Border Name="HeaderBorder" BorderThickness="0,1,0,1">
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlLightColor}" />
</Border.Background>
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}" Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}" Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
- Template의 "HeaderBorder"의 Background와 BorderBrush를 변경합니다.
[ Thumb Style ]
예제에서 사용된 Thumb는 GridViewColumnHeaderGripper에 사용할 Style을 미리 정의해둔 것입니다.
Thumb 속성
<Style x:Key="GridViewColumnHeaderGripper" TargetType="Thumb">
<Setter Property="Width" Value="18" />
<Setter Property="Background">
<Setter.Value>
...
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
...
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
...
</Setter.Value>
</Setter>
</Style>
x:Key
XAML 정의 사전에서 만들고 참고하는 요소를 고유하게 식별합니다.
TargetType
이 Style을 적용할 형식을 설정합니다.
Width
Thumb의 너비를 설정합니다.
Background
Thumb의 배경색을 설정합니다. 예제에서는 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}" Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}" Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
BorderBrush
Thumb의 윤곽선 색을 설정합니다. 예제에서는 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="White" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
👀 그라데이션 색에 대하여 알고 싶으신 분은 이 페이지를 참고하시길 바랍니다.
Template
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
...
</ControlTemplate>
</Setter.Value>
</Setter>
Control의 템플릿을 설정합니다. 예제에서 사용되는 Template는 Control의 외형을 지정해줄 수 있는 ControlTemplate입니다.
👀 Template에 대해서 좀 더 아시고 싶으신 분은 이 페이지를 참고하시길 바랍니다.
Thumb Template 구성
Thumb Style은 Rectangle을 Border가 감싼 형태로 구성되어있습니다.
Border
다른 요소의 주위에 윤곽선, 배경 또는 둘 다를 그립니다.
⭐ Border 속성
<Border Padding="{TemplateBinding Padding}" Background="Transparent">
...
</Border>
Padding
Border의 윤곽선과 자식 요소 사이의 간격을 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 Padding 값으로 설정했습니다.
Background
Border의 배경색을 설정합니다. 예제에서는 Transparent(투명)으로 설정했습니다.
Rectangle
사각형을 그립니다.
⭐ Rectangle 속성
<Rectangle HorizontalAlignment="Center" Width="1" Fill="{TemplateBinding Background}" />
HorizontalAlignment
Rectangle의 가로 정렬 위치를 설정합니다. 기본값은 Stretch이며, 다른 값으로는 Left, Center, Right가 있습니다.
Width
Rectangle의 너비를 설정합니다.
Fill
도형의 내부 색을 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 Background 값으로 설정했습니다.
전체 코드
<Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}"
TargetType="ScrollViewer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel Margin="{TemplateBinding Padding}">
<ScrollViewer DockPanel.Dock="Top"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
Focusable="false">
<GridViewHeaderRowPresenter Margin="2,0,2,0"
Columns="{Binding Path=TemplatedParent.View.Columns,
RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderContainerStyle="{Binding
Path=TemplatedParent.View.ColumnHeaderContainerStyle,
RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderTemplate="{Binding
Path=TemplatedParent.View.ColumnHeaderTemplate,
RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderTemplateSelector="{Binding
Path=TemplatedParent.View.ColumnHeaderTemplateSelector,
RelativeSource={RelativeSource TemplatedParent}}"
AllowsColumnReorder="{Binding
Path=TemplatedParent.View.AllowsColumnReorder,
RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderContextMenu="{Binding
Path=TemplatedParent.View.ColumnHeaderContextMenu,
RelativeSource={RelativeSource TemplatedParent}}"
ColumnHeaderToolTip="{Binding
Path=TemplatedParent.View.ColumnHeaderToolTip,
RelativeSource={RelativeSource TemplatedParent}}"
SnapsToDevicePixels="{TemplateBinding
SnapsToDevicePixels}" />
</ScrollViewer>
<ScrollContentPresenter Name="PART_ScrollContentPresenter"
KeyboardNavigation.DirectionalNavigation="Local"
CanContentScroll="True"
CanHorizontallyScroll="False"
CanVerticallyScroll="False" />
</DockPanel>
<ScrollBar Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Value="{TemplateBinding HorizontalOffset}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" />
<ScrollBar Name="PART_VerticalScrollBar"
Grid.Column="1"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Value="{TemplateBinding VerticalOffset}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="GridViewColumnHeaderGripper"
TargetType="Thumb">
<Setter Property="Width"
Value="18" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Padding="{TemplateBinding Padding}"
Background="Transparent">
<Rectangle HorizontalAlignment="Center"
Width="1"
Fill="{TemplateBinding Background}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="Black"
Offset="0" />
<GradientStop Color="White"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type GridViewColumnHeader}"
TargetType="GridViewColumnHeader">
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="HeaderBorder">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed" />
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="HeaderBorder"
BorderThickness="0,1,0,1"
Padding="2,0,2,0">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter x:Name="HeaderContent"
Margin="0,0,0,1"
RecognizesAccessKey="True"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<Thumb x:Name="PART_HeaderGripper"
HorizontalAlignment="Right"
Margin="0,0,-9,0"
Style="{StaticResource GridViewColumnHeaderGripper}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Role"
Value="Floating">
<Setter Property="Opacity"
Value="0.7" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Canvas Name="PART_FloatingHeaderCanvas">
<Rectangle Fill="#60000000"
Width="{TemplateBinding ActualWidth}"
Height="{TemplateBinding ActualHeight}" />
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="Role"
Value="Padding">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Border Name="HeaderBorder"
BorderThickness="0,1,0,1">
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlLightColor}" />
</Border.Background>
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="{x:Type ListView}"
TargetType="ListView">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility"
Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility"
Value="Auto" />
<Setter Property="ScrollViewer.CanContentScroll"
Value="true" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListView">
<Border Name="Border"
BorderThickness="1">
<Border.Background>
<SolidColorBrush Color="{StaticResource ControlLightColor}" />
</Border.Background>
<Border.BorderBrush>
<SolidColorBrush Color="{StaticResource BorderMediumColor}" />
</Border.BorderBrush>
<ScrollViewer Style="{DynamicResource
{x:Static GridView.GridViewScrollViewerStyleKey}}">
<ItemsPresenter />
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsGrouping"
Value="true">
<Setter Property="ScrollViewer.CanContentScroll"
Value="false" />
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter TargetName="Border"
Property="Background">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource DisabledBorderLightColor}" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type ListViewItem}"
TargetType="ListViewItem">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border"
Padding="2"
SnapsToDevicePixels="true"
Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource SelectedBackgroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource SelectedUnfocusedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<GridViewRowPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</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>
이 글의 내용은 아래의 사이트에서 기초합니다.
'프로그램 개발 > WPF: Style&Template' 카테고리의 다른 글
Menu② (0) | 2022.06.07 |
---|---|
Menu① (0) | 2022.06.03 |
ListView① (0) | 2022.05.31 |
ListBoxItem (0) | 2022.05.30 |
ListBox (0) | 2022.05.30 |