본문 바로가기
Programming/Windows Phone

생애 첫 번째 윈도우 폰7 애플리케이션 만들기 마지막회

by 강철 벼룩 2011. 6. 23.
 

최종회로 지난번에 만든 게임을 업데이트해서 다음 번에 게임을 실행했을 게임을 다시 시작할 있도록 게임의 상태를 저장할 있도록 만든다. 이를 위해 격리 저장소를 사용한다.


격리된
저장소는 관리된 애플리케이션이 지역 저장소에 정보를 저장하고 가져올 있게 해준다. 아키텍처는 실버라이트 4에서 사용한 것과 아주 비슷하다. 모든 I/O 작업은 격리 저장소의 범위로 제한되고 이들은 내부 운영체제 파일 시스템에 직접 접근하지 못한다.

격리된 저장소의 사용에서 생기는 몇 가지 이점은 다른 애플리케이션으로부터 데이터를 보호하고 할당량을 관리하며 애플리케이션이 자체의 고유 데이터만을 다루도록 보장하는 블라인드가 된다.


[어셈블리 참조와 다른 자원 추가하기]

격리된 저장소를 이용하려면 프로젝트에 헬퍼파일과 어셈블리 참조를 제공해야 한다.

1. [생애 번째 윈도우 7 애플리케이션 만들기 6] 단계를 완료했다면, 때의 솔루션을 계속 사용할 것이므로 해당 솔루션을 비주얼 스튜디오에서 연다.

2.  System.Servicemodel.Web 어셈블리에 대한 참조를 추가한다. [솔루션 탐색기]에서 [References] 오른 클릭하고 [Add Reference] 선택한다. [.NET] 탭을 선택하고 컴포넌트 목록에서 [System.Servicemodel.Web] 어셈블리를 선택한 뒤 [확인]을 클릭한다.

[그림 17] 프로젝트에 어셈블리 참조 추가하기


System.Servicemodel.Web 어셈블리는 분리된 저장소에 객체들을 보관하기 전에 애플리케이션이 JavaScript Object Notation (JSON) 사용해 객체를 직렬화하는데 사용하는  DataContractJsonSerializer 포함하고 있다.

3.  이제 분리된 저장소를 다루기 위해 헬퍼 클래스를 추가한다. [Solution Explorer]에서 프로젝트를 오른 클릭하고 [Add] 가리킨 [Existing Item] 선택한다. 랩의 소스 폴더(C:\WP7TrainingKitOffline\Labs\YourFirstWP7Application\Source\Assets) 찾아서 "IsolatedStorageHelper.cs" 선택하고 추가한다.

 "IsolatedStorageHelper" 클래스는 분리된 저장소에서 객체의 직렬화를 처리 하는 메서드를 포함하고 있다. 제공된 클래스는 실습에서 나중에 구현할 가지 메서드 스텁을 포함한다.


4.  참조와 헬퍼 클래스 파일을 추가한 , 솔루션 탐색기는 다음처럼 보인다.

 [그림 18] 새로 추가된 컴포넌트를 보여주는 솔루션 탐색기


[퍼즐 UI 업데이트]

이번
작업에서는 게임 페이지를 업데이트해서 사용자가 게임의 상태를 로드하고 저장, 삭제할 있는 가지 버튼을 제공한다. 이러한 목적을 위해 사용자 인터페이스의 XAML 마크업을 수정해 필요한 요소를 정의한 버튼에 대한 이벤트 핸들러를 생성한다. 마지막으로 "IsolatedStorageHelper" 클래스에서 필요로하는 메서드를 구현해리된 저장소에서 직렬화된 객체를 불러오고 저장, 삭제한다.


1. [솔루션 탐색기]에서 "PuzzlePage.xaml" 더블클릭해 해당 게임의 UI 담고 있는 페이지를 연다.

2. XAML 뷰로 전환한다.  해당 뷰를 변경하고 영역을 최대화 하기 위해, 디자이너 창의 오른편 끝에서 [XAML] 탭을 더블 클릭한다.

3. 다음의 강조된 XAML 마크업을 TapToContinueTextBlock 라는 마지막 "TextBlock" 요소 이후에 바로 삽입한다.

