안녕하세요.
이번 포스팅에서는 사용자 지정 Attached Property에 대해 이해와, 예제를 다룹니다.

1. 다른건 다 기본 내용을 쓰고싶은데, 이거 하나만 추가하고싶어,,

예를 들어서, ListBox에서 여러개를 선택가능하게 하되, 최대갯수를 제한하고 싶은 경우를 봅시다.
기본의 ListBox에서는 MultiSelect를 할수있게/없게 하는 기능은 있어도, 최대 갯수를 지정할 수는 없습니다.
이를 구현하는데 쉽게 생각할 수 있는 방법은 상속입니다. 부모의 기능은 그대로 사용하고 싶은데, 내것 하나만 추가됬으면 하는 경우 니까요


상속을 이용한 MultiSelectionCount 구현

하지만, 이렇게 구현하게되면 하나의 프로퍼티 때매, 전체를상속 받아야 하며,  새로 구현한 아이만을 사용해서 구현하여야 합니다.
좀 더 효과적으로 구현할 수 있는 방법이 있까요?!
이번 포스팅에서 설명하고하 하는 사용자 지정 Attached property를 사용하면 됩니다.

우선
사용자 지정 Attached property를 설명하기 앞써, 사용자 지정을 뺀 Attached property에 대해 이야기 해봅시다.

2.  Attached property란?
    Attacted Property란 어떤 객체에서든지 설정할 수 있는 global한 속성입니다. 
    보통의 경우 부모요소에 포함된 값을 부모가 직접 지정할 수는 없고,  자식요소가 지정해야할 경우에 사용할 수 있도록 해줍니다.
    그러기 위해서  global하게 구현이 되어 있고요.   
    먼가 말로 표현하니 어렵게 느껴지는데요, 평소에 많이 사용하던 Property로 예제를 보면 무릎을 탁 치시게 될꺼에요.


평소에도 많이 사용하는 Attatced Property.  (DockPanel.Dock)
  
즉, 여기서 DockPanel.Dock속성은 부모인 DockPanel에서 정할 수 있는 것이 아니라,
DockPanel안에 포함되는 자식 요소에서 설정되어야 하기 때문에, DockPanel 클래스 안에서는 DockProeperty를 static Dependency Property로 만든 다음 GetDock과 SetDock Metheod를 public으로 제공합니다.



바로 이게 정의는 내가하나, 남들이 정의해서 써야할때-_-!! 사용하는 것이 Attached Property입니다. 
평소에도 사용하시면서 보셨거죠?
 
자 , 그럼 본론으로 들어가 봅시다.

3.  사용자 지정 Attacted Property란?

 위에서 구현하고자 했었던 ListBox에서 여러개를 선택가능하게 하되, 최대갯수를 제한하려고 해 봅시다.
 바로 이 Attacted Property를 이용해서 말이지요. 

 다음과 같이 구현하면 됩니다.


사용자 정의 Atteched Property를 사용할 경우

* 10원 팁 : 아래와 같이 propa를 치게되면 인텔리센스가 적당히 atteched Property를 생성하는것을 도와줍니다.




4. 사용을 해보자.

xaml에서 그럼 실제로 구현한 내용을 적용해 봅시다.


사용자 정의 Attacted Property를 사용할 경우 vs ListBox를 상속받아 구현할 경우 사용

* 별첨


C#코드에서 사용자 정의 Property를 사용하는 방법

어찌보면 extention method 와 비슷하다고 보실 수 있네요.

전체 예제는 아래에 첨부합니다.




저작자 표시

코디네이터 베타로 구현한 WPF, Silverlight UI Theme 디자인.
모든 기본 UI 콘트롤에 적용 가능합니다.


안녕하세요? witstudio의 김대욱입니다. 그동안 동영상등으로만 몇번 소개드린바 있던 WPF UI테마 엔진인 Codinator(코디네이터)가 드디어 베타서비스를 시작 하였습니다. UI개발 & 디자인을 효율적으로 진행 할 수 있는 방법에 대해 많은 시간을 고민한 끝에 제작된 Codinator는 UI테마를 통해 간단한 조작만으로 다양한 Look & Feel를 선택하고 원하는 형태로 수정이 가능한 제품입니다. 현재 베타 서비스는 아래와 같이 진행되고 있으니 많은 관심 부탁드리겠습니다.


[Codinator Closed Beta 서비스 안내]

