정보
요청한 주제가 아래에 표시됩니다. 그러나 이 주제는 이 라이브러리에 포함되지 않습니다.

Windows Phone 8의 Model-View-ViewModel 패턴 구현

2014-06-18

적용 대상: Windows Phone 8 및 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

 

이 연습에서는 MVVM(Model-View-ViewModel) 디자인 패턴을 구현하는 간단한 앱을 빌드합니다. MVVM은 사용자 인터페이스에서 데이터를 분리하는 방법입니다. MVVM을 통해 개발자는 데이터 모델을 코딩하고 디자이너는 사용자 인터페이스를 만들 수 있습니다. 앱에서 Model(데이터)은 C# 클래스이고 View(사용자 인터페이스)는 XAML 사용자 컨트롤입니다. Model과 View 간의 링크인 ViewModel도 C# 클래스입니다. Model-View-ViewModel 디자인 패턴에 대한 자세한 내용은 이 항목의 끝에 나오는 링크를 참조하세요.

이 연습에서 만드는 앱은 사용자가 동영상 게임에서 도전 과제를 추적할 수 있는 "게임 추적기"입니다. 사용자는 수집한 아이템 수와 완료한 레벨을 저장할 수 있습니다. 이 앱의 완료된 버전을 다운로드하려면 Model-View-ViewModel 샘플을 참조하세요.

이 연습에서는 다음 작업을 수행합니다.

  • Model 1개, ViewModel 1개 및 View 2개를 만듭니다.

  • XAML 바인딩을 사용하여 View를 데이터에 연결합니다.

  • 사용자 지정 데이터 변환기를 만듭니다.

  • 앱으로 이동하거나 앱을 닫을 때 페이지 상태를 유지합니다.

  • 앱 데이터를 격리된 저장소에 저장합니다.

  • 앱 바를 사용하여 저장 기능을 노출합니다.

완성된 솔루션에는 다음 구성 요소가 포함됩니다.

완성된 앱은 다음과 같습니다.

The project files in Solution Explorer.The app running in the emulator.

이 연습을 완료하려면 Windows Phone SDK 가 설치되어 있어야 합니다.

먼저 이름이 MVVMTestApp인 새 Windows Phone 앱 프로젝트를 만듭니다. 이후 단계에서 앱 이름을 MVVMTestApp으로 가정하는 코드를 앱에 추가합니다. 앱에 다른 이름을 선택한 경우 코드에서 네임스페이스 참조를 변경해야 합니다.

앱 프로젝트를 만들려면

  1. Visual Studio의 파일 메뉴에서 새로 만들기를 가리킨 다음 프로젝트를 클릭합니다.

    새 프로젝트 대화 상자가 나타납니다.

  2. 왼쪽 창에서 설치된 템플릿을 클릭하고 Visual C# 또는 Visual Basic을 확장한 다음 Windows Phone을 클릭합니다.

  3. 프로젝트 형식 목록에서 Windows Phone 앱 을 클릭합니다.

  4. 이름 상자에 MVVMTestApp를 입력합니다.

  5. 확인을 클릭합니다.

    새 앱 프로젝트가 생성되고 Visual Studio에서 열립니다.

  6. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  7. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

이 Model-View-ViewModel 패턴 구현을 위해 프로젝트 파일을 폴더로 구성합니다. 이 절차에서는 Model, ViewViewModel이라는 새 폴더 3개를 만듭니다.

Model-View-ViewModel 파일을 구성하려면

  1. 솔루션 탐색기에서 MVVMTestApp 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 추가를 가리킨 다음 새 폴더를 클릭합니다. 새 폴더가 프로젝트에 추가되고 이름이 편집 모드로 표시됩니다. 폴더 이름으로 Model을 입력하고 Enter 키를 누릅니다.

  2. 솔루션 탐색기에서 MVVMTestApp 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 추가를 가리킨 다음 새 폴더를 클릭합니다. 새 폴더가 프로젝트에 추가되고 이름이 편집 모드로 표시됩니다. 폴더 이름으로 View을 입력하고 Enter 키를 누릅니다.

  3. 솔루션 탐색기에서 MVVMTestApp 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 추가를 가리킨 다음 새 폴더를 클릭합니다. 새 폴더가 프로젝트에 추가되고 이름이 편집 모드로 표시됩니다. 폴더 이름으로 ViewModel을 입력하고 Enter 키를 누릅니다.

