안녕하세요?
저는 WPF가 처음 나왔을 때부터 사용했는데요, 부끄럽지만 오늘에야 알게 된 내용이 있어 한 번 적어볼까 합니다ㅎ
WPF에서 암시적 키를 가지는 리소스를 정의할 때 Style
과 DataTemplate
의 x:Key
가 어떻게 다르게 적용되는지에 대한 이야기입니다.
Style
리소스의 암시적 키 지정
일반적으로, 컨트롤에 대한 Style
리소스를 정의할 때 x:Key
를 명시적으로 설정하지 않으면 자동으로 TargetType
속성으로 지정된 Type
인스턴스가 키로 설정됩니다.
예를 들어, 버튼에 대한 스타일을 정의할 경우, 다음과 같이 x:Key
를 생략해도 암시적으로 아래와 같은 구문이 추가됩니다.
<Style TargetType="{x:Type Button}">
<!-- ... -->
</Style>
<!-- 컴파일 된 리소스 -->
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<!-- ... -->
</Style>
그리고 해당 스타일을 참조할 때는 다음과 같이 사용할 수 있습니다.
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}"
BasedOn="{StaticResource {x:Type Button}}" />
여기까지는 대부분 알고 계신 내용입니다.
DataTemplate
리소스의 암시적 키 지정
그렇다면 DataTemplate
에서는 암시적 키가 어떻게 작동할까요?
저를 포함한 많은 분들이 Style
과 마찬가지로 DataTemplate
도 자동으로 DataType
속성으로 지정된 형식의 인스턴스가 자동으로 x:Key="{x:Type local:MyType}"
형태로 설정되지 않은까?라고 생각하고 계실 것 같습니다.
공식문서를 살펴봐도 자동으로 지정된다고만 나와 있을 뿐 구체적은 내용은 없습니다.
DataTemplate 클래스에는 Style 클래스의 TargetType 속성과 매우 유사한 DataType 속성이 있습니다. 따라서 위 예제에서 DataTemplate에 대한
x:Key
를 지정하는 대신 다음을 수행할 수 있습니다.…
이 DataTemplate은 모든
Task
개체에 자동으로 적용됩니다. 이 경우x:Key
는 암시적으로 설정됩니다. 따라서 이 DataTemplate에x:Key
값을 할당하면 암시적x:Key
가 재정의되고 DataTemplate이 자동으로 적용되지 않습니다.
심지어 StackOverflow에서도 위 내용처럼 x:Key="{x:Type 형식이름}"
으로 설정된다고 답변하고 있습니다.
하지만 이 답변을 잘못된 답변으로, 실제로는 그렇게 동작하지 않습니다.
예를 들어, MyType
이라는 타입에 대한 DataTemplate
을 다음과 같이 작성했을 때,
<DataTemplate DataType="{x:Type local:MyType}">
<!-- 템플릿 내용 -->
</DataTemplate>
이렇게 정의된 리소스를 참조하기 위해 다음과 같은 코드를 작성하면 오류가 발생합니다.
<ContentControl Content="{Binding MyObject}"
ContentTemplate="{StaticResource {x:Type local:MyType}}"/>
DataTemplateKey
컴파일된 XAML 파일을 리플렉터 툴로 디컴파일 해보면 WPF는 아래와 같은 코드를 생성하는 것을 확인할 수 있습니다.
<DataTemplate x:Key="{DataTemplateKey {x:Type local:MyType}}"
DataType="{x:Type local:MyType}" >
<!-- 템플릿 내용 -->
</DataTemplate>
WPF에서는 DataTemplate
의 x:Key
를 명시적으로 지정하지 않으면, 컴파일러는 위와 같이 자동으로 x:Key="{DataTemplateKey {x:Type local:MyType}}"
구문을
추가해서 DataTemplateKey
형식의 래퍼 객체 인스턴스를 키로 지정합니다.
이제 암시적 키로 정의된 DataTemplate
을 명시적으로 참조하려면 아래와 같이 사용할 수 있습니다.
<ContentControl Content="{Binding MyObject}"
ContentTemplate="{StaticResource {DataTemplateKey {x:Type local:MyType}}}"/>
이상으로 Style
과 DataTemplate
은 리소스의 암시적 키가 어떻게 다르게 설정되는지 알아봤습니다.
혹시나 아직 모르셨던 분들이 계시다면 도움이 됐으면 합니다.
감사합니다ㅎ