WPF Template의 이해


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


답글 남기기

이메일 주소는 공개되지 않습니다.