본문 바로가기

Development/WPF

Runtime DynamicResource for DependencyObject Level

Introduction

WPF Application을 개발할때 동적인 리소스를 활용하기 위해 DynamicResource를 이용합니다. 동일한 내용의 리소스를 메모리에 여러번 올리지 않기 때문에, 메모리 효율이나 퍼모먼스면에서 좋은 효과를 낼수 있습니다. 하지만, DynamicResource의 경우 XAML상에서 한번 지정하면(혹은 지정하지 않으면) 런타임상에서 지정이 불가능하기 때문에 당혹스러울 때가 많습니다.

MSDN에서는 이러한 상황을 위해 FrameworkElement수준에서 SetResourceReference를 제공하고 있지만, FrameworkElement가 아닌 DependencyObject 수준에서는 역시나 제어가 불가능 하기 때문에 완전한 해결방법이라고는 할 수 없습니다. 대표적인 예로 Brush의 경우 DependencyObject에서 Freezable, Animatable을 거쳐 파생된 클래스이기 때문에 SetResourceReference를 이용한 Runtime상에서의 DynamicResource를 지정할수 없습니다.

이번시간에는 Runtime상의 DependencyObject 수준에서 DynamicResource를 지정하는 방법에 대해 소개합니다. 위 동영상은 이번시간에 사용되는 데모 동영상입니다.

DynamicResourceExpression

먼저 우리가 XAML에서 DynamicResource를 지정하고 해당 Property에 DynamicResource가 지정되는 과정을 간략하게 표현하면 위 그림과 같이 표현 할 수 있습니다. XAML에서 DynamicResource MarkupExtension을 이용해 DynamicResource를 정의하면 DynamicResourceExtension객체가 생성되고 DynamicResourceExtension의 ProvideValue()를 통해 Dependency Property에 지정 가능한 ResourceReferenceExpression이 생성됩니다. 생성된 Expression은 최종적으로 DependencyObject의 SetValue메서드를 통해 해당 Property에 DynamicResource Reference가 생성되게 됩니다.

DependencyObject에 SetValue를 통해 Expression이 입력되는것을 확인 하고, 직접 ResourceReferenceExpression 객체를 입력하기 위해 ResourceReferenceExpression 생성하려고하면 문제가 발생합니다. ResourceReferenceExpression 가 상속받은 Expression 클래스의 경우 WPF 인프라를 지원하기 위해 제작된 클래스로, 사용자 코드에서 직접 엑세스가 불가능하기 때문입니다.

그럼 한단계 돌아가서 DynamicResourceExtension을 이용해 ResourceReferenceExpression을 생성하는 방법을 이용해 보겠습니다. DynamicResourceExtension의 경우 MarkupExtension을 상속받은 클래스기 때문에 사용자코드에서 생성하고 ProvideValue 메서드 또한 호출이 가능합니다. 아래 코드는 DynamicResourceExtension을 이용해 ResourceReferenceExpression을 생성하고 대상 DependencyObject에 Expression을 지정하는 코드입니다.


일반적으로 ProvideValue를 호출하기 위해 파라미터로 IServiceProvider를 제공해야하지만, 다행히도 DynamicResourceExtension의 경우 내부적으로 IServiceProvider를 제공하지 않더라도 사용가능하기 때문에 파라미터에 null을 입력하는것으로 Expression을 생성할 수 있습니다. 

실제 코드에서 사용할 때에는 위와 같이 ExtensionMethod를 이용해 Behid Code에서 DependencyObject에 DynamicResource를 지정해서 사용할 수 있습니다. 첨부파일은 이번시간에 사용한 데모 프로그램의 소스코드입니다.