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

ToolBar③

(ㅇㅅㅎ) 2022. 6. 30. 15:44
728x90
반응형

 안녕하세요, 이번 글에서는 지난 글에 이어서 Microsoft에서 제공하는 WPF [ToolBar의 스타일 및 템플릿] 예제를 톺아보겠습니다. ToolBar Style의 경우 ToolBarButtonBaseStyle,  ToolBar.(ButtonStyleKey, ToggleButtonStyleKey, CheckBoxStyleKey, RadioButtonStyleKey, TextBoxStyleKey)ToolBarThumbStyle,  ToolBarOverflowButtonStyle,  ToolBar와  ToolBarTray 순서로 나눠져 있습니다.  이번 글에서는 ToolBarButtonBaseStyleToolBar.(ButtonStyleKeyToggleButtonStyleKeyCheckBoxStyleKeyRadioButtonStyleKeyTextBoxStyleKey)를 보도록 하겠습니다.

 

 

 

ToolBarButtonBaseStyle

 예제에서 사용된 ToolBarButtonBaseStyle은 ToolBar 내부에 사용되는 Button, ToggleButton, CheckBox, RadioButton의 기본 틀로 사용할 Style을 미리 정의해둔 것입니다.

 

 

ToolBarButtonBaseStyle 속성

<Style x:Key="ToolBarButtonBaseStyle" TargetType="{x:Type ButtonBase}">
    <Setter Property="SnapsToDevicePixels" Value="true" />
    <Setter Property="OverridesDefaultStyle" Value="true" />
    <Setter Property="Template">
        <Setter.Value>
            ...
        </Setter.Value>
    </Setter>
</Style>

x:Key

 XAML 정의 사전에서 만들고 참고하는 요소를 고유하게 식별합니다.

 

 

TargetType

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

⭐ ButtonBase : 모든 Button에 대한 기본 클래스를 나타냅니다.

 

 

SnapsToDevicePixels

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

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

더보기

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


 

 

OverridesDefaultStyle

 테마 스타일의 Style 속성을 포함할지 여부를 설정합니다. 테마 스타일 속성을 사용하지 않으면 true이고 사용하면 false입니다.

 

 

Template

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

                <ContentPresenter ... />
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

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

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

 

 

ToolBarButtonBaseStyle Template 구성

 ToolBarButtonBaseStyle은 Border와 ContentPresenter로 구성되어있습니다.

 

Border

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

⭐ Border 속성

더보기
<Border x:Name="Border" BorderThickness="1">
    <Border.BorderBrush>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="{DynamicResource BorderLightColor}" Offset="0" />
            <GradientStop Color="{DynamicResource BorderMediumColor}" 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>
    ...
</Border>

  

x:Name

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

 

BorderThickness

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

 

BorderBrush

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

 

Background

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

 

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


 

ContentPresenter

 ContentControl의 내용을 표시합니다.

⭐ ContentControl 속성

더보기
<ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True" />

 

Margin

 ContentPresenter의 외부 여백을 설정합니다.

 

HorizontalAlignment

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

 

VerticalAlignment

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

 

RecognizesAccessKey

 ContentPresenter의 스타일에 AccessText가 사용되는지 여부를 설정합니다. AccessText가 사용되면 true이고, 그렇지 않으면 false입니다.


 

 

ToolBarButtonBaseStyle 이벤트

 예제에서는 이벤트로  Pressed, MouseOver, Disabled와 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="Pressed">
        <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlPressedColor}" />
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="MouseOver">
        <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlMouseOverColor}" />
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="Disabled">
        <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledControlDarkColor}" />
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
</VisualStateGroup>

 Pressed & MouseOver & Disabled

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

 

🌟 Normal의 경우 Storyboard가 존재하지 않지만 명시해주지 않으면 Normal이 아닌 상태에서 외형이 변경되지 않습니다. 

 

ColorAnimationUsingKeyFrames

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


 

CheckStates

더보기
<VisualStateGroup x:Name="CheckStates">
    <VisualState x:Name="Checked">
        <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                <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에서 외형이 변경되지 않습니다.

 

