Windows2013. 1. 2. 15:49


MVC나 MVVC모델을 사용하여 화면과 데이터를 분리하여 개발할것을 권장한다. 좋은 메트오앱은 view model을 얼마나 잘 적용하였느냐가 관건이다.

여기서는 Data로써 GroceryItem을 정의한다. 따라서 다음과 같이 GroceryItem.cs파일을 작성한다.


name, store, quantity변수가 있고 각각 getter, setter가 정의되어 있는데 특히 setter에는 내부적으로 NotifiPropertyChanged가 호출되고 있으며 PropertyChanged라는 이벤트 핸들러를 호출하고 있다. 

여기서 중요한것이 데이터들에 observable속성을 이런식으로 부여할 수 있다는 것이다. 메트로UI의 특성중에 데이터바인딩도 아주 좋은 특징중 하나이다. observable한 속성을 준 데이터가 변경이 되면 UI에 바로 반영되도록 할수 있다.

System.ComponentModel.INotifyPropertyChanged인터페이스로 observable속성을 부여할 수 있고 이 속성이 변경될때마다  PropertyChangedEventHandler 이벤트로 화면에 표시되도록 할 수 있다. 

ViewModel클래스를 하나더 추가 하였는데 이 클래스(ViewModel.cs)는 사용자데이터와 애플리케이션의 상태정보를 포함한다.



GroceryItem의 컬렉션을 관리하는게 주임무인 클래스이다. ObservableCollection객체로 관리되고 있다. 그외에 stroeList, zipCode, 그리고 현재 선택된 아이템의 인덱스(selectedItemIndex)로 구성된다.

GroceryItem이 Observable이므로 데이터가 변경되면 자동으로 UI에도 반영되기를 기대한다. 여기서 사용한 ObservableCollection은 System.Collections.ObjectModel 네임스페이스에 해당되고 이 클래스는 기본적인 콜렉션의 특성과 리스트아이템이 추가, 삭제, 변경될때 이벤트를 발생시킨다.

ViewModel클래스는 INotifyPropertyChanged를 또한 구현하고 있는데 이는 view model에도 두가지 변수에 대해 observable속성을 주었기 때문이다. HomeZipCode와 SelectedItemIndex가 그것인데 이 정보가 변경될때도 이벤트가 발생하게 된다.

페이지를 새로 정의하여 그 페이지를 맨처음 화면에 띄우고자 한다. Page폴더에 ListPage라는 페이지를 정의할것인데 이 페이지가 처음화면에 뜨도록 하기 위해서는 App.xaml.cs에서 약간의 변경이 필요하다.


위 코드의 rootFrame.Navigate(typeof(Pages.ListPage));가 그 부분이다.


데이터관점에서 설명하기 위해 UI가 아닌 ListPage.xaml.cs의 구현코드먼저 설명하겠다.

ViewModel객체를 가지고 있으며 Store를 4가지, 그리고 GroceryList를 4가지 추가하였다. 여기서 가장 중요한 부분은 this.DataContext = viewModel; 부분이다. 메트로UI의 가장 큰 장점은 데이터바인딩을 통해 UI에 바로 적용되는 것이며 이를 위해 데이터의 소스를 지정하는 것이 중요하다 이 작업을 하는 것이 DataContext를 지정하는 것이다.

또한 List의 아이템이 변경되었을때 이벤트핸들러가 추가되어 있다. 여기서 viewModel.SelectedItemIndex에 인덱스를 업데이트한다. 이 작업은 내부적으로 observable 속성의 영향으로 PropertyChanged이벤트가 호출되면서 화면을 업데이트 하게 된다.


ListPage의 XAML코드는 다음과 같다.


Grid의 Background속성에 AppBackgroundColor라는 StandardStyle.xaml에 정의되지 않은 속성을 부여하였다. 이는 별도의 스타일을 추가로 정의하여 변경함을 의미한다. 이렇게 사용자가 원하는데로 스타일속성을 재정의하여 사용이 가능하다. 그리고 2개의 컬럼을 정의하여 화면은 두갈래로 나누었고 각 칼럼별로 row를 두개를 두어서 화면은 4분할 하였다.

좌측레이아웃은 row두개를 합쳐서 하나로 만들었다.

<StackPanel Grid.RowSpan="2"> 

이 패널은 헤더를 표시하는 TextBlock과 List뷰를 포함한다. 

우측레이아웃은 StackPanel이 두개가 준비되어있다. Grid.Column과 Grid.Row속성으로 위치를 조정할 수 있다.

디자인화면은 데이터가 동적이기 때문에 볼수 없다. ListView는 리스트내의 아이템들을 표시할것인데 다음과 같이 3가지 속성을 줌으로써 가능하다.


ItemSource속성은 어디에서 데이터들을 가져와야 하는지를 지정한다.

ItemTemplate은 ItemSource의 데이터들을 어떻게 화면에 표시할것인지를 결정한다. 이 템플릿도 별도의 스타일로 미리 지정된 스타일을 지정하는 방식으로 처리된다.

마지막으로 리스트아이템이 변경되었을 때 의 이벤트 핸들러를 추가해준다.


이제는 상세내역과 아이템이 선택되지 않았을 때 등을 표시하기 위한 페이지의 추가방법을 설명한다.

모든 컨트롤들과 코드를 하나의 파일안에 구현할 필요는 없다. 프로젝트를 관리하기 쉽게 하기 위해 여러개의 페이지를 만들고 필요에 따라 화면에 띄우면 된다. 간단한 데모로 NoItemSelected.xaml을 새로운 페이지로 프로젝트에 추가한다.


이 페이지는 Frame control을 통해서 화면에 보여질 수 있는데 위에서 ListPage.xaml의 Item Detail부분을 다음과 같이 Frame속성을 추가하여 x:Name을 지정하면 동적으로 코드레벨에서 특정 페이지를 표시할 수 있다.


<Frame x:Name="ItemDetailFrame">으로 프레임속성을 부여하였고 코드에서 ItemDetailFrame.Navigate(typeof(NoItemSelected)); 로 동적으로 페이지를 표시하였다.


동적으로 다른 페이지를 레이아웃에 집어넣어 표시되게 할 수 있다. ItemDetail.xaml을 새로운 페이지로 정의하여 데모를 보자.



페이지의 변경은 viewModel의 SelectedItemIndex가 변경될때마다 해주면 된다.

ListPage.xaml.cs의 생성자부분을 다음과 같이 수정한다.

SelectedItemIndex가 -1이 아니면 viewModel을 파라메터로 하여 ItemDetailFrame의 Page를 변경한다.

여기서 viewModel을 Navigate메서드에 인자로 넣었음을 중요하게 인지해야 한다.

이 인자는 ItemDetail page에서 OnNavigatedTo를 통해서 전달되어진다.


SetItemDetail메서드는 선택된 아이템정보를 화면에 표시하는 함수이다.

HandleItemChange메서드는 사용자가 입력한 정보를 아이템데이터에 업데이트 하는 함수이다.


Posted by 삼스