Property Element 사용 의미
혹시 "Property Element"에 대해 잘 모르시는 분들을 위해 잠시 설명하자면.
보통, 요소의 속성값에 대해서 다음과 같은 식으로 설정하죠.
<TextBox Text="test">
</TextBox>
그런데, 아래와 같이 복잡(?)하게 정의하는 것도 가능합니다.
<TextBox>
<TextBox.Text>
test
</TextBox.Text>
</TextBox>
바로 위와 같이 속성(Property)을 별도로 분리해 내어 하위 Element로 정의하는 것을 "Property Element"라고 부릅니다.
저같은 경우, 처음 페졸드의 책에서 "Property Element"를 보면서, "흠... 뭐 저렇게 복잡하게 사용할 일이 있겠어?"라는 식으로 무시하고 지나갔었습니다. 역시나~~~ 괜히 써 놓은 글이 아니라는 것을 깨닫기에 그리 긴 시간이 걸리지는 않더군요. ^^
Property가 Complex Type인 경우에는 "Property Element" 식으로 정의를 해야하는 경우가 종종 있습니다. 이전에 소개해 드린 아래와 같은 사례가 그 좋은 예이지요.
ConveterParameter로 1개 이상의 값을 전달하고 싶다면?
; http://blogs.msdn.com/permanenttan/archive/2009/06/19/array-as-a-wpf-converterparameter.aspx
이외에도 XAML상에서 컴파일 오류가 발생하는 경우가 종종 있는데, 바로 그런 경우에도 "Property Element" 방식을 사용하면 컴파일 오류를 피할 수 있습니다.
예를 한번 들어볼까요?
"illef" 님의 블로그에서 소개된 "Converter Manager"를 보면,
Converter Manager
; http://illef.tistory.com/entry/Converter-Manager
아래와 같은 내용이 나옵니다.
공통된 Library로 Assembly를 별도로 관리한 다는 의미도 있지만 또 다른 이유는 Microsoft 팀의 버그 때문입니다. 같은 Assembly안에 있으면 MarkUpExtension을 XAML의 Attribute로 설정할 수 없는 버그입니다. (ㅡ.ㅡ)
아쉽게도 illef 님의 글에서 에러 내용은 공개되지 않았지만 아마도 아래와 같은 식일 것으로 추정됩니다.
Unknown property ‘Converter’ for type ‘MS.Internal.Markup.MarkupExtensionParser+UnknownMarkupExtension’ encountered while parsing a Markup Extension.
하나의 프로젝트에서 빌드했는데도 위와 같은 에러가 없는 경우도 있습니다. 저같은 경우에는 다음과 같이 디자이너 화면에서 경고가 발생했습니다.
[그림 1: 디자이너에서 오류 발생]
"No constructor for type 'StaticConverterExtension' has 1 parameters"
다행히 빌드는 되지만, 어쩐지 저런 톱니 모양 밑줄이 그어지는 것이 꺼림직한데요. 바로 이런 경우에 "Property Element"를 사용하면 위와 같은 경고를 피할 수 있습니다.
<Button.Content>
<Binding Path="ButtonTitle">
<Binding.Converter>
<local:StaticConverterExtension Type="{x:Type local:IntToBooleanConverter}" />
</Binding.Converter>
</Binding>
</Button.Content>
***
위의 과정을 테스트한 프로젝트를 첨부해놓았으니 참고하십시오.
이와 관련한 지식을, 이번에 Sibling MarkupExtension을 구현하면서 보게 된 아래의 글에서 알게 되었습니다.
A base class for custom WPF binding markup extensions
; http://www.hardcodet.net/2008/04/wpf-custom-binding-class
위의 내용에서 "Problem: Attribute syntax with resources" 부분을 보면, 아래와 같이 XAML을 사용했는데 컴파일 오류가 발생한다고 합니다.
<TextBox Name="txtZipCode"
Text="{local:LookupExtension Source={StaticResource MyAddress}
Path=ZipCode,
LookupKey=F5}"
/>
그런데, 아래와 같이 "Property Element" 구문으로 사용하면 오류가 안 난다고 하지요.
<TextBox Name="txtZipCode">
<TextBox.Text>
<local:LookupExtension Source="{StaticResource MyAddress}"
Path="ZipCode"
LookupKey="F5" />
</TextBox.Text>
</TextBox>
그러면서, 그와 관련된 내용을 정리한 다음의 글을 소개하고 있습니다.
Custom MarkupExtension && Nested Extensions == Bug
; http://www.hardcodet.net/2008/04/nested-markup-extension-bug
다시, 위의 글에서는 2006년 10월에 씌여진 또 다른 글을 소개해 줍니다.
How should I data bind a Polygon’s Points to a data source? - Part II
; http://www.beacosta.com/blog/?p=36
버그라고는 하지만, 2006년도에 알려진 것이라면 아마도 쉽게 수정되지 않는 문제로 보입니다.
여기서 재미있는 점이 하나 있습니다. ^^ "Property Element"로 이렇게 빌드 오류를 수정할 수 있다고 나오는데요.
이것을 다시 처음에 "illef" 님이 지적한 해결방법으로 보면, 해석을 못하는 그 구문과 엮인 요소를 별도의 DLL로 분리해서 참조하면 역시 "Property Element" 방식으로 정의하지 않아도 정상적으로 빌드가 됩니다. 예를 들어, 위에서 소개한 "
A base class for custom WPF binding markup extensions" 글의 LookupExtension을 별도의 DLL로 분리하면 다음과 같이 Text 속성에 사용해도 빌드 오류가 발생하지 않습니다.
<TextBox Name="txtCityCustom"
Height="23"
HorizontalAlignment="Left"
Margin="109,246,0,0"
VerticalAlignment="Top"
Width="160"
Text="{external:LookupExtension LookupKey=F6,
Path=City,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay,
Converter={StaticResource charConv},
ConverterParameter=*}">
</TextBox>
***
테스트 된 솔루션 파일을 첨부해 놓았으니 참고하십시오.
정리해 보면,
XAML 컴파일 시에 오류가 나는 "올바른 구문"이 있다면 다음과 같은 2가지 방법을 통해서 해결이 가능합니다.
- Property Element 구문을 사용
- 별도의 DLL로 분리해서 사용
[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]