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

ToggleButton

(ㅇㅅㅎ) 2022. 6. 22. 08:46
728x90
반응형

 

 안녕하세요, 이번 글에서는 Microsoft에서 제공하는 WPF [ToggleButton의 스타일 및 템플릿] 예제를 톺아보겠습니다.

⭐ 예제의 경우 [ComboBox의 스타일 및 템플릿]에서 사용되는 ComboBoxToggleButton과 동일합니다.

 

 

 

ToggleButton

기본 ToggleButton
예제 ToggleButton

 ToggleButton은 CheckBox 같이 상태를 전환할 수 있는 Control의 기본 클래스입니다. 주로 2가지 상태 중 하나로 선택되도록 만드는 Button입니다. 예제의 XAML 코드는 [ComboBox 스타일 및 템플릿] 예제의 ToggleButton에 사용할 ControlTemplate을 미리 정의해둔 것입니다.

 

 

ToggleButton Template 구

<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
    <Grid>
        ...
        <VisualStateManager.VisualStateGroups>
          ...
        </VisualStateManager.VisualStateGroups>
        
        <Border x:Name="Border" ... />

        <Border ... />

        <Path x:Name="Arrow" ... />
    </Grid>
</ControlTemplate>

Grid

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

⭐ Grid 속성

더보기
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition Width="20" />
    </Grid.ColumnDefinitions>
    ...
</Grid>

 

ColumnDefinitions

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

 

ColumnDefinition

 Grid 요소에 적용되는 열 별 속성을 정의합니다. Width로 너비를 숫자 값, 'Auto', 또는 '*'로 설정할 수 있습니다.


 

Border

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

⭐ Border 속성

더보기

[ Border ]

<Border x:Name="Border" Grid.ColumnSpan="2" CornerRadius="2" BorderThickness="1">
    <Border.BorderBrush>
        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
            <GradientStop Color="{DynamicResource BorderLightColor}" Offset="0" />
            <GradientStop Color="{DynamicResource BorderDarkColor}" Offset="1" />
        </LinearGradientBrush>
    </Border.BorderBrush>

    <Border.Background>
        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="{DynamicResource ControlLightColor}" />
                    <GradientStop Color="{DynamicResource ControlMediumColor}" Offset="1.0" />
                </GradientStopCollection>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
    </Border.Background>
</Border>

[ NoName ]

<Border Grid.Column="0" CornerRadius="2,0,0,2" Margin="1" >
    <Border.Background>
        <SolidColorBrush Color="{DynamicResource ControlLightColor}"/>
    </Border.Background>
</Border>

 

x:Name

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

 

Grid.Column

  Border에서 표시할 Grid의 열 값을 설정합니다.

 

Grid.ColumnSpan

 Grid에서 Border를 채울 전체 열 수를 설정합니다.

 

CornerRadius

 Border의 모퉁이가 둥근 정도를 나타내는 값을 설정합니다.

 

BorderThickness

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

 

BorderBrush

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

 

Background

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

👀 그라데이션 색에 대해서 알고 싶으신 분은 이 페이지를 참고하시길 바랍니다.


 

Path

 일련의 연결된 선 및 곡선을 그립니다.

⭐ Path 속성

더보기
<Path x:Name="Arrow" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 4 4 L 8 0 Z" >
    <Path.Fill>
        <SolidColorBrush Color="{DynamicResource GlyphColor}"/>
    </Path.Fill>
</Path>

 

x:Name

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

 

Grid.Column

 Path을 표시할 Grid의 열 값을 설정합니다.

 

HorizontalAlignment

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

 

VerticalAlignment

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

 

Data

 그릴 모양을 지정하는 Geometry를 설정합니다.

👀 값에 대한 자세한 설명은 이 페이지를 참고하시길 바랍니다.

 

Fill

 Path 내부 색을 설정합니다. 예제에서는 SolidColorBrush를 사용하여 미리 정의된 색인 GlyphColor로 설정했습니다.


 

 

ToggleButton 이벤트

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

 

VisualStateManager

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

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

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

CommonStates

더보기
<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="Border">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlMouseOverColor}" />
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="Pressed" />
    <VisualState x:Name="Disabled">
        <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                          Storyboard.TargetName="Border">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledControlDarkColor}" />
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                                          Storyboard.TargetName="Arrow">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledForegroundColor}" />
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                          Storyboard.TargetName="Border">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledBorderDarkColor}" />
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
</VisualStateGroup>

 

MouseOver

 Storyboard의 내용을 풀어보면 ["Border"의 Background GradientStops 묶음 중 1번(0번부터 시작)에 해당하는 색을 변경하는 것]입니다.

 

