WPF Template의 이해

프로그래밍 2010.02.09 19:30 Posted by 아일레프

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는 전혀 다른 객체입니다.

저작자 표시
신고