...
<Grid x:Name="LayoutRoot" Background="Transparent">
  <StackPanel Orientation="Vertical" VerticalAlignment="Top" Grid.Row="1">
    <Border x:Name="CongratsBorder"...>
      ...
    </Border>
    <Border x:Name="border"...>
      ...
    </Border>
    <TextBlock x:Name="TapToContinueTextBlock" HorizontalAlignment="Center" Text="Tap the picture to start the puzzle" TextWrapping="Wrap" Foreground="#FFD0D0D0" FontSize="17.333"/>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" >
      <Button x:Name="LoadButton" Content="Load" Margin="10" />
      <Button x:Name="SaveButton" Content="Save" Margin="10" />
      <Button x:Name="ClearStorageButton" Content="Clear" Margin="10" />
    </StackPanel>
  </StackPanel>
</Grid>
...

4. [디자인] 뷰로 전환하면 새로운 버튼이 추가된 사용자 인터페이스의 변경사항을 있다. 이를 위해서는 디자이너 창의 오른편 끝에서 [디자인] 탭을 더블 클릭한다.

[그림 19] 갱신된 사용자 인터페이스를 보여주는 디자인


5. 버튼에 대한 이벤트 핸들러를 정의한다. 디자이너 화면에서 "Load"라는 버튼을 클릭해 선택하고 [F4] 눌러 [속성] 창을 연다.

6. [속성] 창에서 [Events] 탭을 클릭해 사용할 있는 이벤트 목록을 가진 창을 표시한다. 목록에서 [Click] 이벤트를 찾아서 이벤트 옆에 있는 텍스트 상자에 "LoadButton_Click"이라고 입력한다. [엔터] 누르면 이름의 이벤트 핸들러를 생성하고 코드 숨김 파일을 열어 비주얼 스튜디오가 생성한 메서드 스텁을 표시한다.

7. "LoadButton_Click" 이벤트 핸들러의 본문에 다음의 강조된 코드를 삽입한다.

private void LoadButton_Click(object sender, RoutedEventArgs e)
{
  var gameState = IsolatedStorageHelper.GetObject<PuzzleState>("PuzzleState");
  if (gameState == null)
  {
    MessageBox.Show("Sorry, no game state found.", "Oops!", MessageBoxButton.OK);
  }
  else
  {
    // set game state
    this.game.SetState(gameState);
  }
}

8. 코드 편집기 창을 오른 클릭하고 [View Designer] 선택해 다시 디자인 뷰로 전환한다. 디자이너화면에서 "Save"라는 버튼을 클릭하고 [F4] 눌러 해당 속성 창을 연다.

9. [속성] 창에서 [Events] 탭을 클릭해 사용할 있는 이벤트 목록을 가진 창을 표시한다. 목록에서 [Click] 이벤트를 찾아서 이벤트 옆에 있는 텍스트 상자에 "SaveButton_Click"이라고 입력한다. [엔터] 누르면 이름의 이벤트 핸들러를 생성하고 코드 숨김 파일을 열어 비주얼 스튜디오가 생성한 메서드 스텁을 표시한다.

10. "SaveButton_Click" 이벤트 핸들러의 본문에 다음의 강조된 코드를 삽입한다.

 

private void SaveButton_Click(object sender, RoutedEventArgs e)
{
// save game state
  PuzzleState gameState = this.game.GetState();
  IsolatedStorageHelper.SaveObject("PuzzleState", gameState);
}


11. 다시 한번 코드 편집기 창을 오른 클릭하고 [View Designer] 선택해 다시 디자인 뷰로 전환한다. 디자이너화면에서 "Clear"라는 버튼을 클릭하고 [F4] 눌러 해당 속성 창을 연다.

12. [속성] 창에서 [Events] 탭을 클릭해 사용할 있는 이벤트 목록을 가진 창을 표시한다. 목록에서 [Click] 이벤트를 찾아서 이벤트 옆에 있는 텍스트 상자에 "ClearStorageButton_Click"이라고 입력한다. [엔터] 누르면 이름의 이벤트 핸들러를 생성하고 코드 숨김 파일을 열어 비주얼 스튜디오가 생성한 메서드 스텁을 표시한다.

13. "ClearStorageButton_Click" 이벤트 핸들러의 본문에 다음의 강조된 코드를 삽입한다.

