안녕하세요, 이번 글에서는 Microsoft에서 제공하는 WPF [ProgressBar의 스타일 및 템플릿] 예제를 톺아보겠습니다.
ProgressBar
작업 진행률을 나타냅니다. 작업이 진행됨에 따라 기본적으로 왼쪽에서 오른쪽으로 채워진 창으로 구성됩니다.
ProgressBar Style
예제의 XAML 코드를 ProgressBar에 적용하면 위와 같은 결과가 나옵니다. 이러한 결과에 도달하도록 코드 순서로 속성을 살펴보면 다음과 같습니다.
ProgressBar 속성
<Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
<Setter Property="Template">
<Setter.Value>
...
</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>
...
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
...
</Setter.Value>
</Setter>
</Style>
x:Key
XAML 정의 사전에서 만들고 참고하는 요소를 고유하게 식별합니다. 문자를 이용하여 값을 설정하지만 예제에서처럼 x:Type을 사용하여 Control에 바로 적용하도록 설정할 수 있습니다.
TargetType
이 Style을 적용할 형식을 설정합니다.
Template
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid ... >
<VisualStateManager.VisualStateGroups>
...
</VisualStateManager.VisualStateGroups>
<Border x:Name="PART_Track" ... >
...
</Border>
<Border x:Name="PART_Indicator" ... >
...
<Grid ... x:Name="Animation">
<Rectangle x:Name="PART_GlowRect" ... />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
ProgressBar의 템플릿을 설정합니다. 예제에서 사용되는 Template는 ProgressBar의 외형을 지정해줄 수 있는 ControlTemplate입니다.
👀 Template에 대해서 좀 더 아시고 싶으신 분은 이 페이지를 참고하시길 바랍니다.
Background
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="{DynamicResource ControlLightColor}" Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
ProgressBar의 배경색을 설정합니다. 예제에서는 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.
👀 그라데이션 색에 대해서 알고 싶으신 분은 이 페이지를 참고하시길 바랍니다.
Foreground
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlMediumColor}" Offset="0" />
<GradientStop Color="{DynamicResource ControlDarkColor}" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
ProgressBar의 전경색(채워지는 막대 색)을 설정합니다. 예제에서는 LinearGradientBrush을 사용하여 그라데이션 색으로 설정했습니다.
👀 그라데이션 색에 대해서 알고 싶으신 분은 이 페이지를 참고하시길 바랍니다.
ProgressBar Template 구성
ProgressBar는 Grid 내부에 Border를 경로(PART_Track)와 진행률(PART_Indicator)로 나누어서 구성하였습니다.
Grid
열 및 행으로 구성되는 유연한 모눈 영역을 정의합니다.
⭐ Grid 속성
[ 외곽 ]
<Grid MinHeight="14" MinWidth="200" Background="{TemplateBinding Background}">
...
</Grid>
[ Animation ]
<Grid ClipToBounds="True" x:Name="Animation">
...
</Grid>
MinHeight
Grid의 최소 높이를 설정합니다.
MinWidth
Grid의 최소 너비를 설정합니다.
Background
Grid의 배경색을 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 Background 값으로 설정했습니다.
ClipToBounds
요소를 포함하는 Container의 크기에 맞게 이 요소의 Content 또는 이 요소의 자식 요소의 Content를 잘라 낼지 여부를 설정합니다. Content를 잘라내야 하면 true이고, 그렇지 않으면 false입니다.
x:Name
Border에 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다.
Border
다른 요소의 주위에 윤곽선, 배경 또는 둘 다를 그립니다.
⭐ Border 속성
[ PART_Track ]
<Border x:Name="PART_Track" CornerRadius="2" BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
</Border>
[ PART_Indicator ]
<Border x:Name="PART_Indicator" CornerRadius="2" BorderThickness="1" HorizontalAlignment="Left" Background="{TemplateBinding Foreground}" Margin="0,-1,0,1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}" Offset="0.0" />
<GradientStop Color="{DynamicResource BorderMediumColor}" Offset="1.0" />
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
...
</Border>
x:Name
Border의 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다. 예제에서는 PART_Track과 PART_Indicator로 설정했습니다.
🌟 PART_Track : ProgressBar에서 진행률 표시기의 경로를 정의하는 개체입니다.
🌟 PART_Indicator : ProgressBar에서 진행률을 나타내는 개체입니다.
CornerRadius
Border의 모서리 둥근 정도를 설정합니다.
BorderThickness
Border의 윤곽선 두께를 설정합니다.
BorderBrush
Border의 윤곽선 색을 설정합니다. 예제에서는 SolidColorBrush를 사용하여 미리 정의한 색으로 설정하거나 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.
👀 그라데이션 색에 대해서 알고 싶으신 분은 이 페이지를 참고하시길 바랍니다.
HorizontalAlignment
Border의 가로 맞춤 설정입니다. 기본값은 Stretch이며, 다른 값으로 Left, Center, Right가 있습니다.
Background
Border의 배경색을 설정합니다. 예제에서는 TemplateBinding을 사용하여 부모의 Foreground 값으로 설정했습니다.
Margin
Border의 외부 여백을 설정합니다. 예제에서는 값을 4개(좌, 상, 우, 하)로 나누어서 설정했습니다.
Rectangle
사각형을 그립니다.
⭐ Rectangle 속성
<Rectangle x:Name="PART_GlowRect" Width="100" HorizontalAlignment="Left" Fill="{DynamicResource ProgressBarIndicatorAnimatedFill}" Margin="-100,0,0,0" />
x:Name
Rectangle에 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다. 예제에서는 PART_GlowRect로 설정했습니다.
🌟 PART_GlowRect : ProgressBar에서 진행률 표시줄을 장식하는 개체입니다.
Width
Rectangle의 너비를 설정합니다.
HorizontalAlignment
Rectangle의 가로 맞춤 설정입니다. 기본값은 Stretch이며, 다른 값으로 Left, Center, Right가 있습니다.
Fill
도형의 내부 색을 설정합니다. 예제에서는 미리 정의한 색인 ProgressBarIndicatorAnimatedFill로 설정했습니다.
Margin
Rectangle의 외부 여백을 설정합니다. 예제에서는 값을 4개(좌, 상, 우, 하)로 나누어서 설정했습니다.
ProgressBar 이벤트
예제에서는 Indeterminate 변화를 VisualStateManger로 표현하였습니다.
⭐ Indeterminate : ProgressBar에서 반복 패턴을 사용하여 일반적 진행률을 보고합니다.
VisualStateManger
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
...
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
VisualState는 Control의 시각적 상태를 나타냅니다. 예제의 이벤트에서 시각적 변화를 주기 위해서 VisualStateGroup의 x:Name을 CommonStates로 설정했습니다.
⭐ CommonStates
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate" />
<VisualState x:Name="Indeterminate">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="00:00:00" Storyboard.TargetName="PART_Indicator" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush>Transparent</SolidColorBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
Indeterminate
Storyboard의 내용을 풀어보면 ["PART_Indicator"의 Background(배경색)을 SolidColorBrush를 사용하여 Transparent(투명)으로 변경하는 것]입니다.
ObjectAnimationUsingKeyFrames
지정된 Object에 대해 KeyFrames 집합을 따라 Duration 속성 값에 애니메이션 효과를 줍니다.
DiscreteObjectKeyFrame
불연속 보간을 사용하여 이전 키 프레임의 Object 값에서 고유 Value로 애니메이션 효과를 적용합니다.
전체 코드
<Style x:Key="{x:Type ProgressBar}"
TargetType="{x:Type ProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid MinHeight="14"
MinWidth="200"
Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate" />
<VisualState x:Name="Indeterminate">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="00:00:00"
Storyboard.TargetName="PART_Indicator"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush>Transparent</SolidColorBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="PART_Track"
CornerRadius="2"
BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
</Border>
<Border x:Name="PART_Indicator"
CornerRadius="2"
BorderThickness="1"
HorizontalAlignment="Left"
Background="{TemplateBinding Foreground}"
Margin="0,-1,0,1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Grid ClipToBounds="True"
x:Name="Animation">
<Rectangle x:Name="PART_GlowRect"
Width="100"
HorizontalAlignment="Left"
Fill="{DynamicResource ProgressBarIndicatorAnimatedFill}"
Margin="-100,0,0,0" />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1"
StartPoint="0,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlDarkColor}"
Offset="1" />
</LinearGradientBrush>
</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' 카테고리의 다른 글
RepeatButton (0) | 2022.06.16 |
---|---|
RadioButton (0) | 2022.06.16 |
PasswordBox (0) | 2022.06.15 |
NavigationWindow③ (0) | 2022.06.14 |
NavigationWindow② (0) | 2022.06.13 |