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

Expander

(ㅇㅅㅎ) 2022. 5. 20. 23:48
728x90
반응형

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

 

 

 

Expander

 Expander는 Content를 표시하는 축소 가능한 창이 포함된 Header를 표시하는 Control를 나타냅니다.

 

 

 

[ Expander 속성 ]

ExpandDirection

 Expander Content 창이 열리는 방향을 설정합니다. 기본값은 Down이며, 다른 값으로 Left, Right, Up이 있습니다.

<Expander ExpandDirection="Right" />

ExpandDirection

 

 

IsExpanded

 Expander Content 창이 표시되는지 여부를 설정합니다. Content 창이 확장되면 true이고, 그렇지 않으면 false(기본값)입니다.

<Expander IsExpanded="True" />

 

 


 

 

[ Expander Style ]

 예제의 XAML 코드를 Expander에 적용하면 위와 같은 결과가 나옵니다. 이러한 결과에 도달하도록 코드 순서로 속성을 살펴보면 다음과 같습니다.

 

 

 

Expander 속성

<Style TargetType="{x:Type Expander}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Expander}">
        <Grid>
          ...
          <Border x:Name="Border" ...>
            ...
            <Grid>
              ...
              <ToggleButton ...>
                ...
              </ToggleButton>
              <ContentPresenter ... />
            </Grid>
          </Border>          
          <Border x:Name="Content" ...>
            ...
            <ContentPresenter Margin="4" />
          </Border>
        </Grid>
        ...
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Template

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

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

 

 

Expander Style 구성

 Expander Style은 Grid 내부에 ToggleButtonContentPresenter(Expander의 Header)로 구성하였습니다. 그리고 Border를 사용하여 ContentPresenter(Expander의 Content)를 구성하였습니다.

 

Grid

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

Grid 속성

더보기

바깥쪽

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition x:Name="ContentRow" Height="0" />
  </Grid.RowDefinitions>
  ...
</Grid>

안쪽

<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="20" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  ...
</Grid>

 

RowDefinitions

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

 

RowDefinition

 Grid 요소에 적용되는 행 별 속성을 정의합니다. Height로 높이를 숫자 값, 'Auto' 또는 '*'(기본값)로 설정할 수 있습니다.

 

ColumnDefinitions

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

 

ColumnDefinition

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


 

Border(Border, Content)

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

⭐ Border 속성

더보기

x:Name="Border"

<Border x:Name="Border" Grid.Row="0" BorderThickness="1" CornerRadius="2,2,0,0">
  <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}" Offset="0.0" />
          <GradientStop Color="{DynamicResource ControlMediumColor}" Offset="1.0" />
        </GradientStopCollection>
      </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
  </Border.Background>
  ...
</Border>

x:Name="Content"

<Border x:Name="Content" Grid.Row="1" BorderThickness="1,0,1,1" CornerRadius="0,0,2,2">
  <Border.BorderBrush>
    <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
  </Border.BorderBrush>
  <Border.Background>
    <SolidColorBrush Color="{DynamicResource ContentAreaColorDark}" />
  </Border.Background>
  ...
</Border>

 

x:Name

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

 

Grid.Row

 표시할 Grid(Parent)의 행을 설정합니다.

 

BorderThickness

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

 

CornerRadius

 모퉁이가 둥근 정도를 설정합니다.

 

BorderBrush

 Border의 윤곽선 색을 설정합니다.

 

Background

 Border의 배경색을 설정합니다. 

🌟 "Content"에서는 BorderBrush와 Background를 SolidColorBrush를 사용하여 미리 정의한 색으로 설정했습니다.

🌟 "Border"에서는 BorderBrush와 Background를 LinearGradientBrush를 사용하여 그라데이션 색으로 설정했습니다.

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


 

ToggleButton

 상태를 전환할 수 있는 Control입니다.

ToggleButton 속성

더보기
<ToggleButton OverridesDefaultStyle="True" Template="{StaticResource ExpanderToggleButton}"
              IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
  <ToggleButton.Background>
    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
      <GradientStop Color="{DynamicResource ControlLightColor}" Offset="0" />
      <GradientStop Color="{DynamicResource ControlMediumColor}" Offset="1" />
    </LinearGradientBrush>
  </ToggleButton.Background>