Disabled

 Storyboard의 내용을 풀어보면 ["Border"의 Background와 BorderBrush의 GradientStops 묶음 중 1번을 변경하고 "Arrow"의 Fill의 값을 변경하는 것]입니다.

 

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

 

ColorAnimationUsingKeyFrames

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


 

CheckStates

더보기
<VisualStateGroup x:Name="CheckStates">
    <VisualState x:Name="Checked">
        <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                          Storyboard.TargetName="Border">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlPressedColor}" />
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="Unchecked" />
    <VisualState x:Name="Indeterminate" />
</VisualStateGroup>

 

Checked

 Storyboard의 내용을 풀어보면 ["Border"의 Background GradientStops 묶음 중 1번에 해당하는 색을 변경하는 것]입니다.

 

🌟 Unchecked와 Indeterminate의 경우 Storyboard가 존재하지 않지만 명시해주지 않으면 Checked에서 Unchecked나 Indeterminate로 변할 때 외형이 바뀌지 않습니다.

 

ColorAnimationUsingKeyFrames

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


 

 

 

 


 

 

 

전체 코드

더보기
<ControlTemplate x:Key="ComboBoxToggleButton"
                 TargetType="{x:Type ToggleButton}">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition Width="20" />
    </Grid.ColumnDefinitions>
    <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="Border">
              <EasingColorKeyFrame KeyTime="0"
                                   Value="{StaticResource ControlMouseOverColor}" />
            </ColorAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
        <VisualState x:Name="Pressed" />
        <VisualState x:Name="Disabled">
          <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
                (GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                          Storyboard.TargetName="Border">
              <EasingColorKeyFrame KeyTime="0"
                                   Value="{StaticResource DisabledControlDarkColor}" />
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).
                (SolidColorBrush.Color)"
                                          Storyboard.TargetName="Arrow">
              <EasingColorKeyFrame KeyTime="0"
                                   Value="{StaticResource DisabledForegroundColor}" />
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
                (GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                          Storyboard.TargetName="Border">
              <EasingColorKeyFrame KeyTime="0"
                                   Value="{StaticResource DisabledBorderDarkColor}" />
            </ColorAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
      </VisualStateGroup>
      <VisualStateGroup x:Name="CheckStates">
        <VisualState x:Name="Checked">
          <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
                (GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                          Storyboard.TargetName="Border">
              <EasingColorKeyFrame KeyTime="0"
                                   Value="{StaticResource ControlPressedColor}" />
            </ColorAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
        <VisualState x:Name="Unchecked" />
        <VisualState x:Name="Indeterminate" />
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Border x:Name="Border"
            Grid.ColumnSpan="2"
            CornerRadius="2"
            BorderThickness="1">
      <Border.BorderBrush>
        <LinearGradientBrush EndPoint="0,1"
                             StartPoint="0,0">
          <GradientStop Color="{DynamicResource BorderLightColor}"
                        Offset="0" />
          <GradientStop Color="{DynamicResource BorderDarkColor}"
                        Offset="1" />
        </LinearGradientBrush>
      </Border.BorderBrush>
      <Border.Background>

        <LinearGradientBrush StartPoint="0,0"
                             EndPoint="0,1">
          <LinearGradientBrush.GradientStops>
            <GradientStopCollection>
              <GradientStop Color="{DynamicResource ControlLightColor}" />
              <GradientStop Color="{DynamicResource ControlMediumColor}"
                            Offset="1.0" />
            </GradientStopCollection>
          </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>

      </Border.Background>
    </Border>
    <Border Grid.Column="0"
            CornerRadius="2,0,0,2"
            Margin="1" >
      <Border.Background>
          <SolidColorBrush Color="{DynamicResource ControlLightColor}"/>
      </Border.Background>
    </Border>
    <Path x:Name="Arrow"
          Grid.Column="1"
          HorizontalAlignment="Center"
          VerticalAlignment="Center"
          Data="M 0 0 L 4 4 L 8 0 Z" >
      <Path.Fill>
          <SolidColorBrush Color="{DynamicResource GlyphColor}"/>
      </Path.Fill>
    </Path>
  </Grid>
</ControlTemplate>
<!--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/togglebutton-styles-and-templates?view=netframeworkdesktop-4.8 

 

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

ToggleButton 스타일 및 템플릿 아티클 05/06/2022 읽는 데 3분 걸림 기여자 1명 이 문서의 내용 --> 이 항목에서는 ToggleButton 컨트롤의 스타일 및 템플릿을 설명합니다. 기본값을 수정할 수 있습니다 Contr

docs.microsoft.com

 

반응형

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

ToolBar②  (0) 2022.06.29
ToolBar①  (0) 2022.06.28
Thumb  (0) 2022.06.21
TextBox  (0) 2022.06.21
TabControl  (0) 2022.06.20