MelOn WP8 Developer Guide Hugeflow, Guntae Park
context MVVM 패턴 Ninjection DataLoadViewModel 프로젝트 구조. 주요 클래스 Function 설명 Build 매뉴얼
MVVM 패턴
MVVM 패턴 MVVM Light 멜론 프로젝트에서는 Galasoft의 MVVMLight 를 쓴다.
MVVM 패턴 -ViewModel Base 클래스 상속 기본적으로 GalaSoft.MvvmLight.ViewModelBase 를 상속받아서 만든다. ViewModelBase에는 쉽게 프로퍼티 설정을 할 수 있는 Set 함수와 Messenger 프레임워크를 사용할 수 있는 MessengerInstance 프로퍼티가 구현되어있다. 추가로 디자인 모드를 구분할 수 있는 프로퍼티도 IsInDesignModeStatic 프로퍼티도 구현되어있다.
MVVM 패턴 -ViewModel Property 만들기 ViewModel 클래스는 해당 프로퍼티가 View단에서 바인딩 되므로 프로퍼티 값이 변하는 것에 대해서 NotifyPropertyChanged 이벤트 호출을 해줘야 한다. 이부분에 대해서 자동으로 구현한 메서드가 Set<T> 메서드 이므로 프로퍼티의 set 구현 부분 에서 Set<T> 메서드를 활요하여 구현한다. 실제 구현 예는 아래와 같다. public class SampleViewModel : ViewModelBase { private bool _sampleData; public bool SampleData get { return _sampleData; } set Set<bool>(“SampleData”, ref _sampleData, value, fasle); } }
MVVM 패턴 -Command Command 만들기 Command 는 기본적으로 ICommand를 상속받아서 사용하거나 GalaSoft.MvvmLight.Command.RelayCommand 를 사용하면 된다. Viewmodel 에서 만든 Command는 View 에서 Button 등 Command 프로퍼티가 존재하는 컨트롤에 바인딩하거나 Command 를 특정조건에서 실행시킬 수 있는 Trigger에 바인딩하여 사용하게 된다. public class SampleViewModel : ViewModelBase { private ICommand _sampleCommand; public ICommand SampleCommand get { return _ sampleCommand; } set Set<ICommand>(“SampleCommand”, ref _ sampleCommand, value, fasle); } } public SampleViewModel() SampleCommand = new Relaycommand(new Action(object)=>{ //커멘드 실행시 할 액션 });
MVVM 패턴 -Command Command 상세 구현 ICommand 는 세가지를 구현해야 한다. bool CanExcute(object parameter) void Excute(object parameter) event CanExcuteChanged Command의 실행조건이나 실행방법을 좀더 긴밀히 조정하기 위해서는 위에 세가지를 모두 구현하는 것이 좋다 CanExcute 는 Command 바인딩이 처음 일어나거나 CanExcuteChanged 이벤트가 발생하거나 커멘드를 실행시키기 직전에 들어 온다. CanExcute 메서드에서 false를 반환할 경우 Button 의 경우 disabled 상태가 되며 Excute 메서드가 호출이 취소된다. Excute 에서는 실제 실행할 액션들을 짜주면 된다. CanExcuteChanged 는 내부적으로 변화가 있어 CanExcute 상태가 변화가 있을 대 외부에 (바인딩 된 Button 등의 View)에 알려 줄 때 사용되며 이 이벤트가 발생하면 CanExcute 메서드가 다시 호출되면서 Button 등의 상태가 적절하게 변경될 수 있다.
MVVM 패턴 -Messenger Messenger 사용하기. Messaging 프레임워크는 연관관계가 약한 두 객체 혹은 클래스 간의 데이터 교환이나 통신이 필요할 경우 사용한다. ViewModelBase 의 NotifyPropertyChanged 이벤트는 개별 인스턴스를 반드시 알고 있는 상태에서만 쓸 수 있고 이벤트를 엮어놓을 경우 이벤트를 엮은 클래스와 이벤트를 내보내는 클래스가 강한 연관관계가 맺어 져 메모리 해제에 문제(두 클래스가 모두 메모리 해제되는 상태가 되지 않는 한 어느 한쪽도 메모리 해제 되 지 않는다.)가 발생할 수 있다. Messenger 는 event 와 반대로 Messenger 인스턴스에 연락받을 Message 타입과 메신저를 해제할 때 쓸 객체 그리고 Messenger에 반응하여 할 액션을 등록해주면 된다. 관련되 메서드는 아래와 같다. Messenger.Register<T>(object recipient, Action<T> action) Messenger는 기본적으로 DefaultMessenger가 ViewModelBase 에서 생성되게 되고 기본적으로 이 메신 저의 Instance를 사용하게 된다. 하지만 ViewModelBase의 생성자에 Messenger 인스턴스를 새로 넣어줄 경우 이 Messenger 인스턴스가 해당 ViewModel의 Messaging 을 책임지게 된다.
Ninjection
Ninjection 목적 Injection 에 연관된 프레임워크를 사용하는 이유는 두가지이다. 첫번째로 객체들의 생성과 소멸주기를 임의적으로 중앙에서 통제해줌으로써 생성 되는 객체를 효율적으로 관리할 수 있게 해준다. 두번째로 객체의 생성을 인젝션 프레임워크에서 결정해줌으로써 각 클래스를 외 부 클래스의 영향을 받지 않게 독립적으로 짤 수 있다. 인터페이스에 따라 구현만 하면 그 외의 다양한 변화에 따르는 일들은 중앙에서 처리하기 때문에 개별적인 메 서드 구현이 훨씬 simple 해질 수 있다. Ninjection 은 이러한 Injection 프레임워크 중에 가장 가벼우면서도 오픈소 스로써 검증받고 있는 프레임워크이며 쓰기도 비교적 간단한 편이다.
Ninjection 사용 ServiceConfiguration에서 각 클래스의 생성 및 라이프 사이클에 대한 설정 을 해준다. ServiceLocator 클래스는 SingleTon과 인스턴스 형태가 모두 구현되는데 이는 Xaml상이나 Blend상에서 ServiceLocator를 참조할 수 있게끔 하기 위함이다. 그래서 ServiceLocator에서는 인스턴스 형태의 변수를 선언하는 것을 되도록 지양해야 한다. ServiceLocator를 통해 다른 위치에서 대부분의 ViewModel 및 기타 Manager나 API 에 대한 접근을 할 수 있게 된다.
DataLoadViewModel
DataLoadViewModel 목적 ViewModel 의 가장 기본적인 기능 중에 하나는 Api 로부터 데이터를 호출 하고 호출한 데이터를 적절한 데이터 프로퍼티에 설정해주는 것이다. 이런 작업은 반복적으로 이루어지며 View에서 표시되는 것은 제각각 이더라도 내부적으로 이뤄지는 과정은 대부분 대동소이한다. 그러므로 공통적인 인터 페이스로 묶을 수 있으며 이렇게 같은 인터페이스로 통일함으로써 전체 프 로그래밍의 통일성을 꾀할 수 있다.
DataLoadViewModel -상태 이 부분을 IsDataLoading과 IsDataLoaded 의 두가지 프로퍼티로 구분하 여 사용한다. 두가지 프로퍼티로 구분하는 것은 순전히 바인딩의 용이성을 위한 것이고 실제 코딩에서는 3가지 상태로 구분된다. DataLoadViewModelBase 에는 두가지 프러퍼티가 이미 세부 구현되어있 으며 IsDataLoaded 를 true로 설정할 경우 자동으로 IsDataLoading 은 false 로 바뀌게 되어있다.
DataLoadViewModel -Base 이 부분을 IsDataLoading과 IsDataLoaded 의 두가지 프로퍼티로 구분하 여 사용한다. 두가지 프로퍼티로 구분하는 것은 순전히 바인딩의 용이성을 위한 것이고 실제 코딩에서는 3가지 상태로 구분된다. DataLoadViewModelBase 에는 두가지 프러퍼티가 이미 세부 구현되어있 으며 IsDataLoaded 를 true로 설정할 경우 자동으로 IsDataLoading 은 false 로 바뀌게 되어있다.
DataLoadViweModel - 확장 LoadMoreDataViewModelBase LoadMore 동작을 하는 View를 가진 ViewModel을 생성할 때 Base 클래 스로 사용한다.
프로젝트 구조 솔루션 폴더, 프로젝트 구성, 참조 라이브러리
솔루션 폴더 구성 Assemblies Libraries Mocks Melon 프로젝트 Melon.UniTest 외부 라이브러리를 모아 놓은 폴더 Libraries 프로젝트를 구성하기 위한 기본적인 라이브러리 프로젝트를 모아놓은 폴더 Mocks 블랜드나 디자인 타임에서 데이타와 결합된 디자인이 제대로 보일 수 있게 하거나 테스트 를 위한 Mock 데이타 생성및 테스트를 위한 프로젝트를 모아놓은 폴더. Melon 프로젝트 기본 멜론 프로그램이 구축된 프로젝트. Melon.UniTest 멜론의 유닛테스트를 실행하기 위한 프로젝트.
프로젝트 설명 HugeFlow.Common HugeFlow.Controls Melon.Api Melon.Base 휴즈플로우에서 일반적으로 사용되던 라이브러리를 통합한 라이브러리 프로젝트. 폴더나 Resource 혹은 Linq의 Xelement등의 Extension 과 설정과 관련된 Base 클래스를 제공해준다. HugeFlow.Controls MarqueTextBlock 이나 MultiListBox나 ListBoxEx등 확장된 리스트 박스 기능을 사용할 수 있는 프로젝트가 있는 프로젝트 Melon.Api Melon API에 대응하는 클래스. MelonApi 클래스가 있으며 이를 통해 쉽게 Melon API 를 호출 할 수 있다. Melon.Base 멜론의 ViewModel 베이스 클래스나 인터페이스 글고 기본적으로 쓰이고 있는 데이타 모델들이 있는 프로젝트 Melon.Model 멜론에서 사용되는 DataModel이 정의되어있는 프로젝트 NoificationExtensions Tile이나 Toast등 앱의 Noti기능에 관련된 클래스 등을 모아놓은 프로젝트
프로젝트 설명 Melon.Api.Mock Melon.UniTest Melon 멜론 프로젝트의 테스트를 단위별로 테스트할 수 있게 하는 프로젝트. Melon 멜론의 기본 프로젝트.
참조 라이브러리 Callisto.dll 별점 컨트롤과 관련된 기능을 구현한 라이브러리. GalaSoft.MvvmLight HugeFlow.SLF Melon의 가사 형식을 분석하기 위한 라이브러리. Microsoft.Practices.ServiceLocation, Ninject : Dependency Injection을한 라이브러리
주요 Class Function 설명
공통 구조 Class (1) DataLoadViewModel IFiltering IDeletableViewModel LoadData , LoadMoreData 메서드가 구성되어있다. IFiltering 데이타를 필터링 Filter 프로퍼티와 FilterData 메서드로 구성. IDeletableViewModel Delete 메서드 구현(삭제) IEditableViewModel AddNew 메서드(새로 추가)와 Rename 메서드(이름바꾸기) 구현. IMultiSelectViewModel SelectAll, DeselectAll(전체 선택, 선택취소) 메서드 구현 SelectedItems(선택된 아이템들), IsMultiSelection(다중 선택을 지원하는지 안하는지), IsAnySelected(아이템이 하 나라도 선택이 되었는지) 프로퍼티 구현.
공통 구조 Class (2) ISearchViewModelBase ISelectableTitle IShareViewModel CurrentQuery(검색어) 프로퍼티가구현. ISelectableTitle 타이틀 선택이 가능한 ViewModel SelectedTitle(선택된 Title) 프로퍼티 구현. IShareViewModel 공유 기능을 지원하는 ViewModel ShareTitle(공유 제목), ShareDescription(공유 글), ShareUrl(공유 Url), ShareImagePath(공유 이미지 경로) 프로퍼티 들을 구현. ISongAction (SongViewModelBase) 곡과 관련된 ViewModel AddPlaylist(플레이리스트 추가), AddCurrentPlayList(현재 재생목록 추가), Download(다운로드), Play(재생), PlayAll(전체재생) 메서들 를 구현
공통 구조 Class (3) ISubMenuViewModel Command 류 Converter 류 SelectedSubMenu(하부 메뉴) 프로퍼티가구현. Command 류 CanExcute와 Excute 메서드 구현. CanExecuteChanged 이벤트 구현. Converter 류 Xaml에서 데이타를 특정 다른 데이타 형태로 컨버팅하는 클래스들 Convert와 ConvertBack 메서드를 구현.
CacheManager<T> SaveContents(T result, string key=“”) Result값을 Cache에 저장한다. LoadContents(strng key=“”) 해당 키 혹은 해당 컨텐츠 타입의 캐시된 데이타를 불러온다.
DownloadManager (1) GetDownloadInfos(List<int> downloadSongIds, int menuId, string productCode = "") 서버에서 다운로드 정보를 불러온다. GetRestoreDownloadList(string songList) 다운로드된 리스트를 불러온다. DownloadAsync(IEnumerable<DownloadSong> downloadSongList, bool isNavigation = false) 다운로드를 Background하기 시작. Download(bool isRestored) 다운로드하기. isRestored가 true면 다운로드 재시작. Pause() 다운로드 일시 정지. Download(IEnumerable<DownloadItem> downloadItems, bool isRestored) 다운로드 아이템을 다운로드 하기 시작 FailSongsDownload(bool useSelectedFailDownloadList = false) 실패했던 곡들을 다운로드한다. useSelectedFailDownloadList : true일 경우엔 선택된 리스트만 다운로드를 한다.
DownloadManager (2) AddFailDownloadItems(DownloadItem downloadFailItem) 실패한 다운로드 아이템 추가. GetDownloadTempFolder() 임시 다운로드 폴더 구하기. DoesTempFileExistAsync(string fileName) 해당 파일이름을 가진 임시 파일이 있는지 확인 GetDownloadFolder() 다운로드 폴더 구하기. Resume() : 다운로드 재개 Delete() : 다운로드 파일 삭제 GetBitrate(DownloadBitrate downloadBitrate) : bitrate 구하기 ReadyDownload(List<Song> songList) : 곡 다운로드 준비.
LocalContentsManager LocalSongs(저장된 곡들), LocalAlbums(저장된 앨범), LocalArtists(저장된 아티스트), LocalGenre(저장된 장르) 프로퍼티 구현. GetFolderChangedDateTime() 폴더가 변경된 시간을 구하기 GetFolderFileCount() 폴더의 파일 수 구하기. LoadSaveContentsList(uint index, uint count = 30, Func<StorageFile, bool> filterFunction = null) 저장된 컨텐츠를 구해온다. ConvertLocalSong(StorageFile file) 저장된 파일을 LocalSong Type으로 변환한다. Remove(LocalSong song) 저장된 LocalSong 지우기. Clear() : 리스트 초기화. (파일은 삭제되지 않는다.)
MediaPlayCenter 곡을 플레이하고 플레이리스트를 관리하는 매니저 CurrentPlaylist : 현재 재생 목록 Pause() :일시정지 Play() : 재생 Stop() : 정지 PlayNext() : 다음곡 재생 PlayPrev() : 이전곡 재생 AddPlaylist(IList SelectedItems) : 선택된 곡을 현재 재생목록에 추가. RemovePlaylist() : 선택된 곡을 현재 재생목록에서 삭제. SetPosition(TimeSpan timespan) : 특정 시간으로 Seek. ResetDeilverFlag() : Streaming 결산 초기화 CheckDeilverInformation(bool isShortSong = false) : Streaming 결산 체크 ShowDeliverNoti(int afterCount, int totalCount) : Streaming 관련 Notification popup을 띄워줌.
그 외 클래스 Excel 파일로 대체함.
Build 매뉴얼
1. 최신 버전 받기. Get Latest Version 클릭
2. Store용 앱 패키징 Melon프로젝트 우클릭 후 Store메뉴에서 Create App Package 클릭
3. Package 시작 Store에 올릴시 Yes 클릭 후 Sign in(윈도우 개발자 계정 로그인)
4. 버전 수정 및 Create 시작 버전 정보는 이전 업데이트 정 보보다 항상 상위로 수정.
패키지 완료 해당 위치에 패키징 완료. 이후 Launch Windows App Certification Kit 클릭.
앱 인증 시험 앱 인증 시험이 무사히 마쳐지 면 Package를 웹사이트에 올리면 됨. 이 때 확장자가 .appxupload 인 파일을 업로드하면 됨.