본문 바로가기

Coding Note

[WPF] Properties


WPF에서 중요한 KeyPoint는 엘리먼트의 Property들을 어떻게 표현하냐는 것이다.
(태그에선 attribute라고 하지만,, WPF에선 attribute의 의미와 함께 property의 의미도 가지고 있다. 내 생각엔 property 가 WPF에선 더 어울리는 것 같다.  아마도 그래서 property인듯?..  뭐.. 한글론 전부 '속성'  이지만 하하..)

우선 property를 어떻게 표현하는지 보다 property 자체에 대한 간략한 이해가 필요하다.
WPF의 property는 세가지의 중요한 개념을 바탕으로 만들어졌는데, 그 세가지는 DependencyObject, DependencyProperty, DependencyMetadata이다. 이 중 DependencyProperty가 property의 핵심이니, 이놈에 대해 조금 알아보자.
(이부분은 나도 정확히 이해하지 못했다,, 그냥 이사람은 이렇게 생각하는군. 정도로만 봐주시길^^;)

▷ DependencyProperty(의존속성, 종속속성)
: WPF의 property에서 가장 핵심적이고 큰 개념이다. 의존속성이란 어떤 속성이 의존하고있는(종속되어있는) 속성의 모체.. 같은거라고 이해하면 될 듯 하다. 그리고 WPF의 property들은 이 의존속성을 바탕으로 구성되어있다. 때문에 XAML파서도 property에 대한 값을 평가할 때 그 속성의 의존속성에 등록된 정보를 가지고 평가하게된다.
 의존속성을 이해하는건 굉쟝히 중요한데, 이게 개념을 이해하고 마는 수준이 아니라 필요에 따라 새로운 속성을 만들어야 할 때에 의존속성을 바탕으로 원하는 속성을 정의하기 때문이다.
 기존의 방식을 보면, 새로운 속성을 가지는 컨트롤을 만드려면, 기존의 컨트롤을 상속받는 나만의 컨트롤을 만들고, 속성을 추가시켜주면 됬었다. 오히려 의존속성이니 뭐니 머리하파지는것 보다 간단해보인다. 하지만, 속성의 변화에 대한 처리나 속성 자체의 행동에 대한 처리의 책임은 새로운 컨트롤을 만든 당사자에게 고스란히 돌아온다. 유동적인 UI를 지원하는 WPF 윈도우에선 속성 하나의 변화에도 민감하게 반응하는데,, 이런걸 전부 만들어줘야 한다면 결국 WPF 프로그래밍의 결과물은 기존 Form프로그램과 큰 차이가 없을것이다.(귀찮고 힘드니깐 =ㅅ=..)
 그런데 WPF의 의존속성을 이용하면, 기존속성이 갖는 Metadata를 함께 포함하는 속성을 만들 수 있고, 이 말은 속성에 대한 부가적인 처리는 신경 쓸 필요가 없다는 의미이다. 나중에 애니메이션이나 컨트롤에대한 템플릿을 구성할 때 자주보게 될 것 같다.

나머지는.. 
 DependencyObject : DependencyProperty를 가지는 객체이고 대부분의 UI Control들은 이 클래스를 상속받아 구현되어있다. 뜯어보면, 하는일은 속성값에 대한 처리를 담당하고있고 중요한 역할로 SetValue와 GetValue를 정의하고 있다.
 DependencyMetadata : DependencyProperty의 한 부분으로, Owner 정보에 대한 정보이다.
정도로만 알면 될 듯 하다.
(DependencyProperty의 자세한 개념과 활용은 다음기회에 천천히 알아보자..)

그럼 본론으로!  property를 표현하는 방법엔 3가지 정도가 있다. 하나하나 살펴보고 이번 글은 마쳐야겠다.
1. XML attribute : XML에서 attribute를 표현하는것과 같은방식이다. <Element property="value" />  와 같이 표현하고, 복잡하지 않은 property를 표현할 때 편하게 사용할 수 있다.

2. Property-element : 사실 WPF의 엘리먼트는 Class이다. 그리고 엘리먼트의 property또한 클래스일 수 있고, 클래스는 멤버변수를 여럿 가질 수 있다. 그런데 XML attribute 방식만으론 복잡한 property에 대한 표현을 하기가 쉽지않다. 그런 연유로 나온것이 Property-element Syntax!
 이 방법은 엘리먼트에 대한 property또한 엘리먼트태그로써 구분해서 그 속에 존재하는 다른 property에 접근할 수 있게 해준다. 백문이 불여일견, Button으로 예를들어보자. Button에는 Background라는 property가 있다. 얘는 Brush클래스 property이기 때문에 Color값을 가지는 Brush를 참조하도록 하면 된다. XAML태그에선 
             <Button Background="Red" />