ColorAnimationUsingKeyFrames

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

 

 

 


 

 

 

ToolBar.(ButtonStyleKey, ToggleButtonStyleKey, CheckBoxStyleKey, RadioButtonStyleKey)

 예제에서 사용된 ToolBar.ButtonStyleKey, ToolBar.ToggleButtonStyleKey, ToolBar.CheckBoxStyleKey, ToolBar.RadioButtonStyleKey는 ToolBar 내부에 사용되는 Button, ToggleButton, CheckBox, RadioButton에 사용할 Style입니다. 이들의 역할은 위에서 정의한 ToolBarButtonBaseStyle을 BasedOn에 적용한 것입니다.

 

 

ToolBar.(ButtonStyleKey, ToggleButtonStyleKey, CheckBoxStyleKey, RadioButtonStyleKey) 속성

<Style x:Key="{x:Static ToolBar.ButtonStyleKey}"       BasedOn="{StaticResource ToolBarButtonBaseStyle}" TargetType="{x:Type Button}" />
<Style x:Key="{x:Static ToolBar.ToggleButtonStyleKey}" BasedOn="{StaticResource ToolBarButtonBaseStyle}" TargetType="{x:Type ToggleButton}" />
<Style x:Key="{x:Static ToolBar.CheckBoxStyleKey}"     BasedOn="{StaticResource ToolBarButtonBaseStyle}" TargetType="{x:Type CheckBox}" />
<Style x:Key="{x:Static ToolBar.RadioButtonStyleKey}"  BasedOn="{StaticResource ToolBarButtonBaseStyle}" TargetType="{x:Type RadioButton}" />

x:Key

 XAML 정의 사전에서 만들고 참고하는 요소를 고유하게 식별합니다. 문자를 이용하여 값을 설정하지만 예제에서처럼 x:Static을 사용하여 ToolBar."Control"StyleKey에 바로 적용하도록 설정할 수 있습니다. 

 

 

BasedOn

 현재 Style의 기준이 되는 정의된 Style을 설정합니다. 예제에서는 StaticResource를 사용하여 미리 정의한 ToolBarButtonBaseStyle로 설정했습니다.

 

 

TargetType

 이 Style을 적용할 형식을 설정합니다.

 

 

 


 

 

 

ToolBar.TextBoxStyleKey

 예제에서 사용된 ToolBar.TextBoxStyleKey는 ToolBar 내부에 사용되는 TextBox에 사용할 Style을 미리 정의해둔 것입니다.

 

 

ToolBar.TextBoxStyleKey 속성

<Style x:Key="{x:Static ToolBar.TextBoxStyleKey}" TargetType="{x:Type TextBox}">
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
    <Setter Property="AllowDrop" Value="true" />
    <Setter Property="Template">
        <Setter.Value>
            ...
        </Setter.Value>
    </Setter>
</Style>

x:Key

 XAML 정의 사전에서 만들고 참고하는 요소를 고유하게 식별합니다. 문자를 이용하여 값을 설정하지만 예제에서처럼 x:Static을 사용하여 ToolBar.TextBoxStyleKey에 바로 적용하도록 설정할 수 있습니다.

 

 

TargetType

 이 Style을 적용할 형식을 설정합니다.

 

 

SnapsToDevicePixels

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

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

더보기

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


 

 

OverridesDefaultStyle

 테마 스타일의 Style 속성을 포함할지 여부를 설정합니다. 테마 스타일 속성을 사용하지 않으면 true이고 사용하면 false입니다.

 

 

KeyboardNavigation.TabNavigation

 자식 요소에 대한 논리적 탭 탐색 동작을 설정합니다. 값으로는 Contained, Continue, Cycle, Local, None과 Once가 있습니다.

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

 

 

FocusVisualStyle

 키보드 focus를 캡처할 때 ToolBar.TextBoxStyleKey에 적용되는 모양, 효과 또는 기타 Style 특성을 사용자 지정할 수 있는 속성을 설정합니다. 예제에서는 Null로 설정했습니다.

 

 

AllowDrop

