Layout 기본 (1) - Grid
Grid는 뷰를 행과 열의 관점에서 정렬한다. 행과 열은 비율적 또는 절대적인 크기가 될 수 있다. Grid는 전통적인 테이블형식의 데이터를 다루기 위한것과 혼돈하지 마라. Grid는 순수하게 컨텐츠의 레이아웃을 다루는 목적으로 존재한다.
목적
Grid는 뷰를 격자형태로 정렬하는데 사용될 수 있다.
- 계산기 앱의 버튼 정렬
- 버튼이나 아이콘을 iOS 또는 Android의 홈스크린과 같이 배치
- 일차원적인 공간에 동일한 크기의 뷰를 나열 (툴바와 같은 형태)
사용법
테이블과 달리, Grid는 행과 열의 크기나 갯수가 컨텐츠에 의해 결정되지 않는다. 대신, Grid는 RowDefinitions와 ColumnDefinitions 컬렉션을 가진다. 이 정의들은 몇개의 행과 열이 놓여질지에 관한 정보를 가지고 있다. 뷰요소는 특정 행과 열의 번호에 기반해 정해진 곳에 추가된다.
행과 열
RowDefinitions은 Height속성을 갖고, ColumnDefinition은 Width라는 속성을 가진다. 높이와 너비는 다음의 선택값을 가질 수 있다.
- Auto - 행 또는 열에 컨텐츠의 크기에 따라 크기가 자동으로 정해진다. GridUnitType.Auto 또는 Auto 를 사용한다.
- 비례항() - 크기를 남은 공간의 비율에 따라 정한다. GridUnitType.Star 또는 “#“ 과 같이 XAML에서 사용할 수 있다. “#”은 원하는 배율의 숫자로 치환된다. “*”로만 사용되었을 경우에는 가능한 공간만큼 채워진다.
- 절대값 - 정해진 높이나 너비값으로 크기가 정해진다. GridUnitType.Absolute 또는 특정 숫자값을 사용한다.
주의: Xamarin.Forms 에서 너비의 기본값은 Auto이다. 이 크기는 자식 컴포넌트의 크기에 따라 결정된다는것을 의미한다. Microsoft 플랫폼의 XAML 구현체에서는 이와 달리 “*”가 기본값이다. 이것은, 사용가능한 공간을 모두 채운다.
예를들어, 어떤 앱이 세개의 행과 두개의 컬럼으로 구성된다고 가정하자. 마지막 행은 정확히 200px의 높이를 가지고, 맨윗줄은 가운데행 보다 두배 높다. 마지막으로, 맨왼쪽 열은 컨텐츠의 폭만큼 너비를 차지하고 오른쪽은 나머지 공간을 차지한다고 했을때 XAML을 아래와 같이 작성할 수 있다.
C# 에서는 아래와 같다.
뷰를 Grid에 삽입하기
뷰를 Grid에 추가하려면, 뷰를 Grid의 자식으로서 어떤 행과 열에 속할지를 명시하여 추가하면 된다. XAML에서는 Grid.Row와 Grid.Column 을 Zero-base로 추가한다. 즉, 4x4격자의 경우 좌상단 셀의 경우 (0,0)이 되고 우하단 셀은 (3,3)이 된다는것을 의미한다.
아래 Grid의 경우 코드를 보자.
XAML 코드
C# 코드
위 코드는 네개의 레이블을 동일한 크기를 가지는 두개의 컬럼과 행으로 이루어진 격자에 위치시킨다. GridUnitType.Star 이기 때문에 각 레이블은 가능한 공간 만큼 늘어난다.
공백
Grid는 행과 열사이의 공백을 제어할 수 있는 속성을 갖고 있다.
- ColumnSpacing - 열사이의 공백
- RowSpacing - 행사이의 공백
다음 코드는 한행에 두개의 열로 구성되어 있으며, 컬럼사이의 간격은 5px을 할당하였다.
C# 코드
Spans
Grid를 사용하다보면, 어떤 요소의 경우 한칸 이상의 행이나 열을 차지할 필요가 생길때가 있다. 아래의 계산기 앱을 보자.
“0”버튼이 두개의 컬럼을 사용하고 있다. 이것은 ColumnSpan 속성을 사용하면 된다. 이 속성은 몇개의 컬럼을 차지할지를 정한다.
C# 코드
RowSpan도 동일한 방법으로 적용할 수 있다.
출처 : https://developer.xamarin.com/guides/xamarin-forms/user-interface/layouts/grid/
ListView 기본 (3)
ListView의 셀의 표현은 두가지 방법으로 접근할 수 있다.
- 기본셀 커스터마이징 - 비용면에서 저렴하고 쉽게 구현이 가능하다.
- 커스텀셀 생성 - 좀 더 정교한 결과물을 만들어 낼 수 있다. 하지만, 재대로 구현하지 못할 경우 성능 이슈를 야기할 수 있다.
기본 셀
간단한 어플리케이션들을 위해 기본적인 셀을 포함하고 있다.
- TextCell - 텍스트를 표현하기 위한 셀
- ImageCell - 이미지와 텍스트를 표현하기 위한 셀
SwitchCell과 EntryCell도 제공되고 있지만, 이들은 ListView보다는 TableView에 주로 사용된다.
TextCell
TextCell은 텍스트를 표현하며, 옵션으로 두번째 줄에 상세 텍스트를 표현할 수 있다.
TextCell은 네이티브 컨트롤을 실행하여 성능이 커스텀셀에 비해 뛰어나다. TextCell은 다음 속성들을 지원한다.
- Text - 첫번째 라인에 표시할 텍스트. 큰 폰트를 사용한다.
- Detail - 두번째 라인에 표시할 텍스트이며 첫번째 라인보다 작은 폰트를 사용한다.
- TextColor - 첫번째 라인의 텍스트 색상
DetailColor - 두번째 라인의 텍스트 색상
ImageCell
ImageCell 역시 TextCell과 같이 플랫폼의 네이티브 컨트롤을 사용하여 좋은 성능을 보여준다. TextCell과 다른점은 텍스트의 왼쪽에 이미지를 보여주는 것이다. 그러므로, ImageCell은 TextCell과 동일한 속성에 UmageSource 라는 속성을 추가로 지원한다. 주의할점은, 윈도우폰 8.1에서의 경우 이미지가 자동으로 스케일링이 되지 않아 아래와 같이 보일 수 있다는 점이다.
커스텀 셀
기본셀로 표현하기 어려운경우 커스텀셀을 만들 수 있다. 커스텀셀은 반드시 ViewCell을 상속받아야 한다.
XAML
위 샘플 레이아웃은 아래의 XAML코드로 표현될 수 있다.
1234567891011121314151617181920212223242526<?xml version="1.0" encoding="UTF-8"?><ContentPage xmlns="http://xamarin.com/schemas/2014/forms"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"x:Class="demoListView.ImageCellPage"><ContentPage.Content><ListView x:Name="listView"><ListView.ItemTemplate><DataTemplate><ViewCell><StackLayout BackgroundColor="#eee"Orientation="Vertical"><StackLayout Orientation="Horizontal"><Image Source="{Binding image}" /><Label Text="{Binding title}"TextColor="#f35e20" /><Label Text="{Binding subtitle}"HorizontalOptions="EndAndExpand"TextColor="#503026" /></StackLayout></StackLayout></ViewCell></DataTemplate></ListView.ItemTemplate></ListView></ContentPage.Content></ContentPage>
- 커스텀셀 역시 기본셀과 마챦가지로 DataTemplate의 자식이다.
- 즉, DataTemplate의 자식 요소는 모두 ViewCell의 파생 클래스 이다.
C
XAML과 동일한 과정을 C#코드를 거치게 되면 조금 더 복잡해 진다. 먼저, ViewCell을 상속받는 CustomCell 클래스를 정의하자.
다음은, 페이지의 생성자에서 ListView의 ItemTemplate의 속성을 새로운 DataTemplate으로 설정해야 한다.
DataTemplate의 생성자가 type을 취한것에 주목하라. typeof 오퍼레이터는 CustomCell의 CLR타입을 리턴한다.
컨텍스트 변화 바인딩
CustomCell의 BindableProperty 인스턴스에 바인딩할때, UI컨트롤이 BindableProperty의 값을 보여주기 위해서는 OnBindingContextChanged/)를 오버라이드하여 값을 설정해야 한다.
BindingContextChanged 이벤트가 발생하면, OnBindingContextChanged 메소ㄷ가 호출된다. 이 메소드는 BindingContext 의 속성값의 변화에 대한 책임을 진다.
이제 XAML에서, 커스템 셀의 타입을 아래 코드와 같이 데이터에 바인딩할 수 있다.
결과적으로, CustomCell의 Name, Age, Location이라는 Bindable 속성에 콜렉션 객체의 Name, Age, Location 속성이 바인딩 되었다. 이것을 C#코드로 표현하면 아래와 같다.
ListView 기본 (2)
ListView에 데이터를 바인딩 하는 과정은 크게 두가지가 있다.
- 아이템 소스 설정 - 간단한 리스트 또는 배열을 이용
- 데이터 바인딩 - ListView와 모델간의 관계를 설정. 여기에서 MVVM패턴을 다룬다.
아이템 소스
ListView 는 ItemSource 속성을 사용해 데이터를 생성할 수 있다. 이 속성은 IEnumerable을 구현하는 어떤 컬렉션이든 수용할 수 있다. ListView를 생성하는 가장 간단한 방법은 문자열 배열을 이용하는 것이다.
기본적으로, ListView는 ToString을 호출하고 그 결과를 TextCell에 표현한다. 셀의 커스터마이징에 관해서는 Cell Appearance를 참고하라.
하지만, 이 방법은 기반인 문자열 배열이 이미 ItemSource에 이미 보내졌기 때문에 변경사항이 반영되지 않는다. 만일, ListView에 이러한 변경이나 추가, 삭제가 자동으로 업데이트 되길 원한다면 ObservableCollection을 사용해야 한다. 이것은 System.Collections.ObjectModel에 정의되어 있다. 이것은 List와 비슷하지만, 컬렉션의 변화를 ListView에 알려줄 수 있다.
데이터 바인딩
데이터 바인등은 사용자 인터페이스의 속성과 ViewModel과 같은 CLR객체의 속성을 연결하는 과정을 말한다. 데이터 바인딩 덕분에 사용자 인터페이스를 갱신하는 많은 귀챦은 작업들이 간편해 질수 있다. 데이터 바인딩의 기초에 관한 글을 참고하라.
바인딩 셀
셀의 속성은 ItemSource에 객체의 속성과 바인딩 될 수 있다. 아래 예제는 ListView에 직원들의 목록을 표시하는 예제이다.
직원 클래스:
ListView의 ItemsSource에 ObservableCollection
다음과 같이 샘플 데이터를 생성한다.
다음은 ListView를 바인딩하는 XAML 이다.
각 행의 레이아웃은 ListView.ItemTemplate 요소이며, TextCell에 이름이 바인딩되어 있다. 결과는 아래와 같다.
선택된 요소의 바인딩
ListView의 현재 선택된 아이템을 바인드 하고 싶을 경우 이벤트 핸들러를 사용해 변화에 대응하는것 보다, XAML의 SelectedItem속성을 사용할 수 있다.
ListView의 ItemsSource는 문자열 배열이며, SomeLabel의 Text속성이 SelectedItem에 바인딩될 것이다.
ListView 기본 (1)
ListView는 데이터의 목록을 표현하는 뷰이다. 이 가이드에서는 LivtView와 관련하여 다음과 같은 주제들을 다룰것이다.
- 데이터 소스 - ListView에 사용될 데이터.
- 셀 표현 - 기본셀 또는 사용자가 생성한 셀의 커스터마이징.
- 목록 표현 - ListView의 헤더와 푸터, 그룹핑과 행의 높이 조절등.
- 인터랙티브 - 사용자의 행 선택과 새로고침, 컨텍스트 메뉴 행동에 대한 처리
사용예
항상 UI control은 목적에 맞게 적절히 사용되어져야 한다. ListView는 스크롤이 필요한 데이터 목록이 필요한 어떤곳에서든 사용될 수 있으며, 컨텍스트 액션과 데이터 바이딩을 지원한다. ListView는 TableView와 구분되어 사용되어야 한다. iOS의 설정앱에 보여지는 목록과 같이 보여줄 데이터가 미리 정해져 있을 경우에는 ListView보다 TableView가 더 적합하다.
또한, ListView는 동질의 반복되는 데이터를 표현하는데 적합하다. 그것은, ListView가 행에 대해 한가지 셀타입만 지원하기 때문이다. 반면, TableView는 여러가지 셀타입을 지원하므로, 혼합된 형태의 뷰가 필요하다뎐 TableView가 더 적합하다.
컴포넌트
ListView는 각 플랫폼의 네이티브가 가진 기능들을 거의 다 가지고 있다.
- 헤더와 푸터 - 목록의 시작과 끝지점에 데이터 소스와는 별개로 텍스트 또는 특정뷰를 바인딩 할 수 있다.
그룹 - 데이터를 그룹화하여 표현할 수 있다. 일반적으로, 데이터와 바인딩 된다.
셀 - ListView의 데이터는 셀의 형태로 표현된다. 각 셀은 하나의 행 데이터와 대응된다. 기본적으로 제공되는 셀을 사용할 수도 있고 사용자가 만들수도 있다. 셀은 XAML 또는 코드로 정의될 수 있다.
- 기본셀 - 내장된 셀들로서 TextCell, ImageCell과 같은 것이 있다. 기본적으로, 각 플랫폼의 네이티브 컨트롤과 대응되어 좋은 성능을 보여준다.
- TextCell - 텍스트 문자열을 보여준다. 옵션으로 상세 텍스트를 제공할 수 있다. 상세 텍스트는 두번째 라인에 작은 폰트와 강조된 색상으로 표현된다.
- ImageCell - 이미지와 텍스트. 왼쪽의 이미지와 오른쪽에 TextCell의 형태로 표현된다.
- 사용자 정의 셀 - 사용자가 보여주고 싶은 형태로 셀을 꾸밀 수 있다. 노래 목록에 앨범과 가수의 정보등을 함께 표현하는등의 뷰를 만들 수 있다.
기능
ListView 는 다양한 사용자 인터랙션 경험을 지원한다.
- Pull-to-Refresh - 각 플랫폼별로 목록 새로고침을 지원
- Context Action - 목록의 각 행(아이템)에 대한 네이티트 액션을 지원한다. 예를들어, iOS 에서의 밀기 액션(Swipe-to-action) 이다 Android, 윈도우폰의 길게 누름과 같은 액션(long-tap)이 있다.
- Selection - 각 행을 탭하였을때 선택 또는 선택 해제에 대한 액션을 수행할 수 있다.
ListView의 인터랙티브에 대한 더 자세한 사항은 Actions & Interactivity with ListView를 참고하라.
C# 5.0 비동기 프로그래밍 개요
C# 5.0부터는 비동기 오퍼레이션을 위한 두개의 키워드 async와 await가 추가되었다. 이 키워드를 이용하여 간단한 코드로 Task 병렬 라이브러리를 이용해 네트워크 억세스와 같이 별도의 쓰레드에서 비교적 긴시간이 걸리는 작업에 대한 결과를 쉽게 얻을 수 있다.
개요
이 문서는 Xamarin.iOS와 Xamarin.Android를 기준으로 간단한 예제를 구현하고 있으며, 좀 더 상세한 정보는 MSDN문서 Async와 Await를 이용한 비동기 프로그래밍를 참고하기 바란다.
샘플 어플리케이션은 메인 쓰레드에 대한 간섭(Blocking)없이 간단한 비동기 웹요청을 보내고 그 결과값을 UI에 반영하는 과정을 보여준다.
C# 5.0은 Mono 3.0 이상을 요구하며, Xamarin.iOS 6.4, Xamarin.Android 4.8 이상에 포함되어 있다. 최신 버전의 Xamarin Studio로 업그래이드 하면 사용이 가능하다.
async
async 키워드는 메소드 정의시에 사용된다. 람다 또는 익명 메소드에도 사용될 수 있다. 이것은 해당 메소드가 비동기 코드를 포함하고 있다는것을 의미한다. 즉, 호출자의 쓰레드를 블록킹하지 않도록 한다는것을 의미한다. 그러므로, async 메소드는 반드시 하나 이상의 await 구문 또는 표현식을 포함하여야 한다. 만일, await 구문이 없다면 컴파일러 경고가 발생하며 심각한 에러가 발생하지는 않는다.
반환값
async 메소드는 Task, Task
- 메소드가 어떤 값도 리턴하지 않는다면 Task형을 리턴 하도록 한다.
- 값을 리턴할 필요가 있다면 Task
형을 리턴 하도록 한다. TResult는 타입명이다. - void 리턴 타입은 주로 이벤트 핸들러의 경우에 사용된다. 이 코드는 결과를 기다리지 않는다.
await
await 오퍼레이터는 해당 작업을 비동기로 구분한다. 이 지점에 메소드의 실행이 멈추고 작업이 끝나기를 기다리게 된다. await의 사용은 호출 쓰레드까지 멈추게 하지 않고 제어권을 호출자에게 넘긴다. 일반적으로 호출자는 UI 쓰레드인 경우가 많으며 태스크를 기다리는 동안에도 사용자 인터페이스는 블록킹이 되지 않도록 해준다. 작업이 종료되면, 메소드는 다시 원래 지점으로 돌아와 실행을 계속한다. await는 try-catch-finally 구문에서 try 블록 내에서만 사용이 가능하며 catch나 finally 블록에서는 사용될 수 없다. await에 대한 더 상세한 정보는 await on MSDN를 참고하라.
취소
완료하는데 오랜 시간이 걸리는 비동기 메소드는 취소(cancellation)를 지원해야 한다. 일반적으로, 취소는 다음과 같은 순서로 실행된다.
- CancellationTokenSource 객체를 생성한다.
- CancellationTokenSource.Token 인스턴스가 취소 가능한 비동기 메소드로 전달된다.
- CancellationTokenSource.Cancel 메소드를 호출하여 취소를 요청한다.
취소에 대한 상세한 정보는, MSDN의 how to cancel an asynchronous task 문서를 참고하라.
예제
예제소스를 통해 async 와 await 의 모바일에서 실사용 예를 살펴보자.
async 메소드 작성
|
|
- 이 메소드 선언은 async 키워드를 포함한다.
- 반환 타입은 Task<int>이다. 즉, 호출자는 정수값을 받을 수 있다.
- 리턴 구문은 return exampleInt; 이다.
async 메소드 호출 1
다음 코드는 안드로이드 샘플 소스에서 발췌한 버튼 클릭에 대한 이벤트 핸들러 이다.
- 익명의 딜리게이트는 이벤트 핸들러에 비동이 메소드임을 나타내는 async 키워드를 사용할 수 있다.
- DownloadHomepage 는 비동기 메소드로서 Task를 리턴하고, 이것을 sizeTask 변수에 저장한다.
- sizeTask에 대한 await코드는 메소드가 실제로 정체되는 구간으로 제어가 호출자로 돌아가는 부분이다. 이것은 비동기 작업이 현재 쓰레드로 돌아왔을때 다시 재개된다.
- Task가 앞부분에 선언되었다고 해서 메소드가 정체되지 않는다. 반면, Task는 await 키워드가 노출된 부분부터 실행이 정체된다.
- 비동기 작업이 완료되었을뗘 , intResult값이 할당되고 원래 쓰레드로 돌아온다.
async 메소드 호출 2
|
|
TODO: summary
출처 : https://developer.xamarin.com/guides/cross-platform/advanced/async_support_overview/
DependencyService를 이용한 네이티브 접근
개요
DependencyService는 공유코드에서 플랫폼 고유의 기능을 호출할 수 있도록 해준다. DependencyService는 공유코드에 인터페이스를 정의하고 이것에 대한 실제 구현을 찾아주는 resolver의 역할을 수행함으로써 네이티브 앱이 할수 있는 모든 일은 Xamarin.Forms 앱이 할 수 있도록 해준다.
DependencyService의 작동 원리
DependencyService를 사용하기 위해서는 크게 세가지 컴포넌트가 필요하다.
- 인터페이스 : 필요한 기능이 공유코드에 인터페이스로 정의된다.
- 플랫폼 구현체 : 각 플랫폼에 대한 인터페이스의 구현체 클래스.
- 등록(Registration) : 각 플랫폼 구현체는 메타데이터 속성을 통해 DependencyService에 등록 되어야만 한다. 이 과정은 DependencyService가 구현체를 찾고 런타임에 인터페이스에 해당 구현체를 공급할 수 있도록 해준다.
- DependencyService 호출 : 공유코드는 인터페이스의 구현체를 찾기위해 명시적으로 DependencyService를 호출할 필요가 있다.
이 과정을 간단히 도식화 하면 아래와 같다.
인터페이스
인터페이스는 사용하고자 하는 플랫폼 고유의 기능을 정의한다. 만일, 개발하고자 하는 모듈이 다른 프로젝트와 공유될 수 있는 컴포넌트이거나 Nuget 패키지 형태라면 고려되지 않은 네이티브 플랫폼에서 런타임 오류가 발생 할 수 있으므로 주의해야 한다. 아래의 예제코드는 텍스트를 읽어주는 기능에 대한 인터페이스이다. 하지만, 각 플랫폼의 구현체는 별도로 제공하거나 남겨두어야 한다.
플랫폼에서의 구현
인테페이스가 정의되면 프로젝트의 각 플랫폼 프로젝트에서 구현이 수반되어야 한다. 아래 예제코드는 ITextToSpeech 인터페이스에 대한 윈도우폰 플랫폼의 구현에 대한 예제이다.
모든 네이티브 구현체는 반드시 인자가 없는 생성자를 포함하여야 한다. 이것은, DependencyService가 이 구현체를 인스턴스화 하기 위해 필요하다.
등록
인터페이스에 대한 구현체는 DependencyService가 찾을 수 있도록 메타데이터와 함께 등록되어야 한다. 아래 코드는 윈도우폰을 위한 구현체의 등록 예제이다.
이 코드에서 등록이 클래스 레벨이 아닌 네임스페이스 레벨에서 이루어지는것에 주의해야 한다.
DependencyService 호출
공통 인터페이스와 플랫폼 고유의 구현체가 DependencyService에 등록되었다면 아래 예제 코드와 같이 호출하여 사용할 수 있다.
|
|
예제소스 구조
예제코드는 iOS와 Android 구현체를 포함 하고 있으며 아래 그림과 같이 구성되어 있다.
원본출처 : https://developer.xamarin.com/guides/xamarin-forms/dependency-service/introduction/
Xamarin.Forms 데이터 바인딩 3/3
이전 시리즈에서 기본적인 데이터 바인딩을 이용하여 Xamarin.Forms 어플리케이션을 개발할때 최소한의 노력으로 앱의 데이터와 UI가 동기화 할 수 있다는것을 확인하였다. 다음에는, 좀 더 진보된 바인딩 시나리오에 따라 소스와 타깃객체 사이에 값을 전달시 변환하는 방법도 보았다.
이번 글에서는, Xamarin.Forms의 커맨딩이라는 기능을 소개할것이다. 이것은 뷰모델에 직접 메소드 호출을 하여 데이터 바인딩이 이루어지도록 해준다.
커맨딩(Commanding) 소개
기존의 메소드 호출 방법은 일반적으로 버튼객체에 Clicked 이벤트 핸들러나 TapGestureRecognizer의 Tapped 이벤트 핸들러로부터 메소드를 실행하는 형태였다. 하지만, 커맨딩을 이용하면 다음의 UI객체들로 부터 뷰모델에 직접 메소드 호출을 하여 데이터를 바인딩할 수 있다.
- Button
- MenuItem
- ToolbarItem
- TextCell
- ImageCell
- ListView
- TapGestureRecognizer
커맨딩을 지원하기 위해서, 주요 클래스들에 두개의 퍼블릭 속성이 정의되어있다.
- ICommand (System.Window.Input.ICommand)
- CommandParameter (object)
커맨드 구현
커맨딩을 구현하기 위해서, 뷰모델은 하나 이상의 ICommand를 정의하여야 한다. ICommand 인터페이스는 두개의 메소드와 하나의 이벤트로 구성되어 있다.
Xamarin.Forms에서 제공되는 Command와 Command<T>는 ICommand 인터페이스의 구현체이다. “T”는 Execute와 CanExecute의 인자 타입이다. 추가로, 이 클래스들은 ChangeCanExecute 메소드를 포함하고 있다. 이 메소드는 커멘드 객체로 부터 CanExecuteChanged 이벤트를 발생시킨다.
뷰모델 내부의, ICommand타입의 커맨드 객체는 Command 또는 Command
다음은, 제곱근을 계산하는 예제의 뷰모델 코드 일부이다.
SquareRootCommand는 Button의 Command속성으로서 CalculateSqureRoot라는 Action을 콜백으로 가진 바인딩 속성이다. 예제 XAML을 통해 이 뷰모델이 이떻게 사용되는지 보자.
입력값은 Number와 양방향으로 바인딩되고, 버튼을 클릭하면 입력값에 따라 SquareRootCommand가 실행되어 SquareRootResult가 Label에 Text속성으로 적용된다.
커맨드에 파라미터 전달하기
Command
Button의 ICommand 속성에 SquareRootWithParameterCommand가 바운드 되어있다. 이 속성은 Command
이전의 소스와 차이점은 Button의 CommandParameter이다. 인자로, entry의 Text속성이 인자의 값으로 바인딩 되었음을 볼 수 있다.
비동기 메소드 호출
커맨드는 Action콜백에 async와 await 키워드를 사용해 비동기 메소드 호출도 지원한다. 콜백은 Task를 리턴하므로 반드시 기다려야 한다는것을 의미한다.
SimulateDownloadCommand는 버튼의 Command속성에 바운드 되었다. XAML코드는 아래와 같이 선언되어 있다.
버튼이 클릭되면 SimualteDownloadAsync 메소드가 실행되고 5초동안 버튼은 비활성화 되었다가 다시 활성화가 된다. 이것은 ICommand.CanExecute 메소드가 SimulateDownloadCommand 생성자의 두번째 인자로 설정되었기 때문이다. 버튼은 CanExecute를 먼저 체크한다. 만일, false라면 버튼은 비활성화되고 Execute는 호출되지 않는다. 또한, 버튼은 ICommand.CanExecuteChanged 이벤트를 처리한다. 만일, 뷰모델에서 Command.CanExecuteChange 메소드가 호출되어 CanExecuteChanged 이벤트가 발생한다면 버튼은 CanExecute 메소드를 다시 체크하여 버튼의 활성화 및 Execute 메소드의 실행가능 여부를 재평가하게 된다.
이 예제에서 다운로딩이 별도의 쓰레드에서 진행되는 도중에도 UI객체와 교류가 가능함에 주목하도록 하자.
정리
커맨딩 기능을 이용한 데이터 바인딩은 뷰 모델 구현이 좀 복잡해 보일 수 있으나,컴포넌트의 재활용 측면에서 MVVM에 매우 적합한 코딩패턴이다. 또한, 실제 코딩시 비동기 호출이 많이 사용되는데 이 부분 또한 깔끔하게 처리할 수 있을 뿐만 아니라 데이터 모델과 바인딩 처리가 한곳에서 이루어 짐으로써 코드의 유지 관리 측면에서도 유리하다.
원본출처 : https://blog.xamarin.com/simplifying-events-with-commanding/
Xamarin.Forms 데이터 바인딩 2/3
데이터 바인딩 팁
이전 글에서, 데이터 바인딩을 실제 프로젝트에서 어떻게 사용하는지 살펴 보았다. 이번 글에서는 좀 더 발전된 시나리오에 대해 다루어 보겠다.
컨트롤간의 바인딩
데이터 바인딩은 UI와 데이터 모델간의 동기화가 일반적이지만, 동일 페이지의 두 속성간에도 연결될 수 있다. 이것은, 타깃객체의 BindingContext를 x:Reference마크업을 이용해 설정함으로서 간단히 이루어 진다. 다음 코드는, 예제 어플리케이션의 XAML코드 이다.
Slider 컴포넌트의 이름을 “slider”로 설정하였다. 그리고, 그다음에 Image, Label 컴포넌트에 각각 BindnigContext가 “x:Reference”마크업을 이용해 “slider”로 설정되었다. 이후, Image의 Rotation속성과 Label의 Text속성에 Slider의 Value값이 사용된 것을 볼 수 있다.
(Label의 Text속성에 StringFormat사용시 쌍따옴표를 사용하지 않고 홑따옴표를 사용하여 중괄호 바깥의 쌍따움표와 중첩되지 않도록 처리한 부분에 주의하자.)
변환기
앞서 예제에서 Label에 Text속성에서 StringFormat을 사용하여 Value를 포매팅한것을 보았다. 이것은, 말그대로 형식화(Formatting)한 것이지 값에 대한 변환이라고 보긴 어렵다. 즉, 타입의 변환은 별도의 변환기를 거쳐야 한다는 것이다. 이것은 IValueConverter 인터페이스를 구현하는 클래스로 가능하다. 이 인터페이스는 Convert와 ConvertBack 메소드의 구현을 필요로 한다.
다음 코드는 예제 어플리케이션에서 사용된, IntToBooleanConverter 코드 이다.
Convert 메소드는 값이 소스객체에서 타깃객체로 전달될때 호출된다. ConvertBack은 반대로 타깃에서 소스객체로 값이 전달될 때 호출된다. TwoWay 또는 OneWayToSource 모드 바인딩시에 해당된다. 두 메소드 모두 소용 목적은 동일하므로 사용된 인자들에 대해 알아보자.
- object value : 소스객체의 값
- Type targetType : 타깃속성의 타입. Convert 또는 ConvertBack 메소드는 이 타입의 결과값을 리턴한다.
- object parameter : 선택값으로 XAML의 Binding 마크업에서 파라미터를 전달하고자 할때 사용된다. 이 예제에서는, value와 비교하기 위한 최소값의 용도로 사용되었다.
- CultureInfo culture : 지역화를 위한 포매팅이 필요할 경우 사용하기 위한 지역정보이다.
이제, XAML에서 변환기를 ResourceDictionary에 추가하고 StaticResource 마크업을 이용해 사용하면 된다. 변환기는 상태를 관리할 필요가 없으므로 여러곳에서 정적으로 사용될 수 있다.
|
|
이 예제에서, 변환기는 Button의 IsEnabled 속성을 활성 또는 비활성 하는 용도로 사용되었다. 즉, 에디터의 텍스트값의 길이가 최소값 10보다 클 켱우에만 버튼이 활성화 되도록 한것이다.
정리
데이터 바인딩은 숨겨진 모델객체와 UI 사이 뿐만 아니라, 화면상의 컨트롤간에도 동일한 방식으로 바인딩이 가능하다. 이것을 가능하게 하는것이 “x:Reference” 마크업을 이용해 타깃객체에 BindingContext를 설정하는 것이다.
바인딩은 어떤 암묵적인 데이터 변환도 하지 않는다. 데이터 변환기를 통해서 바인딩 과정에 자동으로 변환이 이루어 질 수 있으며, IValueConverter 인터페이스를 구현하는 클래스를 통해 가능하다.
관련링크 :
원본출처 : https://blog.xamarin.com/advanced-data-binding-for-ios-android-and-windows/
Xamarin.Forms 데이터 바인딩 1/3
데이터 바인딩 소개
데이터 바인딩은 자동으로 유저 인터페이스와 데이터를 동기화 시켜주는 기술이다. 이것은 앱이 UI를 표현하고 데이터와 상호 작용하는것을 단순하게 해준다.
데이터 바인딩 기초
데이터 바인딩은 두개의 객체를 연결한다. 하나는 소스, 다른 한쪽은 타깃이 된다. 소스객체는 데이터를 제공하고 타깃객체는 소비(표현)한다. 예를들어 Label의 Text속성은 소스객체의 문자열 속성과 바인드된다.
이런한 데이터 바인딩의 가장 큰 장점은 뷰와 데이터간의 동기화에 관해 신경쓰지 않아도 된다는 것이다. 소스객체에 변화가 생기면 바인딩 프레임워크에 의해 자동으로 타깃객체에 반영되고, 그 반대도 마챦가지 이다.
데이터 바인딩을 하기 위해서는:
- 타깃객체의 BindingContext 속성이 반드시 소스객체를 가르켜야 한다.
- XAML에서 이것은 Binding마크업을 사용해 설정할 수 있다.
다음 코드는, accompanying sample의 일부이다.
HomagePage.xaml.cs
코드에서 먼저 바인딩될 소스객체(DetailsViewModel)을 바인딩 하였다. 이제, XAML에서 이것을 Binding마크업을 이용하여 UI와 연결만 해주면 된다.
HomePage.xaml
BindingContext는 특수한 속성으로 모든 페이지 클래스에 상속된다. BindingContext에 관한 추가적인 설명은 Form Data Bindings to MVVM을 참고하자.
Binding 마크업은 Path와 Mode속성을 가진다. Path는 바인딩 하고자 하는 원본객체의 속성명 가리키며, BInding마크업의 첫번째 요소로 사용할 경우 생략이 가능하다.
Mode속성은 속성값의 변화가 영향을 줄 방향에 대해 설정한다.
- OneWay 바인딩은 소스에서 타깃으로만 변경사항이 반영된다.
- TwoWay 바인딩은 양방향으로 적용된다. 즉, 소스와 타깃객체가 항상 동기화 된다.
- OnwWayToSource 바인딩은 타깃에서 소스로만 변경사항이 반영된다. 주로, 읽기전용의 바인딩 속성에 사용된다.
Mode값은 생략할 경우 OneWay가 기본이다.
속성 변경 알림
기본적으로, 타깃객체는 데이터 바인딩이 생성된 초기에만 소스객체의 값을 전달 받는다. UI가 데이터 소스와 동기화 되려면, 소스 객체에 수정이 생겼음을 타깃객체에 알려주어야 한다. 이 메커니즘은 INotifyPropertyChanged 인터페이스에 의해 제공된다. 이 인터페이스를 구현하면 어떤 데이터 컨트롤간에든 속성값의 변화를 알려줄 수 있다. 아래 코드든, 앞서 사용된 예제에서 사용한 DetailViewModel 의 소스코드 이다.
이 클래스는 Forename과 Surname속성이 변경될때마다 PropertyChanged이벤트를 발생시킨다. 즉, 사용자 이름이 입력될 경우 두개의 Label에 이름도 바로 반영이 된다.
정리
데이터 바인딩은 Xamarin.Forms 앱이 데이터를 표현하고 다루는 기본적인 기술이다. 더 자세한 설명은 Data Binging Basics와 Form Data Bindngs to MVVM에서 상세히 설명하고 있다.
다음에는, 컨트롤간의 데이터 바인딩과 데이터 변환과 같은 기술에 대해 다루어 보겠다.
원본출처: https://blog.xamarin.com/introduction-to-data-binding/