기간 : 2010년 12월 4일 ~ 2011년 1월 30일(예정)
대상 : WPF 기술을 사용하는 개발자 & 디자이너
사용환경 : Visual Studio 2010 또는 Expression Blend 4, .NetFramework 4이상
신청방법 : service@codinator.net으로 이름,소속,연락처,사용목적등을 간단하게 작성하여 참여 신청 메일을 보내주시면됩니다.


Codinator는 기존 개발자, 디자이너가 쉽게 제품에 적응 하고 사용할 수 있도록 Visual Studio와 Expression Blend에서 플러그인 형태로 동작하게 되며 현재 Codinator Beta에서 제공되고 있는 기능은 아래와 같습니다. 

테마 선택하기

테마 선택하기는 미리 제작된 테마(Style과 Template의 묶음)를 간단하게 선택해 반영 해 볼 수 있는 기능으로 현재 베타버전에서는 총 4개의 테마(BlueCity, GodFather, Aquarium, ConcreteBlock)를 제공하고 있으며 각각 테마에는 Button, ListBox, TextBox, TabControl, Panel에 대한 테마가 정의되어 있습니다. 정식버전에서는 모든 종류의 기본컨트롤을 지원할 계획에 있으며 자신이 직접 제작한 테마도 적용 할 수 있습니다.

스타일 선택하기

테마에서는 각 요소마다 한개 이상의 스타일을 가질 수 있습니다. 만약 요소에 대한 기본 스타일이 정의 되어 있는 경우에는 테마를 선택할 때 기본스타일이 반영이 되지만, 기본 스타일이 없거나 다른 스타일을 선택하고자 할때에는 직접 스타일을 선택하여 적용할 수 있습니다.

컬러 수정하기(Color Wheel)

Codinator에서는 Color Wheel을 이용해 디자이너가 아니라도 쉽게 테마의 전체적 분위기를 변경 해 볼 수 있습니다. ColorWheel을 이용하면 테마에서 사용된 색들간의 비율을 유지하면서 색을 변경해 주기 때문에 손쉽게 자연스러운 색으로 변환 할 수 있습니다. 색을 변경할때에는 반영된 결과가 Designer View에 실시간으로 보여지기 때문에 쉽게 원하는 느낌으로 찾아갈 수 있습니다.

컬러 수정하기(Detail)

ColorWheel을 이용한 컬러 수정이 간단하게 전체적인 분위기를 바꾸는 작업이었다면, 이번에는 각각 요소에 대한 색을 디테일하게 변경해 보도록 하겠습니다. 검색 영역에 수정할 요소의 이름을 입력하면 해당 요소가 사용하는 브러시의 목록이 나타나게 되며 여기서 각 요소에 대한 디테일한 수정이 가능합니다.

리소스 저장 및 불러오기

ColorWheel과 Detail Editor를 이용한 리소스는 결과를 저장하거나 불러올 수 있습니다. 이를 활용하면 다양한 리소스 목록을 이용해 한번작업해놓은 결과물을 수시로 바꿔가며 반영해 볼 수 있고, 동료 개발자/디자이너와 공유하기도 쉽습니다.

색맹/색약 시뮬레이션

세계적으로 전체 인구의 약 10%가 색맹 또는 색약을 가지고 있다고 합니다. Codinator에서는 여러분께서 선택하고 수정하신 테마가 이들에게 어떻게 보여지는지를 시뮬레이션 하고 이를 보고 색을 보정 할 수 있는 기능을 제공함으로 써 더 많은 사용자에게 편리한 UX를 제공 할 수 있도록 돕습니다.

이상으로 현재 Codinator Beta에서 제공되고 있는 기능에 대한 소개를 마치며 혹시 더 궁금하신점이나 베타 참여, 피드백, 기타 문의 사항은 언제든지 저에게 또는 service@codinator.net 으로 연락주시면 감사하겠습니다. 아직 부족한점이 많은 제품이지만 관심 가져 주셔서 감사드리며 앞으로 더 나은 제품을 만들기 위해 노력하고 끝까지 최선을 다하겠습니다. 많은 관심과 응원부탁드리겠습니다.

감사합니다!!

Introduction

이번시간에는 WPF에서 사용할 수 있는 Gradient Editor를 구현하는 방법에 대해 소개합니다. 아래 동영상은 이번시간에 구현하게 될 GradientEditor의 데모 동영상으로 Expression Blend와 유사한 형식으로 Gradient를 편집할 수 있습니다. 

Create Gradient Editor Control