와 같이 쓰면 되고, 이는 
            Button b = new Button { Background = new SolidColorBrush(Colors.Red)};
와 같은 의미를 가진다. 그런데 Background의 참조값으로 주어진 SolidColorBrush는 Brush를 상속받는 클래스이다. 비슷하게 Brush를 상속받는 LinearGradientBrush도 Background의 참조값이 될 수 있다. 어라? 그런데 Background="Red"라고 하면 Brushes.Red 로 인식이되고 이는 SolidColorBrush클래스인데 어떻게 LinearGradientBrush값을 참조하도록 할까? 게다가 LinearGradientBrush는 GradientStopCollection에 또다시 새로운 객체들을 가져야한다. 아무래도 기존 XML attribute만으론 표현하기가 너무 힘들다. 이를 해결하기 위해서 Property-element syntax로 property들을 표현해보자.
             <Button>
                <Button.Background>
                    <LinearGradientBrush>
                        <GradientStop Offset="0" Color="Blue"/>
                        <GradientStop Offset="1" Color="Red" />
                    </LinearGradientBrush>
                </Button.Background>
            </Button>
이런식으로 Button의 Button.Background property를 다시 엘리먼트로 하여 이녀석의 값을 태그내에 위치하게 하는 방식이다. 이렇게 한다면 복잡한 property에 대한 표현도 쉽게 할 수 있겠다.

3. Markup Extension : 위에서 설명한 두 개의 방법으로도 대부분의 property표현이 가능한 듯 하다. 하지만 중요한 한가지가 있으니,, 위에서 설명한 두 가지는 property에 대한 값을 표현하는 방식이 생성에 있다는 것이다. 무언가 property에 대한 값을 참조하려고 하면, 참조되는 값은 언제나 new 연산자를 통해 동적으로 생성되게 된다.
 그런데 어플리케이션을 만들다보면 기존에 있던 리소스를 참조할 필요가 생긴다. 이럴때 위의 두 가지 방식으론 해결할 수가 없다. code-behind에서 하드하게 코딩을 해주면 되겠지만, 기껏 디자인과 코드를 분리시켜놨는데 다시 엮어놓으란 말인가!  어불성설이지. 이런 문제를 해결하기 위해서 고민에 고민을 거듭한 개발자들은 기존 XML을 확장시키기로 했고, 태어난것이 Markup Extension이다.
 Markup Extension은 기존에 있는 리소스의 참조나 파라미터가 있는 생성자를 가지는 객체를 만들 수 있게 하는 등 많은 변화를 가능하게 했다. 특히나 data binding시에 많이 쓰인다고 ms는 설명하고있다. 
 간단하게 markup extension의 문법만 살펴보고 넘어가도록 하자. 얘는 property에 대응되는 값으로 { } 사이에 표현식을 써서 주게된다.
             <Element property="{  expression }"   ...  />
이때 들어가는 표현식은 { 형태 키=값 }... 처럼 표현을 한다.  사실 markup extension은 응용이 무궁무진해서 간단하게 끝낼 문제는 아니다. 하지만 긴 설명보단 앞으로 나올 예제들에서 어떤식으로 사용되는지 익숙해져가는게 더 낳은 것 같다고 생각해서 이쯤에서 끝내기로 하자.

지금까지 설명한 property표현은 모두 XAML문서 내에서 사용되는 방식이다. 만약 디자인 분리고 뭐고 내식대로 하겠다.. 라거나 property에 관한 WPF의 내부구현이 궁금하면 XAML없이 code-behind만으로 표현해보는것도 도움이 많이될 것 같다. 물론 이러려면 리플렉터와 msdn을 옆에끼고 봐야겠지 ㅎ..

'Coding Note' 카테고리의 다른 글

[WPF] Dependency Property  (0) 2012.01.21
[WPF] Layout  (2) 2012.01.20
[WPF] about XAML  (0) 2012.01.19
[WPF] 첫번째 프로그램  (0) 2012.01.16
[WPF] WPF 시작하기  (1) 2012.01.16