</ToggleButton>

 

OverridesDefaultStyle

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

 

Template

 Control의 템플릿을 설정합니다. 예제에서 사용되는 Template는 Control의 외형을 지정해줄 수 있는 ControlTemplate입니다. 예제에서는 미리 정의한 "ExpanderToggleButton"을 사용하였습니다.

 

IsChecked

 ToggleButton이 선택된 상태인지 여부를 설정합니다. 선택되어 있으면 true이고, 선택되어 있지 않으면 false(기본값)입니다. 예제에서는 Binding을 사용하여 TemplateParent의 IsExpanded로 설정했습니다.

 

Background

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

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


 

ContentPresenter

 모든 유형의 단일 Content로 이루어진 Control을 나타냅니다.

ContentPresenter 속성

더보기

Grid.Row="0"

<ContentPresenter Grid.Column="1" Margin="4" ContentSource="Header" RecognizesAccessKey="True" />

Grid.Row="1"

<ContentPresenter Margin="4" />

 

Grid.Column

 표시할 Grid(Parent)의 열을 설정합니다.

 

Margin

 ContentPresenter의 바깥쪽 여백을 설정합니다.

 

ContentSource

 별칭을 자동으로 지정할 때 사용할 기본 이름을 설정합니다. 예제에서는 Expander의 "Header" 값으로 설정했습니다.

 

RecognizesAccessKey

 ContentPresenter의 Style에 AccessText가 사용되는지 여부를 설정합니다. AccessText가 사용되면 true이고, 그렇지 않으면 false(기본값)입니다.

🌟 AccessText는 Alt 키를 누르면 Control의 Text/Content 속성에 밑줄을 접두사로 사용하여 액세스 키를 정의합니다. 단축키를 사용하여 이벤트를 줄 때 유용하게 사용됩니다.


 

 

Expander 이벤트

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

 

VisualStateManager

<VisualStateManager.VisualStateGroups>
  <VisualStateGroup x:Name="CommonStates">
    <VisualState x:Name="Normal" />
    <VisualState x:Name="MouseOver" />
    <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>
        <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                      Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
          <EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledBorderLightColor}" />
        </ColorAnimationUsingKeyFrames>
      </Storyboard>
    </VisualState>
  </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

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

⭐ Expander는 5개(CommonStates, FocusStates, ExpnsionStates, ExpandDirectionStates, ValidationStates)의 VisualStateGroup을 가지고 있습니다.

 

CommonStates

Disabled
 Storyboard의 내용을 풀어보면 ["Border"라는 이름을 가진 Control의 Background를 DisabledControlDarkColor 그리고 BorderBrush를 DisabledBorderLightColor로 바꾸는 것]입니다.

ColorAnimationUsingKeyFrames
 지정된 Duration에 대해 KeyFrames 집합을 따라 Color 속성 값에 애니메이션 효과를 줍니다.

 

 

Triggers

<ControlTemplate.Triggers>
  <Trigger Property="IsExpanded" Value="True">
    <Setter TargetName="ContentRow" Property="Height" Value="{Binding Height, ElementName=Content}" />
  </Trigger>
</ControlTemplate.Triggers>

 Trigger는 어떤 조건이나 이벤트 등이 주어졌을 때 Control의 상태 또는 이벤트 핸들러 등을 호출하는 기능을 의미합니다. 예제의 코드는 IsExpanded의 값이 true일 경우 ContentRow의 Height값을 Binding을 사용하여 Content의 Height로 설정합니다.

 

 


 

 

[ ExpanderToggleButton ]

 예제에 사용된 ExpanderToggleButton은 ToggleButton 부분을 ControlTemplate로 미리 정의해둔 것입니다.

 

 

 

ExpanderToggleButton 구성

<ControlTemplate x:Key="ExpanderToggleButton" TargetType="{x:Type ToggleButton}">
  <Border x:Name="Border" ...>
    ...
    <Grid>
      <Path x:Name="CollapsedArrow" ...>
        ...
      </Path>
      <Path x:Name="ExpandededArrow" ...>
        ...
      </Path>
    </Grid>
  </Border>
</ControlTemplate>

 ExpanderToggleButton은 위의 이미지처럼 Grid 내부에 Path 2개가 구성되어있습니다. 

 

