XAML or HTML

018. 컨트롤템플릿(ControlTemplate) #1

XAML 뽀개기

ControlTemplate 한마디로 정의하자면 외형바꾸기입니다. 모든 컨트롤은 ControlTemplate 가질 있습니다. 다시 말하자면 System.Windows.Controls.Control을 상속 받은 컨트롤은 템플릿을 가질 수 있습니다.

 

물론 아주 간단한 외형 변경은 Style 이용해 바꿀 수도 있습니다. 하지만 다른 요소들을 추가하는  복잡하고 섬세한 수준의 외형 변경은 한계가 있습니다. 다시 말해 버튼의 외형에 간단한 도형이라도 추가하려면 스타일을 이용해서는 불가능에 가깝습니다.

 

Button 외형바꾸기는 지겨우니깐 단계 복잡한 컨트롤을 예를 들어 살펴봅시다.

 

 

Header Content 그룹으로 묶여있는 구조입니다. 위와 같이 표현하는 방법에는 어떤 것들이 있을까요?

 

1
2
3
4
5
<StackPanel Margin="15,10">                
    <TextBlock Text="재생" FontWeight="Bold" Margin="5"/>                
    <Button Content="시작"/>                
    <Button Content="정지"/>            
</StackPanel>
cs

 

아무래도 위와 같은 XAML 코드가 가장 빠르고 적당할 같습니다.

 

 

만약 위와 같은 형식이 몇 번이고 반복된다면 어떨까요?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<StackPanel>
    <StackPanel Margin="15,10">
        <TextBlock Text="재생" FontWeight="Bold" Margin="5"/>
        <Button Content="시작"/>
        <Button Content="정지"/>
    </StackPanel>
    <StackPanel Margin="15,10">
        <TextBlock Text="트랙" FontWeight="Bold" Margin="5"/>
        <Button Content="이전"/>
        <Button Content="다음"/>
    </StackPanel>
    <StackPanel Margin="15,10">
        <TextBlock Text="소리" FontWeight="Bold" Margin="5"/>
        <Button Content="작게"/>
        <Button Content="크게"/>
    </StackPanel>
</StackPanel>
cs


StackPanel 각 그룹 요소를 감싼 후 반복해서 코드를 작성하면 되겠습니다. 하지만 여기에 디자인을 변경하기 위한 스타일링 작업이 추가된다면 어떨까요?

 

 

Border 요소를 추가하고 Background, BorderBrush, BorderThickness, Margin 속성 등을 이용해 아주 살짝 스타일을 다듬어주었습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<StackPanel>
    <Border Background="WhiteSmoke" BorderBrush="DarkGray" BorderThickness="1" Margin="5">
        <StackPanel Margin="5" Background="WhiteSmoke">
            <TextBlock Text="재생" FontWeight="Bold" Margin="0,0,0,5"/>
            <Button Content="시작"/>
            <Button Content="정지"/>
        </StackPanel>
    </Border>
    <Border Background="WhiteSmoke" BorderBrush="DarkGray" BorderThickness="1" Margin="5">
        <StackPanel Margin="5">
            <TextBlock Text="트랙" FontWeight="Bold" Margin="0,0,0,5"/>
            <Button Content="이전"/>
            <Button Content="다음"/>
        </StackPanel>
    </Border>
    <Border Background="WhiteSmoke" BorderBrush="DarkGray" BorderThickness="1" Margin="5">
        <StackPanel Margin="5">
            <TextBlock Text="소리" FontWeight="Bold" Margin="0,0,0,5"/>
            <Button Content="작게"/>
            <Button Content="크게"/>
        </StackPanel>
    </Border>
</StackPanel>
cs

 

아주 간단한 스타일 변경이지만 그룹 및 그룹 내 요소의 갯수만큼 반복해서 XAML 코드가 늘어납니다. 말인 즉슨 디자인이 변경될 경우 그룹 및 그룹 내 요소의 갯수만큼 코드를 변경해야 한다는 말과 같습니다. 자 그러면 그런 비효율적인 일 최소화할 있을까요? 하나하나씩 고쳐보겠습니다.



1
2
3
4
5
6
<HeaderedContentControl Header="재생" Grid.Column="1">
    <StackPanel>
        <Button Content="시작"/>
        <Button Content="정지"/>
    </StackPanel>
</HeaderedContentControl>
cs

 

먼저 HeaderedContentControl을 사용하면 Header Content가 짝으로 이루어진 그룹을 표현할 있습니다. 컨트롤 이름에서 어느 정도 짐작이 됩니다. 그런데 어떻게 이런 기본 구조가 표현되는지 궁금할겁니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
<Style x:Key="Style_HeaderedContentControl" TargetType="{x:Type HeaderedContentControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type HeaderedContentControl}">
                <StackPanel>
                    <ContentPresenter ContentSource="Header"/>
                    <ContentPresenter />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
 
cs

 

Blend for VS [템플릿 편집 > 복사본 편집] 기능을 이용하면 아주 간단히 HeaderedContentControl의 기본 ControlTemplate 얻을 있습니다. 자동으로 생성된 코드를 살펴보면 템플릿은 스타일에 속한다고 볼  있습니다. 단독으로 사용될 수도 있습니다만 다음 기회에 살펴봅시다.

 

2개의 ContentPresenter Header Content 역할을 하는 것을 알  있습니다. 단순히 StackPanel 이용해 헤더와 컨텐츠를 세로로 정렬하고 있는 구조입니다. 이전 포스트에서 ContentPresenter 암시적으로 바인딩된다고 이야기했습니다. 그리고 Header 분리하기 위해 ContentSource 속성을 이용해 명시적으로 정의하고 있습니다. Content 속성에 TemplateBinding 문법을 이용해 명시적으로 정의할 수도 있습니다.

 

이렇게 ControlTemplate 컨트롤의 기본 구조 정의와 함께 외형을 정의하는 역할을 합니다. 다른 요소들을 추가하거나 다양한 속성들을 정의해  복잡하고 새로운 외형을 스타일링  있습니다. 다음 포스트에 이어 템플릿을 수정해 보도록 하겠습니다.


관련 목차


018. 컨트롤템플릿(ControlTemplate) #1

019. 컨트롤템플릿(ControlTemplate) #2