이 절차에서는 데이터 모델을 만듭니다. 모델은 Accomplishment라는 단일 클래스입니다. Accomplishment 클래스는 INotifyPropertyChanged 인터페이스 및 PropertyChanged 이벤트를 구현합니다. 이렇게 하면 속성 값이 변경될 때 클래스에서 해당 뷰에 알릴 수 있으며, 뷰가 변경 내용에 따라 사용자 인터페이스를 업데이트할 수 있습니다. 이 앱에서 사용자는 CountCompleted 속성만 변경할 수 있으므로 해당 속성에서만 PropertyChanged 이벤트를 발생하면 됩니다. 최종 절차에서 데이터 바인딩을 테스트합니다.

Accomplishment 클래스에는 다음 속성이 포함됩니다.

속성

설명

이름

도전 과제의 이름입니다.

유형

도전 과제의 유형("아이템" 또는 "레벨")입니다.

Count

아이템의 경우: 수집한 아이템의 수입니다.

완료

레벨의 경우: 레벨이 완료되었는지 여부입니다.

데이터 모델을 만들려면

  1. 솔루션 탐색기에서 Model 폴더를 마우스 오른쪽 버튼으로 클릭하고 추가를 가리킨 다음 클래스를 클릭합니다.

    해당 클래스 템플릿이 선택된 상태로 새 항목 추가 대화 상자가 나타납니다.

    Visual Basic 참고Visual Basic 참고:

    Visual Basic의 경우 코드 파일 템플릿을 수동으로 선택해야 합니다.

  2. 이름 상자에 Accomplishment.cs 또는 Accomplishment.vb를 입력한 다음 추가를 클릭합니다.

    Model 폴더의 프로젝트에 새 클래스가 추가되고 코드 편집기에서 열립니다.

  3. 코드를 다음 코드로 바꿉니다.

    using System;
    using System.ComponentModel;
    
    
    namespace MVVMTestApp.Model
    {
        public class Accomplishment : INotifyPropertyChanged
        {
            // The name of the accomplishment.
            public string Name { get; set; }
    
            // The type of the accomplishment, Item or Level.
            public string Type { get; set; }
    
            // The number of each item that has been collected.
            private int _count;
            public int Count
            {
                get
                {
                    return _count;
                }
                set
                {
                    _count = value;
                    RaisePropertyChanged("Count");
                }
            }
    
            // Whether a level has been completed or not
            private bool _completed;
            public bool Completed
            {
                get
                {
                    return _completed;
                }
                set
                {
                    _completed = value;
                    RaisePropertyChanged("Completed");
                }
            }
    
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void RaisePropertyChanged(string propertyName)
            {
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
    
            // Create a copy of an accomplishment to save.
            // If your object is databound, this copy is not databound.
            public Accomplishment GetCopy()
            {
                Accomplishment copy = (Accomplishment)this.MemberwiseClone();
                return copy;
            }
        }
    }
    
  4. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  5. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

이 절차에서는 Model과 View 간의 링크인 ViewModel을 만듭니다. ViewModel은 Model의 개체(이 경우 Accomplishment 개체)가 포함된 컬렉션입니다. ViewModel은 ObservableCollection<T>을 사용합니다. 이렇게 하면 컬렉션의 항목이 변경될 때 해당 뷰에 알릴 수 있으며, 뷰가 변경 내용에 따라 사용자 인터페이스를 업데이트할 수 있습니다.

ViewModel에는 달성 과제 컬렉션을 가져오는 코드가 포함되어 있습니다. 먼저 격리된 저장소를 검사하여 달성 과제가 이미 저장되었는지 확인합니다. 저장된 경우 격리된 저장소를 사용하여 컬렉션을 채웁니다. 저장되지 않은 경우 컬렉션에 기본 달성 과제를 채웁니다. 이후 절차에서는 달성 과제를 격리된 저장소에 저장하는 코드를 추가합니다.

ViewModel을 만들려면

  1. 솔루션 탐색기에서 ViewModel 폴더를 마우스 오른쪽 버튼으로 클릭하고 추가를 가리킨 다음 클래스를 클릭합니다.

    해당 클래스 템플릿이 선택된 상태로 새 항목 추가 대화 상자가 나타납니다.

    Visual Basic 참고Visual Basic 참고:

    Visual Basic의 경우 코드 파일 템플릿을 수동으로 선택해야 합니다.

  2. 이름 상자에 ViewModel.cs 또는 ViewModel.vb를 입력한 다음 추가를 클릭합니다.

    ViewModel 폴더의 프로젝트에 새 클래스가 추가되고 코드 편집기에서 열립니다.

  3. 코드를 다음 코드로 바꿉니다.

    using System;
    using System.Windows;
    using System.Collections.ObjectModel;
    using System.IO.IsolatedStorage;
    using MVVMTestApp.Model;
    
    namespace MVVMTestApp.ViewModelNamespace
    {
        public class ViewModel
        {
            public ObservableCollection<Accomplishment> Accomplishments { get; set; }
    
    
            public void GetAccomplishments()
            {
                if (IsolatedStorageSettings.ApplicationSettings.Count > 0)
                {
                    GetSavedAccomplishments();
                }
                else
                {
                    GetDefaultAccomplishments();
                }
            }
    
    
            public void GetDefaultAccomplishments()
            {
                ObservableCollection<Accomplishment> a = new ObservableCollection<Accomplishment>();
    
                // Items to collect
                a.Add(new Accomplishment() { Name = "Potions", Type = "Item" });
                a.Add(new Accomplishment() { Name = "Coins", Type = "Item" });
                a.Add(new Accomplishment() { Name = "Hearts", Type = "Item" });
                a.Add(new Accomplishment() { Name = "Swords", Type = "Item" });
                a.Add(new Accomplishment() { Name = "Shields", Type = "Item" });
    
                // Levels to complete
                a.Add(new Accomplishment() { Name = "Level 1", Type = "Level" });
                a.Add(new Accomplishment() { Name = "Level 2", Type = "Level" });
                a.Add(new Accomplishment() { Name = "Level 3", Type = "Level" });
    
                Accomplishments = a;
                //MessageBox.Show("Got accomplishments from default");
            }
    
    
            public void GetSavedAccomplishments()
            {
                ObservableCollection<Accomplishment> a = new ObservableCollection<Accomplishment>();
    
                foreach (Object o in IsolatedStorageSettings.ApplicationSettings.Values)
                {
                    a.Add((Accomplishment)o);
                }
    
                Accomplishments = a;
                //MessageBox.Show("Got accomplishments from storage");
            }
        }
    }
    
  4. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  5. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

이 절차에서는 아이템 달성 과제를 표시할 뷰를 만듭니다. 이후 절차에서는 이 뷰를 페이지에 표시하고 데이터 컨텍스트를 설정하여 ViewModel에 연결합니다. 이 뷰에는 코드 숨김이 없습니다.

뷰는 데이터에 바인딩된 ListBox가 포함된 사용자 컨트롤입니다. ListBox의 각 항목에는 다음 세 개의 열이 있습니다.

이름

바인딩 모드

설명

이름

단방향

아이템의 이름입니다.

Count

양방향

(텍스트 상자) 수집한 아이템 수입니다. 사용자가 이 값을 입력하며, 데이터 바인딩을 통해 모델이 업데이트됩니다.

검사

단방향

데이터가 올바르게 업데이트되고 있는지를 확인하는 검사입니다. 사용자가 이전 열의 개수를 업데이트하면 결과가 즉시 이 열에 나타납니다.

첫 번째 뷰를 만들려면

  1. 솔루션 탐색기에서 View 폴더를 마우스 오른쪽 버튼으로 클릭하고 추가를 가리킨 다음 새 항목을 클릭합니다.

    새 항목 추가 대화 상자가 나타납니다.

  2. 파일 형식 목록에서 Windows Phone 사용자 정의 컨트롤을 클릭합니다.

  3. 이름 상자에 ItemView.xaml을 입력한 다음 추가를 클릭합니다.

    View 폴더의 프로젝트에 새 XAML 파일이 추가되고 디자이너에서 열립니다. 기본적으로 XAML 파일에는 빈 GRID 요소가 있습니다.

  4. GRID 요소에 다음 코드를 추가합니다.

    <ListBox ItemsSource="{Binding}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="200"/>
                        <ColumnDefinition Width="80"/>
                        <ColumnDefinition Width="100"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock x:Name="Item" Text="{Binding Path=Name, Mode=OneWay}" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" />
                    <TextBox x:Name="Count" Text="{Binding Path=Count, Mode=TwoWay}" Grid.Column="1" TextAlignment="Center" InputScope="Number"/>
                    <TextBlock x:Name="Check" Text="{Binding Path=Count, Mode=OneWay}" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    
  5. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  6. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

이 절차에서는 레벨 달성 과제를 표시할 뷰를 만듭니다. 이후 절차에서는 이 뷰를 페이지에 표시하고 데이터 컨텍스트를 설정하여 ViewModel에 연결합니다.

뷰는 데이터에 바인딩된 ListBox가 포함된 사용자 컨트롤입니다. ListBox의 각 항목에는 다음 세 개의 열이 있습니다.

이름

바인딩 모드

설명

수준

단방향

레벨의 이름입니다.

완료

양방향

(확인란) 레벨이 완료되었는지 여부입니다. 사용자가 이 값을 선택하며, 데이터 바인딩을 통해 모델이 업데이트됩니다.

검사

단방향

데이터가 올바르게 업데이트되고 있는지를 확인하는 검사입니다. 사용자가 이전 열의 완료 데이터를 업데이트하면 결과가 즉시 이 열에 나타납니다.

이 View에서는 한 가지 작업을 추가로 수행합니다. 사용자가 레벨을 완료하지 않은 경우 확인란을 사용할 수 있게 하려고 합니다. 사용자가 확인란을 선택하여 레벨이 완료되었음을 나타내면 확인란을 사용할 수 없게 하려고 합니다. 즉, 확인란의 사용 상태는 확인란 값의 반대입니다. 데이터 바인딩을 통해 확인란의 사용 상태를 자동으로 설정할 수 있지만, 먼저 부울 값의 반대를 반환하는 사용자 지정 데이터 변환기를 만들어야 합니다. 사용자 지정 데이터 변환기는 IValueConverter 인터페이스를 구현하고 ConvertConvertBack 메서드를 구현하는 클래스입니다. 최종 절차에서 데이터 변환기를 테스트합니다.

두 번째 뷰를 만들려면

  1. 솔루션 탐색기에서 View 폴더를 마우스 오른쪽 버튼으로 클릭하고 추가를 가리킨 다음 새 항목을 클릭합니다.

    새 항목 추가 대화 상자가 나타납니다.

  2. 파일 형식 목록에서 Windows Phone 사용자 정의 컨트롤을 클릭합니다.

  3. 이름 상자에 LevelView.xaml을 입력한 다음 추가를 클릭합니다.

    View 폴더의 프로젝트에 새 XAML 파일이 추가되고 디자이너에서 열립니다.

사용자 지정 데이터 바인딩 변환기를 만들려면

  1. 솔루션 탐색기에서 LevelView.xaml을 마우스 오른쪽 버튼으로 클릭한 다음 코드 보기를 클릭합니다.

    코드 숨김 파일이 코드 편집기에 열립니다.

  2. 코드를 다음 코드로 바꿉니다.

    using System;
    using System.Windows.Controls;
    using System.Globalization;
    
    namespace MVVMTestApp.View
    {
        public partial class LevelView : UserControl
        {
            public LevelView()
            {
                InitializeComponent();
            }
        }
    
    
        public class BoolOpposite : System.Windows.Data.IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                bool b = (bool)value;
                return !b;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                string s = value as string;
                bool b;
    
                if (bool.TryParse(s, out b))
                {
                    return !b;
                }
                return false;
            }
        }
    }
    
  3. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  4. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