Border(Border)

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

Border 속성

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

 

x:Name

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

 

CornerRadius

 모퉁이가 둥근 정도를 설정합니다.

 

BorderThickness

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

 

Background

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

 

BorderBrush

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

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


 

Grid

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

 

Path(CollapsedArrow, ExpandededArrow)

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

Path 속성

더보기

CollapsedArrow

<Path x:Name="CollapsedArrow" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 4 4 L 8 0 Z">
  <Path.Fill>
    <SolidColorBrush Color="{DynamicResource GlyphColor}" />
  </Path.Fill>
</Path>

ExpandededArrow

<Path x:Name="ExpandededArrow" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed" Data="M 0 4 L 4 0 L 8 4 Z">
  <Path.Fill>
    <SolidColorBrush Color="{DynamicResource GlyphColor}" />
  </Path.Fill>
</Path>

 

x:Name

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

 

HorizontalAlignment

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

 

VerticalAlignment

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

 

Visibility

 Path의 표시 유형을 설정합니다.

 

Data

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

 

Fill

 도형의 내부 색을 설정합니다. 예제에서는 SolidColorBrush를 사용하여 GlyphColor로 설정했습니다.

 

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


 

 

ExpanderToggleButton 이벤트

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

 

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.TargetName="Border"
                                    Storyboard.TargetProperty="(Panel.Background).(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="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
        <EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlPressedColor}" />
      </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>
      <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                    Storyboard.TargetProperty="(Border.BorderBrush).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
        <EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledBorderLightColor}" />
      </ColorAnimationUsingKeyFrames>
    </Storyboard>
  </VisualState>
</VisualStateGroup>

MouseOver
 Storyboard의 내용을 풀어보면 ["Border"라는 이름을 가진 Control의 Background를 ControlMouseOverColor로 바꾸는 것]입니다.

Pressed
 Storyboard의 내용을 풀어보면 ["Border"라는 이름을 가진 Control의 Background를 ControlPressedColor로 바꾸는 것]입니다.

Disabled
 Stoyboard의 내용을 풀어보면 ["Border"라는 이름을 가진 Control의 Background를 DisabledControlDarkColor 그리고 BorderBrush를 DisabledBorderLightColor로 바꾸는 것]입니다.

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

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

 

CheckStates

<VisualStateGroup x:Name="CheckStates">
  <VisualState x:Name="Checked">
    <Storyboard>
      <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="CollapsedArrow"> 
        <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}" /> 
      </ObjectAnimationUsingKeyFrames> 
      <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ExpandededArrow"> 
        <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" /> 
      </ObjectAnimationUsingKeyFrames> 
    </Storyboard> 
  </VisualState> 
  <VisualState x:Name="Unchecked" /> 
  <VisualState x:Name="Indeterminate" /> 
</VisualStateGroup>​


Checked
 Storyboard의 내용을 풀어보면 ["CollapsedArrow"라는 이름을 가진 Control의 Visibility를 Hidden 그리고 ExpandededArrow의 Visibility를 Visible로 바꾸는 것]입니다.

ObjectAnimationUsingKeyFrames
 지정된 Object에 대해 KeyFrames 집합을 따라 Duration 속성 값에 애니메이션 효과를 줍니다.

 

 


 

 

전체 코드

