ContentControl은 아주 유용한 Control이면서 아주 기본적인 Control입니다. 우리가 알고 있는 대부분의 Control이 ContentControl을 상속받고 있죠. 일단 모든 Button류가 상속하고 있고 ListBoxItem등도 상속하고 있는 클래스입니다.
그럼 이것이 도데체 어떤 컨트롤인지 알아보기 위해 한번 화면에 뿌려보도록 하겠습니다.
다음처럼 간단한 코드를 Xaml에 추가해보죠..
화면에 단순히 "This is a ContentControl!!" 이라고 뿌려지는 것을 볼 수 있을 겁니다.
뭐야... 그냥 TextBlock 인거야?... 하지만 다음과 같은 코드를 뿌려보면 단번에 뭐하는 녀석인지 알 수 있습니다.
<ContentControl.Content>
<Ellipse Width="50" Height="50" Fill="Purple"/>
</ContentControl.Content>
</ContentControl>
결과는 단순히 보라색 동그라미가 화면에 뿌려지는 것일 겁니다. (여기서 ContentControl.Content 태그는 생략해도 상관없습니다.)
아하 그러면 결국 이놈은 그냥 Content를 표시해주는 역활을 해주는 것이군요...
사실 좀더 세부적으로 어떻게 구현되는 가를 살펴보기 위해 ContentControl의 Template을 살펴보도록 하죠.
<ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Cursor="{TemplateBinding Cursor}" Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
여러가지 속성들이 TemplateBinding 되어있는데 이런 속성들은 그냥 ContentControl의 속성을 ContentPresenter에 셋팅시켜주는 것일 뿐이고 결국은 내부적으로 ContentPresenter만 달랑 들어있는 형상이네요.
그럼 이 ContentPresenter 란 놈은 무슨 일을 하는지 알아봐야 겠죠. 아쉽게도 ContentPresenter는 Template도 없고 더 뜯어볼 코드도 없습니다.
예전 beta1때 공개되었던 코드를 참고하자면 다음과 같습니다. (현재의 CotentPresenter와 다른 점이 있을 수 있습니다. 일단 Text관련 Property들이 대부분 사라졌습니다. 현재는 ContentPresenter에 Content와 ContentTemplate 두가지 속성만이 있습니다. )
코드를 살펴보면 다음과 같은 DefaultTemplate을 가지고 있는 것을 알 수 있습니다.
"<ControlTemplate " +
"xmlns=\"http://schemas.microsoft.com/client/2007\" " +
"xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" " +
"xmlns:controls=\"clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls\" " +
"TargetType=\"controls:ContentPresenter\">" +
"<Grid x:Name=\"RootElement\" " +
"Background=\"{TemplateBinding Background}\" " +
"Cursor=\"{TemplateBinding Cursor}\">" +
"<TextBlock x:Name=\"TextElement\" " +
"FontFamily=\"{TemplateBinding FontFamily}\" " +
"FontSize=\"{TemplateBinding FontSize}\" " +
"FontStretch=\"{TemplateBinding FontStretch}\" " +
"FontStyle=\"{TemplateBinding FontStyle}\" " +
"FontWeight=\"{TemplateBinding FontWeight}\" " +
"Foreground=\"{TemplateBinding Foreground}\" " +
"HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" " +
"Padding=\"{TemplateBinding Padding}\" " +
"TextAlignment=\"{TemplateBinding TextAlignment}\" " +
"TextDecorations=\"{TemplateBinding TextDecorations}\" " +
"TextWrapping=\"{TemplateBinding TextWrapping}\" " +
"VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" " +
"Visibility=\"Collapsed\" />" +
"</Grid>" +
"</ControlTemplate>";
간단히 Grid 안에 TextBlock 하나 있는 그런 Template인 거죠.
내부적인 구현을 보면 Content와 ContentTemplate Property Change 시 마다 자신의 DataContext에 Content나 ContentTemplate을 엮어준 후 PrepareContentPresenter라는 메소드를 호출해줍니다. 여기서 PrepareContentPresenter 라는 메소드에서는 다음과 같은 작업을 수행합니다.
- 먼저 Default Template을 통해 들어있던 객체를 Grid로부터 제거 합니다.
- 그리고 새로 받은 Template이 있으면 Template을 Content에 UIElement가 있으면 Content를 엘리먼트에 집어넣어줍니다.
- 새로 셋팅된 Template도 없고 Content가 UIElement도 아닌 경우 Default Template에 있던 TextBlock의 Text값에 Content를 ToString 해서 넣어줍니다.
결국 ContentPresenter는 단순한 PlaceHolder 역활을 해준다는 것입니다. 여기서 한가지 알아보지 않은 것이 ContentTemplate 인데 ContentPresenter에 새로운 Template을 넣어준다고 생각하면 쉬울 것같습니다. 다음과 같은 코드를 실행해 보죠.
<ContentControl Content="This is a ContentControl!!!">
<ContentControl.ContentTemplate>
<DataTemplate>
<Grid>
<Ellipse Width="200" Height="50" Fill="LightSteelBlue"/>
<TextBlock Text="{Binding }" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
<ContentControl.ContentTemplate>
<DataTemplate>
<Grid>
<Ellipse Width="200" Height="50" Fill="LightSteelBlue"/>
<TextBlock Text="{Binding Tag}" />
</Grid>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
{
public Page()
{
InitializeComponent();
contentControl.Content = new TestData() { Tag = "This is a ContentControl!!!" };
}
}
public class TestData
{
public string Tag { get; set; }
}
'Programming > WPF' 카테고리의 다른 글
Control Lifecycle (0) | 2015.03.11 |
---|---|
Custom Numeric Format Strings (0) | 2015.02.07 |
TextBox.OnTextChanged 에서 발생하는 예외 처리 (0) | 2015.02.05 |
WPF 데이터 바인딩 시의 예외 처리 방법 (0) | 2015.02.05 |
How to bind multiple values to a single WPF TextBlock? (0) | 2015.02.05 |