두 번째 뷰의 사용자 인터페이스를 만들려면

  1. 솔루션 탐색기에서 LevelView.xaml을 두 번 클릭하여 디자이너에서 엽니다.

  2. XAML 편집기의 <UserControl> 태그에서 다른 네임스페이스 선언과 함께 다음 코드를 추가합니다.

    C# 버전:

    xmlns:src="clr-namespace:MVVMTestApp.View"
    

    Visual Basic 버전:

    xmlns:src="clr-namespace:MVVMTestApp"
    
  3. USERCONTROL 요소와 GRID 요소 사이에 다음 코드를 추가합니다.

    <UserControl.Resources>
        <src:BoolOpposite x:Key="BoolOpposite"/>
    </UserControl.Resources>
    
  4. GRID 요소에 다음 코드를 추가합니다.

    <ListBox ItemsSource="{Binding}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="200"/>
                        <ColumnDefinition Width="80"/>
                        <ColumnDefinition Width="100"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock x:Name="Level" Text="{Binding Path=Name, Mode=OneWay}" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    <CheckBox x:Name="Completed" IsChecked="{Binding Path=Completed, Mode=TwoWay}" Grid.Column="1" HorizontalAlignment="Center" IsEnabled="{Binding Path=Completed, Converter={StaticResource BoolOpposite}}"/>
                    <TextBlock x:Name="Check" Text="{Binding Path=Completed, Mode=OneWay}" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    
  5. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  6. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