더보기
<ControlTemplate x:Key="ExpanderToggleButton"
                 TargetType="{x:Type ToggleButton}">
  <Border x:Name="Border"
          CornerRadius="2,0,0,0"
          BorderThickness="0,0,1,0">
    <Border.Background>
      <LinearGradientBrush EndPoint="0.5,1"
                           StartPoint="0.5,0">
        <GradientStop Color="{DynamicResource ControlLightColor}" />
        <GradientStop Color="{DynamicResource ControlMediumColor}"
                      Offset="1" />
      </LinearGradientBrush>
    </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>
    <VisualStateManager.VisualStateGroups>
      <VisualStateGroup x:Name="CommonStates">
        <VisualState x:Name="Normal" />
        <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="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="Disabled">
          <Storyboard>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                          Storyboard.TargetProperty="(Panel.Background).
                (GradientBrush.GradientStops)[1].(GradientStop.Color)">
              <EasingColorKeyFrame KeyTime="0"
                                   Value="{StaticResource DisabledControlDarkColor}" />
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                          Storyboard.TargetProperty="(Border.BorderBrush).
                (GradientBrush.GradientStops)[1].(GradientStop.Color)">
              <EasingColorKeyFrame KeyTime="0"
                                   Value="{StaticResource DisabledBorderLightColor}" />
            </ColorAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
      </VisualStateGroup>
      <VisualStateGroup x:Name="CheckStates">
        <VisualState x:Name="Checked">
          <Storyboard>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                           Storyboard.TargetName="CollapsedArrow">
              <DiscreteObjectKeyFrame KeyTime="0"
                                      Value="{x:Static Visibility.Hidden}" />
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                           Storyboard.TargetName="ExpandededArrow">
              <DiscreteObjectKeyFrame KeyTime="0"
                                      Value="{x:Static Visibility.Visible}" />
            </ObjectAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
        <VisualState x:Name="Unchecked" />
        <VisualState x:Name="Indeterminate" />
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid>
      <Path x:Name="CollapsedArrow"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Data="M 0 0 L 4 4 L 8 0 Z">
        <Path.Fill>
          <SolidColorBrush Color="{DynamicResource GlyphColor}" />
        </Path.Fill>
      </Path>
      <Path x:Name="ExpandededArrow"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Visibility="Collapsed"
            Data="M 0 4 L 4 0 L 8 4 Z">
        <Path.Fill>
          <SolidColorBrush Color="{DynamicResource GlyphColor}" />
        </Path.Fill>
      </Path>
    </Grid>
  </Border>
</ControlTemplate>

<Style TargetType="{x:Type Expander}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Expander}">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition x:Name="ContentRow"
                           Height="0" />
          </Grid.RowDefinitions>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="MouseOver" />
              <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>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Border.BorderBrush).
                      (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledBorderLightColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <Border x:Name="Border"
                  Grid.Row="0"
                  BorderThickness="1"
                  CornerRadius="2,2,0,0">
            <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}"
                                  Offset="0.0" />
                    <GradientStop Color="{DynamicResource ControlMediumColor}"
                                  Offset="1.0" />
                  </GradientStopCollection>
                </LinearGradientBrush.GradientStops>
              </LinearGradientBrush>

            </Border.Background>
            <Grid>
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20" />
                <ColumnDefinition Width="*" />
              </Grid.ColumnDefinitions>
              <ToggleButton OverridesDefaultStyle="True"
                            Template="{StaticResource ExpanderToggleButton}"
                            IsChecked="{Binding IsExpanded, Mode=TwoWay, 
                  RelativeSource={RelativeSource TemplatedParent}}">
                <ToggleButton.Background>
                  <LinearGradientBrush EndPoint="0.5,1"
                                       StartPoint="0.5,0">
                    <GradientStop Color="{DynamicResource ControlLightColor}"
                                  Offset="0" />
                    <GradientStop Color="{DynamicResource ControlMediumColor}"
                                  Offset="1" />
                  </LinearGradientBrush>
                </ToggleButton.Background>
              </ToggleButton>
              <ContentPresenter Grid.Column="1"
                                Margin="4"
                                ContentSource="Header"
                                RecognizesAccessKey="True" />
            </Grid>
          </Border>
          <Border x:Name="Content"
                  Grid.Row="1"
                  BorderThickness="1,0,1,1"
                  CornerRadius="0,0,2,2">
            <Border.BorderBrush>
              <SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
            </Border.BorderBrush>
            <Border.Background>
              <SolidColorBrush Color="{DynamicResource ContentAreaColorDark}" />
            </Border.Background>
            <ContentPresenter Margin="4" />
          </Border>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsExpanded"
                   Value="True">
            <Setter TargetName="ContentRow"
                    Property="Height"
                    Value="{Binding Height, ElementName=Content}" />
          </Trigger>
        </ControlTemplate.Triggers>
      </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/expander-styles-and-templates?view=netframeworkdesktop-4.8 

 

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

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

docs.microsoft.com

 

반응형

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

Frame②  (0) 2022.05.26
Frame①  (0) 2022.05.25
DocumentViewer  (0) 2022.05.20
DatePicker②  (0) 2022.05.19
DatePicker①  (0) 2022.05.18