본문 바로가기
C#/WPF

[WPF] ControlTemplate의 영향력

by HJ0216 2024. 6. 30.

xaml에서 비슷한 두 개의 코드에 style을 적용시켰는데, 하나의 코드에서는 동작하고 하나의 코드에서는 동작을 하지 않았습니다. 이유를 간단하게 정리해 보고자 합니다.


저에겐 MouseOver 시, 글씨를 굵게 만들어주는 Style이 하나 있습니다.

 

<Style x:Key="DefaultButton" TargetType="Button">
    <Setter Property="Background" Value="DodgerBlue"/>
    <Setter Property="Foreground" Value="#FFFFFF"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border x:Name="Border" 
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        CornerRadius="5">
                    <ContentPresenter HorizontalAlignment="Center" 
                                      VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="FontWeight" Value="Bold" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

 

스타일을 한 번 정의해두면, 여러 UI 요소에 동일한 스타일을 적용할 수 있어 코드의 재사용성이 높아집니다.

 

DodgerBlue 색상의 호버 효과가 있는 버튼은 이제 저에게 식은죽 먹기가 됩니다.

 

<Button Style="{StaticResource DefaultButton}">
    <TextBlock Text="Hello"/>
</Button>
<Button Style="{StaticResource DefaultButton}"
        Content="Hello"
        >

 

 

하지만, 아래 코드에서는 Button안의 TextBlock에 FontWeight를 직접적으로 명시했다가는 DodgerBlue 색상만 가진 버튼이 됩니다.

 

<Button Style="{StaticResource DefaultButton}">
    <TextBlock Text="Hello"
               FontWeight="Light"
               />
</Button>
<Button Style="{StaticResource DefaultButton}"
        Content="Hello"
        FontWeight="Light"
        >

 

그 차이를 간단히 정리해 보고자 합니다.

 

먼저, Sytle에 설정된 내용을 간력히 정리해보면, 다음과 같습니다.

 

 

1. ControlTemplate

Control Template , 즉 <> 태그의 외형을 정의합니다.

ControlTemplate을 사용할 경우, 기본 Template을 덮어씁니다.

 

2. ContentPresenter

새로운 Template을 만들어 사용할 경우, 내용(Content)을 표시하는 기능인 ContentPresenter도 함께 선언해야 합니다.

 

3. TemplateBinding

ControlTemplate 안에서 외부의 속성 값을 바인딩할 때 사용합니다.

여기서는 DefaultButton을 사용한 Button의 Background인 DodgerBlue를 참조하게 됩니다.

 

4. Trigger

마지막으로 trigger는 특정 조건이 만족될 때(여기서는 마우스가 버튼 위에 올라왔을 때) 스타일이나 속성을 변경합니다. 이를 통해 ControlTemplate에서 설정된 속성들을 변경할 수 있습니다.

 

 

1번 코드와 2번 코드는 Button 안의 TextBlock에 FontWeight를 직접 설정했느냐의 차이가 있습니다.

 

1번은

  Complate.Trigger → Button 속성 변경 → ContentPresenter: 변경된 속성을 Button의 자식 요소인 TextBlock에 전달합니다.

2번은

  Complate.Trigger → Button 속성 변경 → ContentPresenter: 변경된 속성을 Button의 자식 요소인 TextBlock에 전달합니다. 하지만, 자식 요소에서 직접 설정된 속성은 ControlTemplate의 외부에서 설정된 것으로 간주되어, ControlTemplate의 트리거에서 영향을 받지 않습니다. 

 

간단하게 정리하면, ControlTemplate은 전체적인 Template를 control할 수 있지만, <> 안에서 직접 설정된 요소는 변경할 수 없습니다.

 

 

 

📚 참고 자료

 

[c# wpf] Control Template 란? / 사용방법 (with Style)

이 글을 읽기 전 선수 지식 포스팅 [c# wpf] Style 태그 사용 방법 [c# wpf] Style 상속 방법(with BasedOn) [c# wpf] StaticResource란? (DynamicResource 비교) 왼쪽 그림은 우리가 아는 기본적인 버튼에 빨간 배경색을

yeko90.tistory.com

 

'C# > WPF' 카테고리의 다른 글

[WPF] 생성자 단위 초기화와 필드 단위 초기화  (0) 2024.06.04
[WPF] MVVM 패턴에서의 전체 선택  (0) 2024.05.19
[WPF] ObservableCollection  (0) 2024.05.15
[WPF] View, ViewModel Singleton  (0) 2024.05.12
[WPF] 생성자 Overloading (2)  (0) 2024.05.11