이 절차에서는 기본 앱 페이지를 만듭니다. 기본 페이지에는 이전에 만든 두 개의 뷰가 포함되어 있습니다. 첫 번째 뷰에는 항목이 있고 두 번째 뷰에는 수준이 있습니다. 코드에서 먼저 새 ViewModel 인스턴스를 만들고 사용하여 데이터를 가져옵니다. 그런 다음 View에 표시할 데이터를 ViewModel에서 선택하여 각 View를 ViewModel에 연결합니다. 이후 절차에서는 사용자가 앱을 닫았다가 다시 돌아올 때 페이지 상태를 유지하는 코드를 추가합니다.

기본 앱 페이지의 사용자 인터페이스를 만들려면

  1. 솔루션 탐색기에서 MainPage.xaml을 두 번 클릭하여 디자이너에서 이 파일을 엽니다.

  2. 디자인 보기에서 텍스트 블록 MY APPLICATION을 클릭합니다.

  3. 속성 창에서 Text 속성을 MVVM Test App으로 설정합니다.

  4. 디자인 보기에서 텍스트 블록 페이지 이름을 클릭합니다.

  5. 속성 창에서 Text 속성을 game tracker으로 설정합니다.

  6. XAML 편집기의 <phone> 태그에서 다른 네임스페이스 선언과 함께 다음 코드를 추가합니다.

    C# 버전:

    xmlns:views="clr-namespace:MVVMTestApp.View"
    

    Visual Basic 버전:

    xmlns:src="clr-namespace:MVVMTestApp"
    
  7. 기본적으로 프로젝트에 추가되는 ContentPanel GRID 요소를 찾습니다. 이 요소는 다음과 같습니다.

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
    
  8. 기본 ContentPanel GRID 요소를 다음 코드로 바꿉니다.

    주의주의:

    ContentPanel GRID 요소 바로 뒤에 오는 LayoutRoot GRID 요소의 끝 태그를 삭제하지 않도록 주의하세요.

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <StackPanel>
            <TextBlock Text="Items Collected" Foreground="{StaticResource PhoneAccentBrush}" Style="{StaticResource PhoneTextLargeStyle}" />
            <views:ItemView x:Name="ItemViewOnPage" Height="200"/>
    
            <TextBlock Text="Levels Completed" Foreground="{StaticResource PhoneAccentBrush}" Style="{StaticResource PhoneTextLargeStyle}" />
            <views:LevelView x:Name="LevelViewOnPage" Height="200"/>
        </StackPanel>
    </Grid>
    
  9. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  10. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

기본 앱 페이지의 코드를 추가하려면

  1. 솔루션 탐색기에서 MainPage.xaml을 마우스 오른쪽 버튼으로 클릭한 다음 코드 보기를 클릭합니다.

    코드 숨김 파일이 코드 편집기에 열립니다.

  2. 코드를 다음 코드로 바꿉니다.

    using System;
    using System.Linq;
    using System.Windows;
    using Microsoft.Phone.Controls;
    using MVVMTestApp.ViewModelNamespace;
    
    namespace MVVMTestApp
    {
        public partial class MainPage : PhoneApplicationPage
        {
            private ViewModel vm;
    
            // Constructor
            public MainPage()
            {
                InitializeComponent();
                vm = new ViewModel();
            }
    
    
            protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
                base.OnNavigatedTo(e);
    
                // Later, you will replace this next line with something better.
                vm.GetAccomplishments();
    
    
                // There are two different views, but only one view model.
                // So, use LINQ queries to populate the views.
    
                // Set the data context for the Item view.
                ItemViewOnPage.DataContext = from Accomplishment in vm.Accomplishments where Accomplishment.Type == "Item" select Accomplishment;
    
                // Set the data context for the Level view.
                LevelViewOnPage.DataContext = from Accomplishment in vm.Accomplishments where Accomplishment.Type == "Level" select Accomplishment;
    
                // If there is only one view, you could use the following code
                // to populate the view.
                //AccomplishmentViewOnPage.DataContext = vm.Accomplishments;
            }
        }
    }
    
  3. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  4. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

이 절차에서는 페이지 상태를 유지하는 코드를 추가합니다. 사용자가 앱을 닫았다가 다시 돌아오는 경우 페이지 상태를 유지하려고 합니다. 사용자가 앱 목록에서 앱의 새 인스턴스를 시작하는 경우 페이지 상태를 유지하지 않으려고 합니다.

먼저 IsLaunching이라는 속성 한 개가 있는 유틸리티 클래스를 만듭니다. 이 속성을 사용하여 사용자가 앱의 새 인스턴스를 시작했는지 여부를 추적합니다. 이 앱에서 유지해야 하는 상태는 ViewModel뿐입니다. Windows Phone 에서는 페이지 상태 개체를 제공하며, 전체 ViewModel을 상태에 한 개의 개체로 저장할 수 있습니다. ViewModel 컬렉션의 항목을 개별적으로 저장할 필요는 없습니다. 사용자가 앱으로 돌아오면 상태에서 ViewModel을 검색하고 View를 ViewModel에 바인딩할 수 있습니다. 최종 절차에서 페이지 상태를 테스트합니다.

페이지 상태를 유지하려면

  1. 솔루션 탐색기에서 MVVMTestApp 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 추가를 가리킨 다음 클래스를 클릭합니다.

    해당 클래스 템플릿이 선택된 상태로 새 항목 추가 대화 상자가 나타납니다.

    Visual Basic 참고Visual Basic 참고:

    Visual Basic의 경우 코드 파일 템플릿을 수동으로 선택해야 합니다.

  2. 이름 상자에 StateUtilities.cs 또는 StateUtilities.vb를 입력한 다음 추가를 클릭합니다.

    프로젝트에 새 클래스가 추가되고 코드 편집기에서 열립니다.

  3. 코드를 다음 코드로 바꿉니다.

    using System;
    
    namespace MVVMTestApp
    {
        public static class StateUtilities
        {
            private static Boolean isLaunching;
    
            public static Boolean IsLaunching
            {
                get { return isLaunching; }
                set { isLaunching = value; }
            }
        }
    }
    
  4. 솔루션 탐색기에서 App.xaml을 마우스 오른쪽 버튼으로 클릭한 다음 코드 보기를 클릭합니다.

    코드 숨김 파일이 코드 편집기에 열립니다.

  5. Application_Launching 메서드를 찾아 다음 코드로 바꿉니다.

    private void Application_Launching(object sender, LaunchingEventArgs e)
    {
        StateUtilities.IsLaunching = true;
    }
    
  6. Application_Activated 메서드를 찾아 다음 코드로 바꿉니다.

    private void Application_Activated(object sender, ActivatedEventArgs e)
    {
        StateUtilities.IsLaunching = false;
    }
    
  7. 솔루션 탐색기에서 MainPage.xaml을 마우스 오른쪽 버튼으로 클릭한 다음 코드 보기를 클릭합니다.

    코드 숨김 파일이 코드 편집기에 열립니다.

  8. MainPage 클래스의 OnNavigatedTo 메서드에서 GetAccomplishments 호출을 찾습니다. 이 요소는 다음과 같습니다.

    // Later, you will replace this next line with something better.
    vm.GetAccomplishments();
    

    이 호출을 다음 코드로 바꿉니다.

    if (!StateUtilities.IsLaunching && this.State.ContainsKey("Accomplishments"))
    {
        // Old instance of the application
        // The user started the application from the Back button.
        
        vm = (ViewModel)this.State["Accomplishments"];
        //MessageBox.Show("Got data from state");
    }
    else
    {
        // New instance of the application
        // The user started the application from the application list,
        // or there is no saved state available.
        
        vm.GetAccomplishments();
        //MessageBox.Show("Did not get data from state");
    }
    
  9. MainPage 클래스의 OnNavigatedTo 메서드 뒤에 다음 코드를 추가합니다.

    protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
    {
        base.OnNavigatedFrom(e);
    
        if (this.State.ContainsKey("Accomplishments"))
        {
            this.State["Accomplishments"] = vm;
        }
        else
        {
            this.State.Add("Accomplishments", vm);
        }
    
        StateUtilities.IsLaunching = false;
    }
    
  10. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  11. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

이 절차에서는 앱 데이터를 격리된 저장소에 저장하는 코드를 추가합니다. 이 앱의 경우 텍스트 파일이나 로컬 데이터베이스가 아니라 격리된 저장소 설정 사전에 데이터를 저장합니다. 격리된 저장소 형식에 대한 자세한 내용은 Windows Phone의 데이터를 참조하세요. 로컬 설정 사전에 대한 자세한 내용은 IsolatedStorageSettings 클래스를 참조하세요. 최종 절차에서 격리된 저장소를 테스트합니다.

격리된 저장소에 저장하는 데이터는 데이터 바인딩된 Accomplishment 개체입니다. 사용자가 앱을 종료하면 Windows Phone 이 자동으로 Save를 호출하여 격리된 저장소를 저장합니다. 사용자가 앱을 종료할 때가 아니라 저장 버튼을 명시적으로 클릭할 때만 데이터를 저장하려고 하므로 격리된 저장소와 데이터 바인딩된 개체 간의 연결을 끊어야 합니다. 이렇게 하려면 실제 개체 대신 Accomplishment 개체의 복사본을 저장합니다.

데이터를 격리된 저장소에 저장하려면

  1. 솔루션 탐색기에서 ViewModel.cs 또는 ViewModel.vb를 두 번 클릭하여 코드 편집기에서 파일을 엽니다.

  2. ViewModel 클래스에서 세 개의 GetAccomplishments 메서드 뒤에 다음 코드를 추가합니다.

    public void SaveAccomplishments()
    {
        IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
    
        foreach (Accomplishment a in Accomplishments)
        {
            if (settings.Contains(a.Name))
            {
                settings[a.Name] = a;
            }
            else
            {
                settings.Add(a.Name, a.GetCopy());
            }
        }
    
        settings.Save();
        MessageBox.Show("Finished saving accomplishments");
    }
    
  3. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  4. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

이 앱에서 사용자는 저장 버튼을 클릭하여 데이터를 저장할 시기를 선택합니다. 이 절차에서는 앱 바에 저장 버튼을 추가합니다. 버튼 아이콘에는 표준 Windows Phone 아이콘 중 하나를 사용합니다. 자세한 내용은 Windows Phone용 앱 바을 참조하세요.

아이콘 파일을 추가하려면

  1. 솔루션 탐색기에서 MVVMTestApp 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음, 기존 항목을 클릭합니다.

    그러면 기존 항목 추가 대화 상자가 나타납니다.

  2. 다음 위치로 이동하여 표준 아이콘을 찾습니다.

    C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons\dark

  3. appbar.save.rest.png 파일을 클릭한 다음 추가를 클릭합니다.

  4. 솔루션 탐색기에서 새 파일을 선택합니다.

  5. 속성 창에서 새 파일에 대해 다음 속성을 설정합니다.

    속성

    빌드 작업

    Content

    출력 디렉터리로 복사

    변경된 내용만 복사

    파일 이름

    AppBarSave.png

  6. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  7. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