ToolBar.TextBoxStyleKey를 끌어서 놓기 작업의 대상으로 사용할 수 있는지 여부를 설정합니다. 끌어서 놓기 작업의 대상으로 사용할 수 있으면 true이고 그렇지 않으면 false입니다.

 

 

Template

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type TextBox}">
            <Border x:Name="Border" ... >
                ...
                <VisualStateManager.VisualStateGroups> ... </VisualStateManager.VisualStateGroups>
                <ScrollViewer ... x:Name="PART_ContentHost" />
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

ToolBar.TextBoxStyleKey의 템플릿을 설정합니다. 예제에서 사용되는 Template는 ToolBar.TextBoxStyleKey의 외형을 지정해줄 수 있는 ControlTemplate입니다.

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

 

 

ToolBar.TextBoxStyleKey Template 구성

 ToolBar.TextBoxStyleKey은 Border과 ScrollViewer로 구성되어있습니다.

 

Border

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

⭐ Border 속성

더보기
<Border x:Name="Border" Padding="2" BorderThickness="1">
    <Border.Background>
        <SolidColorBrush Color="{DynamicResource ControlLightColor}" />
    </Border.Background>
    <Border.BorderBrush>
        <SolidColorBrush Color="{StaticResource BorderMediumColor}" />
    </Border.BorderBrush>
    ...
</Border>

 

x:Name

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

 

Padding

 윤곽선과 자식 요소 사이의 간격을 설정합니다. 

 

BorderThickness

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

 

Background

 Border의 배경색을 설정합니다. 예제에서는 SolidColorBrush를 사용하며 미리 정의한 색인 ControlLightColor로 설정했습니다.

 

BorderBrush

 Border의 윤곽선 색을 설정합니다. 예제에서는 SolidColorBrush를 사용하여 미리 정의한 색인 BorderMediumColor로 설정했습니다.


 

ScrollViewer

 표시 가능한 다른 요소를 포함할 수 있는 Scroll 가능한 영역을 나타냅니다.

⭐ ScrollViewer 속성

더보기
<ScrollViewer Margin="0" x:Name="PART_ContentHost" />

 

Margin

 ScrollViewer의 외부 여백을 설정합니다.

 

x:Name

 ScrollViewer에 이름을 설정합니다. 이름을 설정하는 것과 동시에 다른 곳에서 사용할 수 있도록 만들어줍니다. 예제에서는 TextBox의 명명된 부분인 PART_ContentHost로 설정했습니다.

🌟 PART_ContentHost : TextBox의 텍스트가 표시됩니다.


 

 

ToolBar.TextBoxStyleKey 이벤트

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

 

VisualStateManager

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

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

CommonStates

더보기
<VisualStateGroup x:Name="CommonStates">
    <VisualState x:Name="Normal" />
    <VisualState x:Name="Disabled">
        <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledControlDarkColor}" />
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)">
                <EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledBorderLightColor}" />
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="ReadOnly" />
    <VisualState x:Name="MouseOver" />
</VisualStateGroup>

Disabled

 Storyboard의 내용을 풀어보면 ["Border"의 Background와 BorderBrush를 변경하는 것]입니다.

 

🌟 Normal, ReadOnly, MouseOver의 경우 Storyboard가 존재하지 않지만 명시해주지 않으면 Disabled에서 외형이 변경되지 않습니다.  

 

ColorAnimationUsingKeyFrames

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


 

 

 

 


 

 

 

전체 코드

더보기
<Style x:Key="ToolBarButtonBaseStyle"
       TargetType="{x:Type ButtonBase}">
  <Setter Property="SnapsToDevicePixels"
          Value="true" />
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type ButtonBase}">
        <Border x:Name="Border"
                BorderThickness="1">
          <Border.BorderBrush>
            <LinearGradientBrush EndPoint="0.5,1"
                                 StartPoint="0.5,0">
              <GradientStop Color="{DynamicResource BorderLightColor}"
                            Offset="0" />
              <GradientStop Color="{DynamicResource BorderMediumColor}"
                            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>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="Pressed">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlPressedColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="MouseOver">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background). 
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
            <VisualStateGroup x:Name="CheckStates">
              <VisualState x:Name="Checked">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlPressedColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Unchecked" />
              <VisualState x:Name="Indeterminate" />
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <ContentPresenter Margin="2"
                            HorizontalAlignment="Center"
                            VerticalAlignment="Center"
                            RecognizesAccessKey="True" />
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Style x:Key="{x:Static ToolBar.ButtonStyleKey}"
       BasedOn="{StaticResource ToolBarButtonBaseStyle}"
       TargetType="{x:Type Button}" />