먼저 Linear Gradient를 표현하기 위해서 아래와 같이 기본적인 속성들을 선언합니다. 각요소를 표현하기 위해 DrawingVisual을 이용 할 예정이기 때문에 FrameworkElement를 상속받아 VisualCollection를 선언한 뒤 VisualChildrenCount와 GetVisualChild를 재정의 합니다.


그리고 DrawingVisual을 이용해 Linear Gradient의 방향성을 표현하기 위한 Header, Tail의 Visual을 구현하고 VisualCollection에 등록합니다. GradientStopVisuals는 GradientStop과 Visual객체를 매핑 하기 위한 도구로 GradientStop이 추가되거나 삭제 또는 상태가 변경되었을때 GradientStop을 이용해 대상 Visual객체에 접근할 수 있도록 Dictionary형태로 관리합니다.


위에서 생성한 Visual객체들은 모양과 크기 정도만 정의가 되어 있는 상태이기 때문에 데이터가 들어 왔을때 정확한 위치에 출력 되진 않습니다. 따라서 정확한 위치에 출력 될 수 있도록 ArrangeOverride메서드를 재정의 하여 각 요소의 위치를 바로잡는 과정을 수행합니다.

이외에 몇가지 추가기능(마우스 제어 등)을 구현이 필요하지만 포스팅에 올리기에는 많은양의 소스코드라 나머지 부분에 대해서는 첨부파일을 확인 해주시기 바랍니다. 아래는 이번시간에 사용된 전체 소스코드 입니다. 기타 궁금하신점이나 문의사항은 이메일이나 댓글로 올려주시면 답변드리도록 하겠습니다.


Introduction

WPF를 이용해 MVVM패턴으로 개발할때, ViewModel에서 View에 있는 객체에 Binding을 해야 할경우, ViewModel에서 View에 있는 객체를 직접 Access해야 하므로, View와 ViewModel의 독립성이 떨어지게 됩니다. 이번시간에는 이러한 상황에서 MarkupExtension을 이용해 View에서 ViewModel의 독립성을 유지한체 ViewModel에서 View를 Binding할 수 있도록 하는 ReverseBinding을 구현 하는 방법에 대해 소개합니다.

Create DemoView(Default Data Binding)

ReverseBinding를 구현하기에 앞서 ReverseBinding을 테스트 하기 위한 상황을 만들기 위해 위와 같이 두개의 RadioButton이 있는 간단한 DemoView를 구현했습니다. 그리고 RadioButton에 ViewModel에 정의된 IsMale속성을 Binding하고, 텍스트 박스에도 IsMale 속성을 Binding합니다. 아래는 DemoView에 해당하는 소스코드입니다.


대충 눈으로 살펴봤을때는 특별하게 문제가 없는 코드 같지만, 실제로 동작을 시켜보면 동영상과 같이 DataBinding이 정상적으로 동작하지 않는것을 확인 하실 수 있습니다.
 
이유는 RadioButton의 특성상 IsChecked 속성이 변경될때 같은 Group내에 포함된 다른 RadioButton들의 IsChecked속성이 영향을 받게되는데, 이 과정에서 Binding되어있던 IsChecked속성에 다른 값이 덮여 씌워지면서  Binding이 해제되어 버리기 때문입니다.
 
이를 해결하기 위한 RadioButton에 Binding을 하지 않고, 아래와 같이 IsMale속성에 RadioButton의 IsChecked속성을 Binding하는 방법을 사용 할 수 있습니다.
하지만 위에서 언급 했듯이 ViewModel에서 View 객체를 멤버를 직접 제어하는 방법은 독립성이 떨어지기 때문에 View와 ViewModel에 종속받지 않고 위와 같은 동작을 수행하는 ReverseBinding을 직접 구현해서 사용 할 수 있습니다.

Create ReverseBinding Extension

아래는 ReverseBinding을 구현한 소스코드의 일부분으로, 요약하면 Binding객체를 파라미터로 받는 MarkupExtension을 생성하고, ProvideValueTarget을 이용해 Source Object와 Source Property를 가져온 뒤, DataContext의 Target Property에 Binding을 수행하는 과정을 나타냅니다.
위와 같이 구현된 ReverseBinding을 이용해 실제 XAML에서 사용할 때에는 아래와 같이 사용할 수 있습니다.


실행시켜보면 아래 동영상과 같이 Binding이 정상적으로 동작하는것을 확인 하실 수 있습니다.


아래는 이번시간에 사용된 전체소스코드입니다. 혹시 글을 읽으시고 이해가 안되시는 부분이나, 기타 문의사항은 댓글이나 이메일로 남겨주시면 답변드리도록 하겠습니다.