티스토리 뷰

반응형
이 포스트의 내용은 Summary of Chapter 11. The Bindable infrastructure (https://docs.microsoft.com/en-us/xamarin/xamarin-forms/creating-mobile-apps-xamarin-forms/summaries/chapter11) 을 번역한 자료입니다. 한글로 표현하기 어색하거나 모호한 문장은 임의로 조정하거나 삭제하였으므로 필요한 경우 원문을 참고하시기 바랍니다. 또한 언제든지 원저자의 요청에 의해 게시물이 내려지거나 수정될 수 있음을 알려드립니다. 마지막으로 이 글은 개인적인 학습목적으로 번역한 자료이며, 따라서 오역이나 잘못된 해석이 포함되어 있을 수 있으며 이로인한 어떠한 일체의 보장을 하지 않습니다.

모든 C#프로그래머는 C# Property 개념에 익숙합니다. Property는 GetSet과 접근자를 포함하고 있습니다. CLR 환경(Common Language Runtime)에서 제공하기 때문에 종종 CLR Property라고 불리기도 합니다.

Xamarin.Forms는 Bindable Property라고 불리는 향상된 Property를 제공합니다. Bindable Property는 BindableProperty Class에 의해 캡슐화되고 BindableObject Class에 의해 지원됩니다. 이 Class들은 서로 관련된 것처럼 보이지만 전혀 다릅니다: BindableProperty는 Property를 정의하는데 사용됩니다; 반면에 BindableObject는 Bindable Property를 정의하는 Class들을 위한 Base Class로서의 역할을 한다는 점에서 object와 유사하다고 볼 수 있습니다.

이 문서에서는 다음 주제를 다룹니다.

Xamarin.Forms 클래스 계층 구조

ClassHierarchy 샘플은 Xamarin.Forms의 Class 계층구조를 보여줍니다.

최상위 Object 바로아래에는 BindableObject가 위치하고 있습니다. BindableObject 아래에는 Element Class가 위치하고 있으며, VisualElementElement를 상속하고 있습니다. VisualElementPage View의 부모입니다. ViewLayout의 부모입니다.
Class Hierarchy

System.Object
  └BindableObject
    └Element
      └VisualElement
        └View
        │    └...
        │    └Layout
        │        └...
        │        └Layout<T>
        │          └...
        └Page
          └...

BindableObject의 주요한 역할은 Data Binding을 지원하는 것입니다. Data Binding이란 2개의 객체 인스턴스의 Property를 연결하고 같은 값을 가지도록 유지시켜주는 기술을 말합니다. BindableObjectStyleDynamicResource Markup Extension도 지원합니다. Data Binding은 2가지 방법으로 구현가능합니다. 첫번째가 BindableObject를 상속한 Class가 BindableProperty를 통해 Property를 정의하는 경우 Data Binding이 가능합니다. 두번째로 .NET의 INotifyPropertyChange interface를 구현하는 Class의 경우 Data Binding을 지원할 수 있습니다.

BindableObject 하위에 존재하는 Element는 Xamarin.Forms의 UI 객체들이 부모 자식 계층구조를 가질 수 있도록 지원하는 역할을 합니다.

VisualElement는 Xamarin.Forms에서 스크린 화면을 차지하는 비주얼 객체에 필요한 Property를 제공합니다. 현재 VisualElement는 28개의 Property를 제공하는데 크기, 위치, 배경색, IsEnabled, IsVisible와 같은 시각적이고 기능적인 특성을 다룹니다.

View는 Xamarin.Forms에서 버튼, 슬라이더, 텍스트박스 와 같은 모든 시각적 객체를 가리키는 말로 통합니다. 하지만 View의 자식으로는 Layout Class도 존재한다는 것을 알 수 있습니다. ViewVisualElement에서 3개의 Property를 추가하는데 HorizontalOptions, VerticalOptions, GestureRecognizers와 같은 Page에게 불필요한 Property입니다.

Layout의 자식 Class들은 자식 View을 가질 수 있습니다. 자식 View는 부모인 Layout이 제공하는 영역 내에서 공간을 차지합니다. Layout을 상속하는 Class는 오직 1개의 View를 자식으로 가지지만, 제네릭 클래스인 Layout<T>Children Property를 제공하며 이를 통해 여러 개의 자식 View를 가질 수 있습니다.

BindableObject와 BindableProperty 살펴보기

BindableObject를 상속한 Class들이 제공하는 CLR Property들은 Bindable Property에 의해 지원된다고 명시되어 있습니다. 예를들어 Label Class의 Text Property는 CLR Property입니다. 또한 Label Class는 BindableProperty Type의 TextProperty ReadOnly Public Static Field도 정의하고 있습니다.

일반적으로 애플리케이션은 LabelText Property를 통해 값을 할당하거나 읽을 수 있지만 BinableObject가 정의하고 있는 SetValue 메서드를 Label.TextProperty 매개변수와 함께 호출하여 Text Property에 값을 할당할 수도 있습니다. 마찬가지로 GetValue 메서드를 Label.TextProperty 매개변수와 함께 호출하여 Text Property의 값을 읽을 수 있습니다. PropertySettings 샘플에서는 이에 관한 예제를 제공합니다.

실제로 Text CLR Property는 내부적으로 BindableObjectSetValueGetValue 메서드를 Label.TextProperty 매개변수와 함께 호출하는 형태로 구현되어 있습니다.

BindableObjectBindableProperty는 다음과 같은 지원을 제공합니다.

  • Property의 기본 값을 제공함
  • Property의 값을 저장
  • Property 값의 유효성 검사를 위한 장치를 제공
  • 단일 Class의 관련된 Property들의 일관성을 유지 관리
  • Property의 값이 변경되었을 때 응답을 제공
  • Property의 값이 변경되거나 변경된 후에 실행되는 콜백 메서드를 지원
  • DataBinding을 지원
  • Style을 지원
  • DynamicResource를 지원

Bindable Property에 의해 지원되는 Property 값이 변경되면 BindableObjectPropertyChanged 이벤트를 호출하여 값이 변경된 Property가 무엇인지 알수 있도록 지원합니다. 만약 동일한 값이 할당된다면 PropertyChanged 이벤트는 실행되지 않습니다.

일부 Property는 Bindable Property에 의해 지원되지 않습니다. 예를들어 Xamarin.Forms의 Span과 같은 Class들은 BindableObject를 상속하지 않습니다. BindableObject를 상속한 Class만이 Bindable Property를 지원할 수 있습니다. 왜냐하면 BindableObjectSetValueGetValue 메서드를 정의하고 있기 때문입니다.

SpanBindableObject를 상속하지 않기 때문에 SpanText Property를 포함한 모든 Property는 Bindable Property에 의해 지원되지 않습니다. 이것이 바로 이전 챕터의 DynamicVsStatic 샘플에서 SpanText Property에 DynamicResource를 설정했을 때 Exception이 발생한 이유입니다. DynamicVsStaticCode 샘플은 Element에 의해 정의되어 있는 SetDynamicResource 메서드를 이용하여 Dynamic Resource를 설정하는 예제를 제공합니다. SetDynamicResource 메서드의 첫번째 매개변수는 BindableProperty Type 객체입니다.

마찬가지로 BindableObject가 정의하고 있는 SetBinding 메서드의 첫번째 매개변수도 BindableProperty 입니다.

Bindable Property 정의

BindableProperty.Create static 메서드를 사용하여 BindableProperty Type의 Static ReadOnly Field를 정의할 수 있으며, 이를 통해 필요한 BindableProperty Property를 직접 정의할 수 있습니다.

Xamarin.FormsBook.Toolkit 라이브러리의 AltLabel Class를 통해 Bindable Property를 정의하는 샘플을 보실 수 있습니다. 이 Class는 Label을 상속하고 있으며 폰트 크기를 Point 단위로 설정 할 수 있는 Bindable Property를 제공합니다. 이에 관한 예제는 PointSizedText 샘플에서 제공하고 있습니다.

BindableProperty.Create 메서드는 4개의 매개변수를 요구합니다.

  • propertyName : Property의 이름 (CLR Property의 이름과 동일한 문자열로 지정해야 합니다)
  • returnType : CLR Property의 Type
  • declaringType : 이 Property를 제공하는 Class의 Type
  • defaultValue : Property의 기본 값

defaultValueobject Type으로 전달받기 떄문에 컴파일 타임에 Type이 적절한지 파악하지 못합니다. 따라서 반드시 Type에 맞는 값을 지정하도록 유의해야 합니다. 예를들어 returnTypedouble이면 defaultValue는 반드시 0이 아니라 0.0과 같이 double 값을 지정해야 하며, 이를 준수하지 않을 경우 실행 중에 Exception이 발생하게 됩니다.

propertyChanged는 Bindable Property를 정의할 때 자주 사용하는 매개변수 입니다.

  • propertyChanged : Property의 값이 변경되 었을 때 호출되는 Static 메서드로서 값이 변경된 Class의 인스턴스가 첫번째 매개변수로 전달됨

BindableProperty.Create 메서드에서 자주 사용되지 않는 매개변수입니다.

  • defaultBindingMode : Data Binding과 관련하여 사용됩니다. (자세한 내용은 Chapter 16 DataBinding에서 다룹니다.)
  • validateValue : 데이터 유효성 검증을 위한 콜백 메서드
  • propertyChanging : Property의 값이 변경되었을 때 호출되는 콜백 메서드
  • coerceValue : 값을 지정할 때 특정 값으로 강제하기 위한 콜백 메서드
  • defaultValueCreate : Class 인스턴스간에 공유되지 않는 기본값을 생성하기 위한 콜백 메서드 (예: Collection)

ReadOnly Bindable Property

Bindable Property는 ReadOnly가 될 수 있습니다. ReadOnly Bindable Property를 생성하려면 BindableProperty.CreateReadOnly Static 메서드의 호출을 필요로 하며, 이 메서드 호출을 통해 BindablePropertyKey Type의 Private Static ReadOnly Field를 정의해야합니다.

그런 다음 CLR Property를 정의하고 set 접근자를 private로 구현해야 합니다. set 접근자에서는 BindablePropertyKey 값을 매개변수로 SetValue 메서드를 호출해야 합니다. 이러한 구현을 통해 Class의 외부에서 Property의 값 변경을 막을 수 있습니다.

BaskervillesCount 샘플에서 CountedLabel Class는 이러한 ReadOnly Bindable Property 구현방법을 보여주고 있습니다.


댓글