<Style x:Key="{x:Static ToolBar.ToggleButtonStyleKey}"
       BasedOn="{StaticResource ToolBarButtonBaseStyle}"
       TargetType="{x:Type ToggleButton}" />
<Style x:Key="{x:Static ToolBar.CheckBoxStyleKey}"
       BasedOn="{StaticResource ToolBarButtonBaseStyle}"
       TargetType="{x:Type CheckBox}" />
<Style x:Key="{x:Static ToolBar.RadioButtonStyleKey}"
       BasedOn="{StaticResource ToolBarButtonBaseStyle}"
       TargetType="{x:Type RadioButton}" />

<Style x:Key="{x:Static ToolBar.TextBoxStyleKey}"
       TargetType="{x:Type TextBox}">
  <Setter Property="SnapsToDevicePixels"
          Value="True" />
  <Setter Property="OverridesDefaultStyle"
          Value="True" />
  <Setter Property="KeyboardNavigation.TabNavigation"
          Value="None" />
  <Setter Property="FocusVisualStyle"
          Value="{x:Null}" />
  <Setter Property="AllowDrop"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type TextBox}">
        <Border x:Name="Border"
                Padding="2"
                BorderThickness="1">
          <Border.Background>
            <SolidColorBrush Color="{DynamicResource ControlLightColor}" />
          </Border.Background>
          <Border.BorderBrush>
            <SolidColorBrush Color="{StaticResource BorderMediumColor}" />
          </Border.BorderBrush>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).  
                    (SolidColorBrush.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledControlDarkColor}" />
                  </ColorAnimationUsingKeyFrames>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Border.BorderBrush).  
                    (SolidColorBrush.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledBorderLightColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="ReadOnly" />
              <VisualState x:Name="MouseOver" />
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <ScrollViewer Margin="0"
                        x:Name="PART_ContentHost" />
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Style x:Key="ToolBarThumbStyle"
       TargetType="{x:Type Thumb}">
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="Cursor"
          Value="SizeAll" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Thumb}">
        <Border Background="Transparent"
                SnapsToDevicePixels="True">
          <Rectangle Margin="0,2">
            <Rectangle.Fill>
              <DrawingBrush Viewport="0,0,4,4"
                            ViewportUnits="Absolute"
                            Viewbox="0,0,8,8"
                            ViewboxUnits="Absolute"
                            TileMode="Tile">
                <DrawingBrush.Drawing>
                  <DrawingGroup>
                    <GeometryDrawing Brush="#AAA"
                                     Geometry="M 4 4 L 4 8 L 8 8 L 8 4 z" />
                  </DrawingGroup>
                </DrawingBrush.Drawing>
              </DrawingBrush>
            </Rectangle.Fill>
          </Rectangle>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Style x:Key="ToolBarOverflowButtonStyle"
       TargetType="{x:Type ToggleButton}">
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type ToggleButton}">
        <Border x:Name="Border"
                CornerRadius="0,3,3,0"
                SnapsToDevicePixels="true">
          <Border.Background>
            <LinearGradientBrush EndPoint="0.5,1"
                                 StartPoint="0.5,0">
              <GradientStop Color="#00000000"
                            Offset="0" />
              <GradientStop Offset="1" />
            </LinearGradientBrush>
          </Border.Background>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="Pressed">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).    
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlPressedColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="MouseOver">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).     
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlMouseOverColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).   
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledBorderLightColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <Grid>
            <Path x:Name="Arrow"
                  Fill="Black"
                  VerticalAlignment="Bottom"
                  Margin="2,3"
                  Data="M -0.5 3 L 5.5 3 L 2.5 6 Z" />
            <ContentPresenter />
          </Grid>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Style x:Key="{x:Type ToolBar}"
       TargetType="{x:Type ToolBar}">
  <Setter Property="SnapsToDevicePixels"
          Value="true" />
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type ToolBar}">
        <Border x:Name="Border"
                CornerRadius="2"
                BorderThickness="1">
          <Border.BorderBrush>
            <LinearGradientBrush StartPoint="0,0"
                                 EndPoint="0,1">
              <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                  <GradientStop Color="{DynamicResource BorderMediumColor}"
                                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="#FFF"
                                Offset="0.0" />
                  <GradientStop Color="{DynamicResource ControlMediumColor}"
                                Offset="1.0" />
                </GradientStopCollection>
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
          </Border.Background>
          <DockPanel>
            <ToggleButton DockPanel.Dock="Right"
                          IsEnabled="{TemplateBinding HasOverflowItems}"
                          Style="{StaticResource ToolBarOverflowButtonStyle}"
                          ClickMode="Press"
                          IsChecked="{Binding IsOverflowOpen, Mode=TwoWay, 
              RelativeSource={RelativeSource TemplatedParent}}">
              <Popup x:Name="OverflowPopup"
                     AllowsTransparency="true"
                     Placement="Bottom"
                     StaysOpen="false"
                     Focusable="false"
                     PopupAnimation="Slide"
                     IsOpen="{Binding IsOverflowOpen, 
                RelativeSource={RelativeSource TemplatedParent}}">
                <Border x:Name="DropDownBorder"
                        BorderThickness="1">
                  <Border.BorderBrush>
                    <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
                  </Border.BorderBrush>
                  <Border.Background>
                    <LinearGradientBrush EndPoint="0.5,1"
                                         StartPoint="0.5,0">
                      <GradientStop Color="{DynamicResource ControlLightColor}" />
                      <GradientStop Color="{DynamicResource ControlMediumColor}"
                                    Offset="1" />
                    </LinearGradientBrush>
                  </Border.Background>
                  <ToolBarOverflowPanel x:Name="PART_ToolBarOverflowPanel"
                                        Margin="2"
                                        WrapWidth="200"
                                        Focusable="true"
                                        FocusVisualStyle="{x:Null}"
                                        KeyboardNavigation.TabNavigation="Cycle"
                                        KeyboardNavigation.DirectionalNavigation="Cycle" />
                </Border>
              </Popup>
            </ToggleButton>

            <Thumb x:Name="ToolBarThumb"
                   Style="{StaticResource ToolBarThumbStyle}"
                   Width="10" />
            <ToolBarPanel x:Name="PART_ToolBarPanel"
                          IsItemsHost="true"
                          Margin="0,1,2,2" />
          </DockPanel>
        </Border>
        <ControlTemplate.Triggers>
          <Trigger Property="IsOverflowOpen"
                   Value="true">
            <Setter TargetName="ToolBarThumb"
                    Property="IsEnabled"
                    Value="false" />
          </Trigger>
          <Trigger Property="ToolBarTray.IsLocked"
                   Value="true">
            <Setter TargetName="ToolBarThumb"
                    Property="Visibility"
                    Value="Collapsed" />
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Style x:Key="{x:Type ToolBarTray}"
       TargetType="{x:Type ToolBarTray}">
  <Setter Property="Background">
    <Setter.Value>
      <LinearGradientBrush StartPoint="0,0"
                           EndPoint="1,0">
        <LinearGradientBrush.GradientStops>
          <GradientStopCollection>
            <GradientStop Color="#FFF"
                          Offset="0.0" />
            <GradientStop Color="{DynamicResource WindowColor}"
                          Offset="1.0" />
          </GradientStopCollection>
        </LinearGradientBrush.GradientStops>
      </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>

 

 

 


 

 

 

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

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

 

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

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

docs.microsoft.com

 

반응형

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

TreeView①  (0) 2022.07.05
ToolTip  (0) 2022.07.01
ToolBar②  (0) 2022.06.29
ToolBar①  (0) 2022.06.28
ToggleButton  (0) 2022.06.22