Template에 대해서 간단히 포스팅 합니다.
<Button Height=”100″ >
<TextBlock Height=”Test”></TextBlock>
</Button>
XamlReader는 위 XAML 코드를 아래와 같은 코드로 번역할 것입니다.
Button button = new Button { Height = 100 };
button.Content = new TextBlock { Text = “Test”
Button과 TextBlock의 실제 Instance를 내부에서 실제로 ‘생성’하게 되는 것이죠. 하지만 Template의 경우는 이와 완전히 다릅니다.
<Button Height=”100″ >
<Button.ContentTemplate>
<DataTemplate>
<StackPanel Orientation=”Horizontal”>
<TextBlock Text=”Content : “/>
<ContentControl Content=”{Binding }”/>
</StackPanel>
</DataTemplate>
</Button.ContentTemplate>
<TextBlock>Test</TextBlock>
</Button>
그리고 이 포스트를 더 읽지 마시고, 잠깐 저 XAML을 코드로 나타내면 어떻게 될 지 생각 해봅시다.
혹시 아래와 같다고 생각하셨나요?
Button button = new Button { Height = 100 };
DataTemplate template = new DataTemplate();
StackPanel stackPanel = new StackPanel { Orientation = Orientation.Horizontal };
stackPanel.Children.Add(new TextBlock { Text = “Content : “ });
stackPanel.Children.Add(new ContentControl { Content = new Binding() });
template.Content = stackPanel;
button.ContentTemplate = template;
button.Content = new TextBlock { Text = “Test” };
하지만 재미있게도 Template의 경우는 위와 같은 코드로 번역되지 않습니다. 왜냐면 Template – 한국말로 ‘틀’ – 이기 때문입니다. Template의 목적은 하나의 단일 Object Tree를 생성하기 위한 것이 아니라 Object Tree를 만들어내는 ‘틀’을 만드는 것에 있기 때문입니다. 긴말하지 않고 위 XAML이 어떻게 번역되는지 코드로 알려드립니다.
Button button = new Button { Height = 100 };
FrameworkElementFactory stackPanelFactory = new FrameworkElementFactory(typeof(StackPanel));
stackPanelFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
FrameworkElementFactory textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
textBlockFactory.SetValue(TextBlock.TextProperty, “Content : “);
FrameworkElementFactory contentControlFactory = new FrameworkElementFactory(typeof(ContentControl));
textBlockFactory.SetBinding(ContentControl.ContentProperty, new Binding());
stackPanelFactory.AppendChild(textBlockFactory);
stackPanelFactory.AppendChild(contentControlFactory);
DataTemplate template = new DataTemplate();
template.VisualTree = stackPanelFactory;
button.ContentTemplate = template;
button.Content = new TextBlock { Text = “Test” };
재미있지요? 실제 Object를 생성하는 것이 아니라 FrameworkElementFactory라는 녀석을 사용하고 있습니다. 즉, Template는 이 녀석을 사용해서 자신의 ‘틀’의 모양을 구성하고 이 틀을 사용해서 자신의 틀과 일치하는 Object Tree을 마구 마구 찍어 낼 수 있는 겁니다.
//위의 코드에 계속해서..
template.Seal();
object obj1 = template.LoadContent();
object obj2 = template.LoadContent();
bool isSame = obj1 == obj2;
자, 간단한 퀴즈가 나갑니다. 위 코드가 실행되면 isSame이라는 변수에는 어떤 값이 들어갈까요?
예 맞습니다. ‘false’가 들어갑니다. LoadContent()라는 메소드가 ‘너의 틀을 이용해서 Object Tree를 찍어내라!’라는 명령을 수행하기 때문입니다. 따라서 ob1과 obj2는 전혀 다른 객체입니다.