'MarkupExtension'에 해당되는 글 3건

  1. 2013.08.09 WPF Method Binding Extension for MVVM
  2. 2013.03.19 WPF StaticMethod Markup Extension
  3. 2013.02.28 ValueSelector MarkupExtension

Introduction

WPF를 이용해 MVVM패턴으로 개발할때 데이터는 DataBinding을 사용자 입력은 Command를 사용해 View와 ViewModel을 느슨하게 연결합니다. 이것만으로도 충분히 디자인 코드와 로직 코드를 효과적으로 나눌 수 있기 때문에 많이 사용되고 있지만 Command로는 처리하기 까다롭거나 Command를 제공하지 않고 이벤트로만 제공되는 기능을 처리할 때(ex. MouseEvent, SelectionEvent 등)는 View와 ViewModel의 경계가 모호해져 완벽한 분리를 하기가 어렵습니다.

(Trigger와 Action을 이용해 일부 EventTrigger와 InvokeCommandAction을 통해 Event를 Command로 전달 할 수 있지만, 각 Event에 대해 모두 Command를 만들어 줘야 하고 파라미터에 대한 정보 또한 전달 할 수 없기에 이방법은 이번시간에서는 다루지 않습니다.)

이번시간에는 MVVM으로 개발 할 때 ViewModel에 구현되어있는 Method를 Event, Command, Property에 바인딩 할 수 있는 MethodBinding을 구현하는 방법에 대해 소개합니다.

MethodBinding

MethodBinding과 DataBinding의 가장큰 차이점은 바인딩 하는 대상이 다릅니다. DataBinding은 Source객체의 Property를 바인딩하지만 MethodBinding은 Method를 바인딩 합니다. 또 전용 Provider를 통해 Method를 전달 해 주기 때문에 Target객체의 속성이 Delegate Property가 아닌 Event, Command형태로 있다하더라도 대응이 가능합니다.

아래와 같이 ViewModel이 정의되어있다라고 했을때

MethodBinding의 적용하면 아래와 같이 사용할 수 있습니다.
그리고 ViewModel은 아래와 같이 구성되었습니다.

Create MethodBindingExtension

MethodBinding은 크게 3가지 파트로 나뉘며 각 파트별 설명은 아래와 같습니다.

  1. MethodBinding Extension : MarkupExtension으로 MethodBindingProvider의 Proxy Method를 생성
  2. MethodBindingProvider : 대상 객체의 DataContext로부터 Method Path를 추출하여 메서드를 호스팅
  3. CommandProvider : 대상 Property가 Command형식 일경우 Method를 Command로 감싸는 역할

아래는 MethodBindingExtension의 MethodBindingProvider를 생성하고 ProxyMethod를 구현하는 코드입니다.

대상 Property의 Handler Type을 추출하고 HandlerType의 Parameter들을 object[] 파라미터로 변환한 뒤 MethodProviderHandler를 호출 하는 LamdaExpression을  생성합니다. 동적으로 Handler Type에 대한 Proxy Method를 다양한 형태의 Delegate를 처리 할 수 있습니다.

아래는 이번시간에 구현한 MethodBinding의 전체 소스코드이며 기타 궁금하신 점이나 문의 사항은 메일이나 댓글로 남겨주시면 답변드리겠습니다.

WIT.WPF.MethodBindingExample.zip

신고

 

Introduction

WPF에서는 효율적인 XAML개발을 위해 여러가지 MarkupExtension을 제공합니다. Binding이나 StaticResource, DynamicResource가 대표적인 인데요. 기본적으로 제공되지 않는 기능의 경우 직접 MarkupExtension을 개발 할 수도 있습니다. 이번시간에는 XAML단에서 Static Method에 접근이 필요한 경우를 위해 StaticMethod MarkupExtension을 구현하는 방법에 대해 소개합니다.

Create StaticMethodExtension


StaticMethodExtension의 구조는 WPF에서 제공되는 StaticExtension과 유사합니다. 다른점은 Member에 해당하는 부분이 Method로 대체되고 Reflection을 통해 Static Member에 접근하는 대신 Static Method에 접근하는 점 입니다. IXamlTypeResolver와 IProvideValueTarget를 통해 사용자가 입력한 Path에 대한 MethodInfo를 가져오고 Delegate.CreateDelegate를 통해 StaticMethod의 Delegate를 제공해주는 방식으로 구성됩니다.

아래와 같이 C#코드에 Static메서드를 정의한 뒤

XAML코드에서는 아래와 MarkupExtension을 사용할 수 있습니다.

이상이며, 기타 궁금하신 점있으시면 댓글달아주시면 답변드리겠습니다.

신고

Introduction

WPF에서 Binding결과값을 다른 값으로 변환하기 위해 Converter를 사용합니다. 일반적으로 Converter를 구현하기 위해 개발자는 IValueConverter를 상속받은 객체를 구현하고 리소스로 등록하여  사용합니다. 아래 코드는 ValueConverter를 이용해 Slider의 Value에 따라 TextBlock의 FontSize를 변환하는 샘플 코드입니다.


그런데 필요에 따라 Converter를 매번 구현하게 되면  필요 이상으로 Converter를 위한 Type 이 너무 많아지는 상황이 발생합니다. 이렇게 되면 Converter의 경우 XAML코드가 아니기 때문에 관리상으로도 어려움을 격게 됩니다.  이번시간에는 단순한 값 변환을 위해 ValueConverter를 이용하지 않고 XAML코드에서 처리가능하도록 하는 MarkupExtension을 구현하는 방법에 대해 소개합니다.

Create ValueSelectorExtension

ValueSelectorExtension을 구현하기 위해서 먼저 MarkupExtension 형식의 객체를 구현해야합니다. 이때 ValueSelector의 기준이 되는 값이 Binding결과가 될거기 때문에 간단히 Binding객체를 상속받고 ValueConverter또한 상속받는 구조로 아래와 같이 정의합니다.

ValueSelectorExtension은 Selector들을 통해 현재 값에 대한 Converter를 유동적으로 선택 할 수 있고 매칭되는 Selector를 통해 값을 변환 해주게 됩니다. 이제 여러가지 상황을 대응 할 수 있는 Selector만 임의로 구현하면 되는데요, Selector를 구현 할 때는 아래와 같이 구현 할 수 있습니다.

RangeSelector는 사용자가 입력한 범위에 따라 결과값을 지정해 줄 수 있습니다.  위와 같이 Selector를 구현하고 실제 XAML에서 사용할 때에는 아래와 같이 사용할 수 있습니다.


RangeSelector이외에도 용도에 맞게 BooleanSelector, TypeSelector 등을 구현한다면 많은 상황에 대응할 수 있는 Converter를 매번 만들지 않고도 대응 할 수 있습니다.  이상으로 이번 포스팅을 마치며 아래 첨부파일은 ValueSelectorExtension예제 파일입니다. 기타 궁금하신 점이나 문의사항은 이메일이나 댓글로 남겨주시면 답변드리도록 하겠습니다. 감사합니다.

WIT.WPF.ValueSelectorExample.zip

신고