private void ClearStorageButton_Click(object sender, RoutedEventArgs e)
{
// remove state and image
  IsolatedStorageHelper.DeleteObject("PuzzleState");
}

14. [솔루션 탐색기]에서 "IsolatedStorageHelper.cs" 파일을 더블 클릭해서 연다.

15. [GetObject<T>] 메서드를 찾아서 다음의 강조된 코드로 바디를 대체한다.


 

public static T GetObject<T>(string key)
{
  if (IsolatedStorageSettings.ApplicationSettings.Contains(key))
  {
    string serializedObject = IsolatedStorageSettings.ApplicationSettings[key].ToString();
    return Deserialize<T>(serializedObject);
  }

return default(T);
}


 

GetObject<T> 메서드는 주어진 개체 키로리된 저장소에서 객체를 가져온다.  격리된 저장소에서 - 쌍의 딕셔너리를 저장하는 IsolatedStorageSettings 이용한다. 객체들은 System.ServiceModel.Web

어셈블리에서 제공된 DataContractJsonSerializer 사용해 직렬화된 형식으로 저장되는데, 메서드는 객체를 JSON으로 직렬화하고 JSON 데이터를 객체로 역직렬화한다.


16. 다음의 강조된 코드를 SaveObject<T> 메서드의 바디에 넣는다.

public static void SaveObject<T>(string key, T objectToSave)
{
    string serializedObject = Serialize(objectToSave);
    IsolatedStorageSettings.ApplicationSettings[key] = serializedObject;
}

SaveObject<T> 메서드는 주어진 개체 키로리된 저장소에 개체를 저장한다.

17. 마지막으로 다음의 강조된 코드를 사용해 [DeleteObject<T>] 메서드를 구현한다.

public static void DeleteObject(string key)
{
  IsolatedStorageSettings.ApplicationSettings.Remove(key);
}

DeleteObject 메서드는리된 저장소에서 주어진 개체의 키로 개체를 제거한다


18. 최종 변경을 테스트 하기 위해 [F5] 눌러 애플리케이션을 빌드하고 에뮬레이터로 다시 한번 배포한다. 잠깐 기다리면 시작 화면이 나타나고 [START] 버튼을 클릭해 새로운 게임을 시작한다.

19. 게임 페이지에서 [Load] 클릭해 저장된 상태의 복구를 시도한다. 아마 저장된 상태가 없다는 오류 메시지를 뿌릴 것이다. [OK] 클릭해 오류 메시지를 해제한다.

[그림 20] 이전 상태가 없을 load 작업이 실패한다.


20. 보드에서 퍼즐의 조각 일부를 드래그 한다. 하나 이상의 조각을 배치하는 경우 쉽게 기억할 있는 패턴으로 하는것이 상책이다. 나중에 게임 상태를 다시 로드한 동일한 패턴인지를 알아보기가 훨씬 쉽다.

21. [Save] 클릭해 게임의 현재 상태를 저장한다.

22. 이제 다른 배열로 조각을 계속 이동한 다음 이번에는 게임의 상태를 저장하지는 않는다.

23. 다시 한번 [Load] 클릭해 이전의 저장된 상태를 복원한다. 이번에는 해당 조각의 위치가 원래 저장했던 게임 상태와 동일한 패턴으로 복구된다.

24. 에뮬레이터 윈도우에서 뒤로 가기 버튼(<-) 눌러 시작화면을 담은 페이지로 간다. 다음 뒤로 가기 버튼을 다시 클릭해 애플리케이션을 나가면 [Quick Launch] 메뉴를 표시한다.

25.  이제, [Quick Launch] 메뉴에서 해당 애플리케이션을 시작하기 위해 다시 한번 [WindowsPhonePuzzle] 클릭한다.


[그림 21] Quick Launch 메뉴에서 애플리케이션을 시작한다.


26. [START] 클릭해 새로운 게임을 시작하고 게임 페이지에서 [Load] 클릭해 이전 상태를 로드 한다. 보드 패턴이 이전에 애플리케이션에서 저장했던 상태인지 확인한다.

27.  [Clear] 클릭해 분리된 저장소에서 저장된 상태를 지운다.

28. 이제 다시 한번 [Load] 클릭하면 앞서 저장된 상태가 없을 보았던 동일한 오류 메시지를 받게 된다.