앱 바를 추가하려면

  1. 솔루션 탐색기에서 MainPage.xaml을 마우스 오른쪽 버튼으로 클릭한 다음 코드 보기를 클릭합니다.

    코드 숨김 파일이 코드 편집기에 열립니다.

  2. MainPage 클래스의 OnNavigatedFrom 메서드 뒤에 다음 코드를 추가합니다.

    private void AppBarSave_Click(object sender, EventArgs e)
    {
        vm.SaveAccomplishments();
    }
    
  3. 솔루션 탐색기에서 MainPage.xaml을 두 번 클릭하여 디자이너에서 XAML을 엽니다.

  4. 기본적으로 프로젝트에 추가되는 샘플 앱 바 요소를 찾습니다. 이 요소는 다음과 같습니다.

    <!--Sample code showing usage of ApplicationBar-->
    <!--<phone:PhoneApplicationPage.ApplicationBar>
    
    …
    
    </phone:PhoneApplicationPage.ApplicationBar>-->
    
  5. 샘플 앱 바 요소를 다음 코드로 바꿉니다.

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" >
            <shell:ApplicationBarIconButton IconUri="AppBarSave.png" Text="Save"  Click="AppBarSave_Click" />
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>
    
  6. 파일 메뉴에서 모두 저장을 클릭합니다(Ctrl+Shift+S).

  7. 빌드 메뉴에서 솔루션 빌드를 클릭합니다(Ctrl+Shift+B).

다음 절차에서는 앱을 테스트합니다.

에뮬레이터에서 앱을 실행하려면

  1. 표준 도구 모음에서 앱의 배포 대상을 Windows Phone 단말기가 아니라 Windows Phone 에뮬레이터로 설정합니다.

    Target on Standard Toolbar selecting emulator

  2. 디버그 메뉴에서 디버깅하지 않고 시작을 클릭합니다.

    에뮬레이터가 열리고 앱이 시작됩니다.

View가 Model에 바인딩되어 있는지 테스트하려면

  1. Items Collected 텍스트 상자에 숫자를 입력합니다.

    내부 모델이 업데이트됩니다. 이 모델은 INotifyPropertyChanged 인터페이스를 사용하므로 Count 속성을 변경하면 PropertyChanged 이벤트가 발생합니다. 뷰에 알리고, 텍스트 상자 오른쪽에 있는 검사 열이 업데이트되어 입력된 새 값을 표시합니다.

  2. Levels Completed 확인란에서 첫 번째 수준을 선택합니다.

    내부 모델이 업데이트됩니다. 이 모델은 INotifyPropertyChanged 인터페이스를 사용하므로 Completed 속성을 변경하면 PropertyChanged 이벤트가 발생합니다. 뷰에 알리고, 텍스트 상자 오른쪽에 있는 검사 열이 업데이트되어 값 True를 표시합니다.

데이터 변환기를 테스트하려면

  • Levels Completed 확인란에서 수준 중 하나를 선택합니다.

    확인란이 선택되고, 텍스트 상자 오른쪽에 있는 검사 열이 업데이트되어 값 True를 표시합니다. 확인란이 사용할 수 없게 됩니다. 사용자가 만든 사용자 지정 데이터 변환기를 사용하여 확인란의 enabled 속성이 확인란 값의 반대인 False로 설정됩니다.

페이지 상태를 테스트하려면

  1. 텍스트 상자와 확인란에 데이터를 입력합니다.

  2. 시작 버튼을 클릭한 다음 뒤로 버튼을 클릭합니다.

    앱이 계속되면 페이지 상태가 유지됩니다.

격리된 저장소의 데이터를 테스트하려면

  1. 텍스트 상자와 확인란에 데이터를 입력합니다.

  2. 저장 버튼을 클릭합니다.

    "Finished saving accomplishments"라는 메시지가 나타납니다.

  3. 텍스트 상자와 확인란에 새 데이터를 입력합니다.

  4. 시작 버튼을 클릭한 다음 오른쪽 화살표를 클릭합니다.

    앱 목록이 나타납니다.

  5. MVVMTestApp을 클릭하여 앱의 새 인스턴스를 시작합니다.

    앱은 격리된 저장소에 저장한 데이터를 로드합니다. 그 후에 입력한 데이터는 로드되지 않습니다.

다음 방법으로 앱의 기능을 확장할 수 있습니다.

  • 사용자가 수집할 항목의 이름을 입력할 수 있게 합니다.

  • 저장 기능을 MVVM 명령으로 변경합니다.

표시: