@Vincent 두서 없이 설명드려볼게요.
아시는 부분도 많으시겠지만 시작하실 분들을 위해서도 상세하게 설명드립니다.
우선 Control 클래스에서부터 시작해볼게요.
Control 클래스는 Template (ControlTemplate) 속성을 포함하고 있습니다.
public class Control
{
public ControlTemplate Template { get; set; }
}
그리고 ItemsControl과 ContentControl은 Control 클래스를 상속받고 있죠. 그래서 이 둘은 Template을 사용할 수 있어요.
Template (ControlTemplate)은 컨트롤 모양이라고 생각하면 편해요.
그리고,
기본적으로 제공되는 Button은 실제로 ControlTemplate이 아래처럼 구현되어 있을겁니다.
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<ControlTemplate TargetType="{x:Type Button}">
<Border BorderThickness="1"
BorderBrush="#CCCCCC"
Background="{TemplateParent Background}"
Padding="8 4 8 4"
CornerRadius="2 2 2 2">
<ContentPresenter ContentSource="Content"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#DDDDDD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter>
</Style>
버튼의 모양, 트리거 등은 ControlTemplate에서 정의하고, 내부에 더 커스터마이징 가능한 영역을 지정하기 위해 ContentPresenter를 사용합니다.
그래서 Button을 사용할 때에는 Content 내용만 넣으면 되죠.
<Button Content="버튼"/>
Content를 입력하면 내부적으로 ContentPresenter를 대체하게 됩니다.
그리고 이와 동일한 개념으로 Window 클래스 또한 동일한 구조입니다.
윈도우도 버튼과 동일하게 ContentControl을 상속받는데요.
이미 윈도우도 ControlTemplate을 아래처럼 제공하고 있습니다.
<Style TargetType="{x:Type Window}">
<Setter Property="Template">
<ControlTemplate TargetType="{x:Type Window}">
<Border>
<Grid>
<Grid.RowDefinition>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinition>
<Button x:Name="PART_MinButton"/>
<Button x:Name="PART_MaxButton"/>
<Button x:Name="PART_CloseButton"/>
<ContentPresenter ContentSource="Content"/>
</Grid>
</Border>
</ContentTemplate>
</Setter>
</Style>
윈도우 클래스도 이미 ControlTemplate에서 모든 모양이 구현되어 제공되고 있기 때문에 ContentPresenter 영역에 해당하는 Content 부분만 채워 넣으면 되는데요.
소스코드에서는 아래처럼 Content 영역만 사용할 수도 있습니다.
Button btn = new();
btn.Content "확인";
Window win = new();
win.Content = new Grid();
또한 이미 ControlTemplate이 정의되어 있기 때문에,
Xaml에서도 마찬가지로 Content 영역만 신경쓰면 됩니다.
<Window x:Class="Exam.MainWindow.cs" ...>
<Window.Content>
<Grid>
<!-- 윈도우 안 영역 -->
</Grid>
</Window.Content>
</Window>
ContentControl, ItemsControl을 상속받는 모든 컨트롤은 사실 ControlTemplate의 모양(기반)을 시작으로 이루어져 있는 셈이죠.
그리고 Content는 생략할 수 도 있어서 우리가 Window나 UserControl을 생성하면 아래처럼 바로 Grid 등의 UI 컨트롤을 배치시킬 수 있습니다.
(이런 생략 규칙이 Content 개념을 이해하는데 독이 되지 않았나 생각해요…)
<Window x:Class="Exam.MainWindow.cs" ...>
<Grid>
<views:ProfileView/>
</Grid>
</Window>
<Button>
확인
</Button>
그래서 평범해 보이는 Content 속성이 WPF에서는 실로 엄청 중요한 역할을 하고 있죠.
Control 입장에서 봤을 때 ControlTemplate는 필수이고 ContentPresenter는 선택사항입니다. 또 ContentPresenter는 얼마든지 개수를 늘릴 수도 있어요.
가령 Expander는 2개의 ContentPresenter를 가지고 있죠.
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<ControlTemplate TargetType="{x:Type TabItem}">
<StackPanel>
<ContentPresenter ContentSource="Header"/>
<ContentPresenter ContentSource="Content"/>
</StackPanel>
</ContentTemplate>
</Setter>
</Style>
때문에 ContentPresenter를 아래처럼 다양하게 이를 다양하게 사용할 수 있습니다.
<Expander Header="접기">
<!-- 내용 -->
</Expander>
<Expander Header="접기" Content="내용"/>
<Expander>
<Expander.Header>
<CheckBox Content="접기"/>
</Expander.Header>
<Expander.Content>
<DataGrid/>
</Expander.Content>
</Expander>
<Expander HeaderTemplate="{StaticResource MyHeaderStyle}"/>
<DataGrid/>
</Expander>
이처럼 Expander 뿐만 아니라 Window, UserControl, GroupBox, TabControl, TabItem, ComboBox 등등 다양한 컨트롤을 ControlTemplate 을 통해 설계하고 ContentPresenter 또는 ItemsPresenter 영역을 활용해서 가변적인 UI를 만들도록 설계되어 있습니다.
끝으로…
ControlTemplate을 잘 활용한다면 DevExpress 같은 컨트롤을 원하는 방향으로 직접 만들 수 있기 때문에 제 개인적으로는 이 개념이 WPF에서가장 중요한 내용이라고 생각해요.
그리고 ControlTemplate에 익숙해진다면 뭐든 다 만들 수 있고요. 
읽어주셔서 감사합니다.