팁/트릭 : 실버라이트와 WPF 사용자 정의 컨트롤 만들고 사용하기

번역/ScottGu's Blog 2008. 4. 5. 16:13

원문 : Tip/Trick: Creating and Using Silverlight and WPF User Controls

실버라이트와 WPF의 기본 설계 목표 중 한 가지는 UI 기능을 재사용 가능한 컨트롤로 캡슐화하기 쉽게 하는 것입니다.

Control 클래스들(즉  Control  기초 클래스 혹은 TextBox, Button 같은 컨트롤)에서 상속받아 새로운 사용자 지정 컨트롤을 구현할 수 있습니다. 또는 XAML 마크업 파일을 이용하여 UI를 구성하는(따라서 무척 쉽게 개발할 수 있습니다) 재사용가능한 사용자 정의 컨트롤을 만들 수도 있습니다.

저의 Digg.com 튜토리얼 파트 6에서 VS 2008의 "새 항목 추가" 대화 상자를 통해 사용자 정의 컨트롤을 만드는 방법을 보여드린 적이 있습니다. 사용자 정의 컨트롤에 캡슐화된 UI의 최종 모습을 예상할 수 있다면 이는 좋은 방법입니다. 또한 이 방법은 Expression Blend를 사용할 때도 적용될 수 있습니다.

기존 UI를 캡슐화하여 사용자 정의 컨트롤로 만들기

실제로 부모 페이지나 부모 컨트롤에 올려지기 전까지는 그 캡슐화된 UI 기능을 알 수 없는 사용자 정의 컨트롤도 있을 수 있습니다.

예를 들어, 사용자로부터 배송 정보와 결제 정보를 입력받는 폼을 개발한다고 가정하겠습니다. 먼저 배송 정보를 캡슐화하는 UI를 작성하여야 합니다. <border> 컨트롤을 페이지에 올려 놓고, 그 안에 그리드 레이아웃 패널을 집어 넣습니다(2열 4행). 그리고 라벨과 텍스트박스들을 추가합니다.

신중하게 레이아웃을 완성한 후에야 다음과 같은 사실을 알게 됩니다. "아하, 똑같은 UI를 결제 정보에도 사용할 수 있겠구나. 재사용 가능한 주소 사용자 정의 컨트롤을 만들어서 재사용하면 되겠네".

"새 항목 추가" 프로젝트 템플릿을 이용하여 빈 사용자 정의 컨트롤을 만들고 위 UI를 복사/붙여넣기 합니다.

블렌드를 이용하면 이 작업을 더 수월하게 할 수 있습니다. 사용자 정의 컨트롤로 캡슐화할 컨트롤들을 선택한 후, "오른쪽 클릭"한 후 "Make Control"을 선택합니다.

"Make Control"을 선택하면 새 사용자 정의 컨트롤의 이름을 묻는 확인 상자가 뜹니다.

"AddressUserControl"이라고 이름을 지정한 후 확인 버튼을 누릅니다. 그러면 위에서 선택한 컨트롤들을 포함하는 새 사용자 정의 컨트롤이 만들어집니다.

프로젝트를 다시 빌드하고 원래의 페이지로 돌아가면, 이전과 동일한 UI를 볼 수 있습니다. 하지만 이 UI는 이제 AddressUserControl로 캡슐화되어 있습니다.

첫 번째 AddressUserControl을 "ShippingAddress" 이라고 이름을 지정한 후 결제 정보를 받는 두 번째 사용자 정의 컨트롤을 추가합니다. (이 이름은 "BillingAddress" 라고 지정 합니다.)

이제 주소 정보의 UI를 변경해야 할 경우, 한 곳에서만 수정을 하면 배송과 결제 정보의 UI가 모두 변경이 됩니다.

AddressUserControl에 바인딩되는 데이터 바인딩 Address 객체

지금부터는 AddressUserControl에 바인딩할 수 있는 Address 데이터 모델 클래스를 작성하도록 하겠습니다. 아래와 같이 클래스를 정의합니다. (자동으로 구현된 속성 기능을 사용하였습니다.)

Page.xaml의 코드 비하인드 파일에 Address 객체의 인스턴스를 두 개 생성합니다. 하나는 배송 정보를 나타내며 다른 하나는 결제 정보를 나타냅니다. (예제 목적이므로 더미 데이터로 채우도록 하겠습니다.) 그리고는 Address 객체를 AddressUserControl에 프로그래밍 방식으로 바인드하는데, 이는 각 사용자 정의 컨트롤의 "DataContext" 속성에 배송 혹은 결제 Address 데이터 모델 인스턴스를 지정하면 됩니다.

마지막 단계는 AddressUserControl.xaml 파일에 선언적으로 {Binding} 구문을 지정하는 것입니다. 이는 사용자 정의 컨트롤 내부에 있는 텍스트박스 컨트롤의 "Text" 속성과 Address 데이터 모델 객체의 속성을 바인딩하는 것입니다.

F5를 눌러 애플리케이션을 실행하면 Address 데이터 모델이 자동적으로 AddressUserControl에 바인딩이 되는 것을 확인할 수 있습니다.

{Binding} 선언을 "Mode=TwoWay"로 선언하였기 때문에 텍스트박스에 입력된 변경내용운 자동으로 Address 데이터 모델 객체로 전달됩니다. (어떠한 코드도 필요가 없습니다.)

예를 들어, 브라우저에서 원래의 배송 주소를 디즈니랜드로 변경을 하겠습니다.

"Save" 버튼의 "Click" 이벤트 핸들러에 디버거 중단점을 걸고 "Save" 버튼을 누르면, 위 텍스트박스의 변경 내용이 자동으로 "_shippingAddress" 데이터 모델 객체에 반영이 되는 것을 확인할 수 있습니다.

따라서 SaveBtn_Click 이벤트 핸들러에 배송과 결제 Address 데이터 모델 객체를 저장하는 코드를 추가하면 되는데, 이떄 페이지의 UI로부터 값을 수동으로 읽어들이거나 할 필요가 없습니다.

이처럼 WPF와 실버라이트가 지원하는 뷰와 모델의 명확한 구분을 사용하면, 주소 사용자 정의 컨트롤이 변경되더라도 페이지의 코드는 변경되지 않으므로 더욱 유연한 애플리케이션을 작성할 수 있습니다. 또한 유닛 테스트도 더욱 수월하게 수행할 수 있습니다. (자세한 내용은 저의 실버라이트 유닛 테스트(한국어) 포스트를 읽어보시기 바랍니다.)

정리

WPF와 실버라이트를 사용하면 매우 편리하게 컨트롤의 UI 기능을 캡슐화할 수 있습니다. 사용자 정의 컨트롤과 바인딩과 함께 사용하면 뷰와 모델의 분리가 가능해, 데이터를 조작하는 코드를 매우 깔끔하게 작성할 수 있습니다.

위 샘플을 직접 실행시켜 보고 싶으신 분들은 여기서 다운받을 수 있습니다.

실버라이트와 WPF에 대해 더 자세한 알고 싶으면, 저의 실버라이트 튜토리얼 링크 페이지를 방문해보시기 바랍니다. 그리고 MIX08에서 Karen Corby가 한 강연(사용자 정의 컨트롤, 사용자 지정 컨트롤, 스타일링, 컨트롤 템플릿 등을 다루고 있습니다)도 적극 추천합니다. 여기에 가시면 무료로 보실 수 있습니다.

도움이 되길 바라며,

스캇

: