Windows Phone アプリでの Model-View-ViewModel パターンの実装

2013/12/05

対象: Windows Phone 8 | Windows Phone OS 7.1

 

このチュートリアルでは、Model-View-ViewModel (MVVM) デザイン パターンを実装する単純なアプリをビルドします。MVVM はユーザー インターフェイスからデータを分離する方法の 1 つです。MVVM を使用すると、開発者はデータ モデルをコード化し、設計者はユーザー インターフェイスを作成することができます。作成するアプリでは、Model (データ) は C# クラス、View (ユーザー インターフェイス) は XAML ユーザー コントロールになります。Model と View とのリンクである ViewModel も C# クラスになります。Model-View-ViewModel デザイン パターンの詳細については、このトピックの最後にあるリンクを参照してください。

このチュートリアルで作成するアプリは、ユーザーがビデオ ゲームで達成度を追跡するための "ゲーム トラッカー" です。ユーザーは、収集したアイテムの数および完了したレベルを格納できます。このアプリの完全版をダウンロードするには、「Model-View-ViewModel サンプル」を参照してください。

このチュートリアルでは、以下のタスクを行います。

  • Model、ViewModel、および 2 つの View を作成します。

  • 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. [OK] をクリックします。

    新しいアプリ プロジェクトが作成され、Visual Studio で開きます。

  6. [ファイル] メニューの [すべてを保存] をクリックします。(Ctrl + Shift + S)

  7. [ビルド] メニューの [ソリューションのビルド] をクリックします。(Ctrl + Shift + B)

この Model-View-ViewModel パターンの実装のために、プロジェクト ファイルをフォルダーに編成します。この手順では、ModelView、および ViewModel という名前の 3 つの新しいフォルダーを作成します。

Model-View-ViewModel ファイルを編成するには

  1. ソリューション エクスプローラーで、プロジェクト MVVMTestApp を右クリックし、[追加] をポイントして、[新しいフォルダー] をクリックします。新しいフォルダーが編集モードの名前でプロジェクトに追加されます。フォルダーの名前に「Model」と入力し、Enter キーを押します。

  2. ソリューション エクスプローラーで、プロジェクト MVVMTestApp を右クリックし、[追加] をポイントして、[新しいフォルダー] をクリックします。新しいフォルダーが編集モードの名前でプロジェクトに追加されます。フォルダーの名前に「View」と入力し、Enter キーを押します。

  3. ソリューション エクスプローラーで、プロジェクト MVVMTestApp を右クリックし、[追加] をポイントして、[新しいフォルダー] をクリックします。新しいフォルダーが編集モードの名前でプロジェクトに追加されます。フォルダーの名前に「ViewModel」と入力し、Enter キーを押します。

この手順では、データ モデルを作成します。モデルは、Accomplishment という名前の単一のクラスです。Accomplishment クラスは、INotifyPropertyChanged インターフェイスと PropertyChanged イベントを実装します。これにより、クラスはプロパティ値の変更をそのビューに通知でき、ビューはその変更に基づいてユーザー インターフェイスを更新できます。このアプリでは、ユーザーが変更できるのは Count プロパティと Completed プロパティのみであるため、これらのプロパティでのみ PropertyChanged イベントを発生させるようにします。最後の手順で、データ バインディングをテストします。

Accomplishment クラスには、次のプロパティが含まれています。

プロパティ

説明

名前

達成度の名前。

Type

達成度の種類: “アイテム” または “レベル” です。

カウント

アイテムの場合: 収集したアイテムの数。

完了

レベルの場合: そのレベルを完了したかどうか。

データ モデルを作成するには

  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 内の各項目には、次の 3 つの列があります。

名前

バインディング モード

説明

名前

片方向

アイテムの名前。

カウント

双方向

(テキスト ボックス) 収集したアイテムの数。ユーザーがこれを入力し、データ バインディングによってモデルが更新されます。

チェック

片方向

これはデータが正しく更新されていることを確認するチェックです。ユーザーが前の列で Count を更新すると、直ちにこの列に結果が表示されます。

最初のビューを作成するには

  1. ソリューション エクスプローラーで、フォルダー ビューを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。

    [新しい項目の追加] ダイアログが表示されます。

  2. ファイルの種類の一覧で、[Windows Phone ユーザー コントロール] をクリックします。

  3. [名前] ボックスに「ItemView.xaml」と入力し、[追加] をクリックします。

    新しい 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 内の各項目には、次の 3 つの列があります。

名前

バインディング モード

説明

レベル

片方向

レベルの名前。

完了

双方向

(チェック ボックス) そのレベルを完了したかどうか。ユーザーがこのチェック ボックスをオンにし、データ バインディングによってモデルが更新されます。

チェック

片方向

これはデータが正しく更新されていることを確認するチェックです。ユーザーが前の列で Completed データを更新すると、直ちにこの列に結果が表示されます。

この View では、もう 1 つの処理を行います。ユーザーがレベルをまだ完了していない場合は、チェック ボックスを有効にする必要があります。ユーザーがレベルを完了したことを示すためにチェック ボックスをオンにした場合は、チェック ボックスを無効にする必要があります。つまり、有効になっているチェック ボックスの状態は、チェック ボックス自体の値とは逆になります。有効になっているチェック ボックスの状態はデータ バインディングによって自動的に設定できますが、まず、Boolean 値とは逆の値を返すカスタム データ コンバーターを作成する必要があります。カスタム データ コンバーターは IValueConverter インターフェイスを実装するクラスであり、Convert メソッドと ConvertBack メソッドを実装します。最後の手順で、データ コンバーターをテストします。

2 番目のビューを作成するには

  1. ソリューション エクスプローラーで、フォルダー ビューを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。

    [新しい項目の追加] ダイアログが表示されます。

  2. ファイルの種類の一覧で、[Windows Phone ユーザー コントロール] をクリックします。

  3. [名前] ボックスに「LevelView.xaml」と入力し、[追加] をクリックします。

    新しい 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)

2 番目のビューのユーザー インターフェイスを作成するには

  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)

この手順では、アプリのメイン ページを作成します。メイン ページには、前に作成した 2 つのビューが含まれています。最初のビューにはアイテム、2 番目のビューにはレベルが含まれています。コードで、まず ViewModel の新しいインスタンスを作成し、データの取得に使用します。次に、View に表示するデータを ViewModel から選択して、各 View を ViewModel に接続します。後続の手順で、ユーザーがアプリを行き来する際にページの状態を保持するコードを追加します。

アプリのメイン ページのユーザー インターフェイスを作成するには

  1. ソリューション エクスプローラーで、MainPage.xaml をダブルクリックしてデザイナーで開きます。

  2. デザイン ビューで、テキスト ブロック [マイ アプリケーション] をクリックします。

  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 という名前の 1 つのプロパティだけを持つユーティリティ クラスを作成します。このプロパティは、ユーザーがアプの新しいインスタンスを開始したかどうかを追跡するために使用します。このアプリで保持する必要がある唯一の状態は、ViewModel です。Windows Phone ではページの状態オブジェクトが提供されており、ViewModel 全体を 1 つのオブジェクトとして状態に格納できます。ViewModel コレクションのアイテムを個別に格納する必要はありません。ユーザーがアプリに戻った際に、状態から 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 を呼び出して分離ストレージを保存します。ユーザーがアプリを終了した際ではなく、ユーザーが明示的に [Save] ボタンをクリックした際にのみデータを保存する場合は、分離ストレージとデータ バインド オブジェクトとの間の接続を解除する必要があります。そのためには、実際の Accomplishment オブジェクト自体の代わりにオブジェクトのコピーを保存します。

データを分離ストレージに保存するには

  1. ソリューション エクスプローラーで ViewModel.cs または ViewModel.vb をダブルクリックして、ファイルをコード エディターで開きます。

  2. ViewModel クラスで、3 つの 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)

このアプリでは、ユーザーは [Save] ボタンをクリックすることにより、データをいつ保存するかを選択します。この手順では、アプリ バーに [Save] ボタンを追加します。ボタンのアイコンには、標準の 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. [プロパティ] ウィンドウで、新しいファイルに対して次のプロパティを設定します。

    プロパティ

    ビルド アクション

    コンテンツ

    出力ディレクトリにコピー

    新しい場合はコピーする

    ファイル名

    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 イベントが発生します。View が通知を受け、テキスト ボックスの右側にあるチェック列が更新されて、入力した新しい値が表示されます。

  2. [Levels Completed] チェック ボックスで、最初のレベルを選択します。

    基になるモデルが更新されます。モデルでは INotifyPropertyChanged インターフェイスが使用されているため、Completed プロパティを変更すると、PropertyChanged イベントが発生します。View が通知を受け、テキスト ボックスの右側にあるチェック列が更新されて、値 True が表示されます。

データ コンバーターをテストするには

  • [Levels Completed] チェック ボックスで、レベルの 1 つを選択します。

    チェック ボックスがオンになり、テキスト ボックスの右側にあるチェック列が更新されて、値 True が表示されます。ここで、チェック ボックスが無効になります。作成したカスタム データ コンバーターを使用することにより、有効になっているチェック ボックスのプロパティが、チェック ボックス自体の値と反対の False に設定されます。

ページの状態をテストするには

  1. テキスト ボックスとチェック ボックスにデータを入力します。

  2. [開始] ボタンをクリックし、[戻る] ボタンをクリックします。

    アプリが再開され、ページの状態が保持されます。

分離ストレージ内のデータをテストするには

  1. テキスト ボックスとチェック ボックスにデータを入力します。

  2. [保存] ボタンをクリックします。

    メッセージ "Finished saving accomplishments" が表示されます。

  3. テキスト ボックスとチェック ボックスに新しいデータを入力します。

  4. [開始] ボタンをクリックし、右方向の矢印をクリックします。

    アプリのリストが表示されます。

  5. MVVMTestApp をクリックして、アプリの新しいインスタンスを起動します。

    アプリによって、後で入力したデータではなく、分離ストレージに保存したデータが読み込まれます。

アプリの機能は、次のようにして拡張することができます。

  • 収集するアイテムの名前をユーザーが入力できるようにします。

  • [保存] 機能を MVVM コマンドに変更します。

表示:
© 2014 Microsoft