エクスポート (0) 印刷
すべて展開
情報
要求されたトピックは次のとおりです。しかし、このトピックはこのライブラリには含まれていません。

チュートリアル: Windows Phone 8 用の MVVM で OData を使用する

2014/06/18

対象: Windows Phone 8 および Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

このチュートリアルでは、Model-View-ViewModel (MVVM) デザイン パターンを実装して、Open Data Protocol (OData) を実装するデータ サービスにアクセスする簡単なアプリを構築します。MVVM は、ユーザー インターフェイスからデータを分離する方法であり、OData フィードを使用するアプリにとって重要です。このサンプルでは、データ モデルはサンプル Northwind データ サービスを使用して生成される一連のプロキシ クラスであり、ビューは XAML ユーザー コントロールです。データ モデルとユーザー インターフェイス間のリンクである ViewModel は、Windows Phone の OData クライアント ライブラリを使用する C# クラスです。MVVM デザイン パターンの詳細については、「Windows Phone 8 での Model-View-ViewModel パターンの実装」を参照してください。Windows Phone の OData クライアントは Windows Phone SDK には含まれておらず、WCF Data Services Tools for Visual Studio から別途ダウンロードする必要があります。

このチュートリアルで作成するアプリを使用すると、サンプル Northwind データ サービスの Northwind データを表示できます。このアプリは Windows Phone データ バインド アプリケーション テンプレートを開始点として使用して作成し、テンプレートで提供されているサンプル データを OData サービスの Northwind データに置き換えます。このアプリの完成したバージョンは、この MSDN サンプル ギャラリー ページからダウンロードできます。

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

作業の過程で、次のコード ファイルを変更または作成します。

  1. ViewModels\MainViewModel.cs: アプリのメイン ViewModel を、Northwind サンプル データ サービスのデータにアクセスするように変更します。この ViewModel は、アプリケーションの状態を保存して復元し、読み書き可能なデータ サービスに変更を保存するメソッドも提供します。

  2. MainPage.xaml: アプリのメイン ページを変更して、既存の StackPanel コントロールと Grid コントロールを更新します。

  3. DetailsPage.xaml:アプリの詳細ページを変更して、ページのレイアウト ルートである既存の Grid コントロールを更新します。

  4. App.xaml.cs: このファイルを変更して、アプリ全体でアクセス可能な静的 ViewModel を作成します。SaveState メソッドと RestoreState メソッドを呼び出して、アプリ状態の変更時にアプリの状態を保持して復元します。

  5. MainPage.xaml.cs: このページを変更して、[Cancel] ボタンと [Refresh] ボタンのクリックを処理します。

  6. DetailsPage.xaml.cs: このページを変更して、[Save] ボタンのクリックを処理します。

このチュートリアルを完了するには、Windows Phone SDK がインストールされている必要があります。詳細については、「SDK を取得する」を参照してください。

Windows Phone の OData クライアントも次の場所からダウンロードしてインストールする必要があります:WCF Data Services Tools for Visual Studio

このチュートリアルでは、OData の Web サイトで公開されている Northwind サンプル データ サービスを使用します。このサンプル データ サービスは読み取り専用です。変更を保存しようとすると、エラーが返されます。Northwind データ サービスに変更を保存する、このチュートリアルの最後のセクションを実行するには、Northwind データ サービスの独自の読み書き可能バージョンを実装する必要があります。これを行うには、「方法: Northwind データ サービスを作成する (WCF Data Services)」の手順を実行します。

まず、MVVMODataTestApp という名前の新しい Windows Phone アプリ プロジェクトを作成します。後の手順で、アプリ名が MVVMODataTestApp であると仮定するコードをアプリに追加します。アプリに別の名前を選択する場合、コードの名前空間の参照を変更する必要があります。

アプリ プロジェクトを作成するには

  1. Visual Studio で、[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。

    [新しいプロジェクト] ダイアログが表示されます。

  2. 左側のペインで [テンプレート] 項目が展開されていることを確認し、[Visual C#] または [Visual Basic] を選択します。Visual Basic は [他の言語] にあります。

  3. プロジェクトの種類の一覧で、[Windows Phone データ バインド アプリ] をクリックします。

  4. [名前] ボックスに「MVVMODataTestApp」と入力します。

  5. [OK] をクリックします。

    Windows Phone プラットフォームの選択ダイアログ ボックスが表示されます。

  6. [対象の Windows Phone OS のバージョン] を展開し、[Windows Phone OS 8.0] を選択し、[OK] をクリックします。

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

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

    メモメモ:

    Windows Phone データ バインド アプリケーションのプロジェクト テンプレートにはサンプル データを格納する XML ファイルが含まれているため、このプロジェクトは変更を加える前に実行されます。サンプル データを使用したアプリの動作を確認するには、[デバッグ] メニューの [デバッグ開始] をクリックします。(F5)

  8. ソリューション エクスプローラーで、SampleData フォルダーを右クリックし、[プロジェクトから除外] をクリックします。

    これにより、プロジェクトからサンプル データ フォルダーが削除されます。これをデータ サービスの Northwind データに置き換えます。

この手順では、Northwind サンプル データ サービスへの参照を追加します。Visual Studio でサービス参照の追加ツールを使用すると、Northwind データ サービスのデータ モデルを表す一連のクライアント データ クラスが生成されます。これらのクラスは、このアプリの MVVM パターンのモデルです。

プロジェクトにデータ サービスへの参照を追加するには

  1. MVVMODataTestApp プロジェクトを右クリックし、[サービス参照の追加] をクリックします。

    [サービス参照の追加] ダイアログ ボックスが表示されます。

  2. [アドレス] ボックスに以下の URI 値を入力し、[OK] をクリックします。

    http://services.odata.org/Northwind/Northwind.svc/
    

    パブリックな読み取り専用の Northwind サンプル データ サービスからメタデータ ドキュメントがダウンロードされます。

    Northwind データ サービスの独自の読み書き可能実装を使用する場合、代わりにこのサービスへの URI 値を提供する必要があります。カスタム Northwind データ サービスのプロジェクトが、MVVMODataTestApp サンプル プロジェクトと同じソリューション内にある場合、[探索] ボタンをクリックして、Northwind データ サービスの URI を検出します。

  3. [名前空間] ボックスに「Northwind」と入力し、[OK] をクリックします。

    これで、プロジェクトに新しいコード ファイルが追加されます。このコード ファイルには、データ サービスのリソースにオブジェクトとしてアクセスし、操作するためのデータ クラスが存在します。データ クラスは名前空間 MVVMODataTestApp.Northwind に作成されます。System.Data.Services.Client.WP80.dll アセンブリへの参照も追加されます。

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

この手順では、プロジェクト テンプレートから生成された MainViewModel クラスを定義するコードを、型指定された DataServiceCollection を公開するバージョンに置き換えます。ObservableCollection<T> を継承するこのコレクションにより、ViewModel でコレクション内の Customer オブジェクトが変更されたことをビューに通知し、ビューでユーザー インターフェイスを更新することが可能になります。

MainViewModel には、データ サービスにクエリを実行して、Customer データをコレクションに読み込むコードも含まれています。後の手順で、変更の保存、要求のキャンセル、およびアプリ状態の保存に必要な OData クライアント ライブラリの機能を公開するその他のメソッドを追加します。

ViewModel を更新するには

  1. ソリューション エクスプローラーで ViewModels フォルダーを展開し、MainViewModel.cs ファイルまたは MainViewModel.vb ファイルを右クリックして、[コードの表示] をクリックします。

    これにより、コード ファイルが表示されます。

  2. MainViewModel クラスのコードを次のコードで置き換えます。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data.Services.Client;
    using System.Linq;
    using System.Windows;
    using MVVMODataTestApp.Northwind;
    
    namespace MVVMODataTestApp
    {
        public class MainViewModel : INotifyPropertyChanged
        {
    
            // This is the URI of the public, read-only Northwind data service. 
            // To make updates and save changes, replace this URI 
            // with your own Northwind service implementation.
            private static readonly Uri _rootUri = 
                new Uri("http://services.odata.org/Northwind/Northwind.svc/");
    
            // Define the typed DataServiceContext.
            private NorthwindEntities _context;
    
            // Define the binding collection for Customers.
            private DataServiceCollection<Customer> _customers;
    
            // Gets and sets the collection of Customer objects from the feed.
            // This collection is used to bind to the UI (View).
            public DataServiceCollection<Customer> Customers
            {
                get { return _customers; }
    
                private set
                {
                    // Set the Titles collection.
                    _customers = value;
    
                    // Register a handler for the LoadCompleted callback.
                    _customers.LoadCompleted += OnCustomersLoaded;
    
                    // Raise the PropertyChanged events.
                    NotifyPropertyChanged("Customers");
                }
            }
    
            // Used to determine whether the data is loaded.
            public bool IsDataLoaded { get; private set; }
    
            // Loads data when the application is initialized.
            public void LoadData()
            {
                // Instantiate the context and binding collection.
                _context = new NorthwindEntities(_rootUri);
                Customers = new DataServiceCollection<Customer>(_context);
    
                // Specify an OData query that returns all customers.
                var query = from cust in _context.Customers
                            select cust;
    
                // Load the customer data.
                Customers.LoadAsync(query);
            }
    
            // Displays data from the stored data context and binding collection 
            public void LoadData(NorthwindEntities context,
                DataServiceCollection<Customer> _customers)
            {
                _context = context;
                Customers = _customers;
    
                IsDataLoaded = true;
            }
    
            // Handles the DataServiceCollection<T>.LoadCompleted event.
            private void OnCustomersLoaded(object sender, LoadCompletedEventArgs e)
            {
                // Make sure that we load all pages of the Customers feed.
                if (Customers.Continuation != null)
                {
                    Customers.LoadNextPartialSetAsync();
                }
                IsDataLoaded = true;
            }
    
            // Declare a PropertyChanged for the UI to register 
            // to get updates from the ViewModel.
            public event PropertyChangedEventHandler PropertyChanged;
    
            // Notifies the binding about a changed property value.
            private void NotifyPropertyChanged(string propertyName)
            {
                var propertyChanged = PropertyChanged;
                if (propertyChanged != null)
                {
                    // Raise the PropertyChanged event.
                    propertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
    
    
  3. [ファイル] メニューの [すべてを保存] をクリックします。(Ctrl + Shift + S)

この手順では、プロジェクト テンプレートから生成された MainPage.xaml ファイルを更新して、ListBox コントロールであるこのページのビューが MainViewModel によって公開された Customers プロパティにバインドされるようにします。

MainPage.xaml ファイルを更新するには

  1. ソリューション エクスプローラーで、MainPage.xaml ファイルを右クリックし、[ビュー デザイナー] をクリックします。

    これにより、デザインおよび編集用にファイルが開きます。

  2. トップレベルの phone 要素で、d:DataContext 要素を削除します。

    デザイン時には MainViewModelSampleData.xaml サンプル データ ファイルを結合に使用できないため、この操作を行う必要があります。

  3. TitlePanel という名前の StackPanel 要素を検索し、次のコードに置き換えます。

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
                <TextBlock x:Name="ApplicationTitle" Text="NORTHWIND TRADERS" Style="{StaticResource PhoneTextNormalStyle}"/>
                <TextBlock x:Name="PageTitle" Text="Customers" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
            </StackPanel>
    
    
  4. ContentPanel という名前の Grid 要素を検索し、次のコードに置き換えます。

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <ListBox x:Name="MainLongListSelector" Margin="0,0,-12,0" ItemsSource="{Binding Customers}" SelectionChanged="MainLongListSelector_SelectionChanged">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="0,0,0,17" Width="432" Height="100">
                        <TextBlock Text="{Binding CompanyName}" TextWrapping="NoWrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                        <TextBlock Text="{Binding ContactName}" TextWrapping="NoWrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                        <TextBlock Text="{Binding Phone}" TextWrapping="NoWrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
    
    

    ListBox (ビュー) は MainViewModel クラスの Customers プロパティにバインドされ、ItemTemplate の各コントロールはコレクション内の Customer オブジェクトのプロパティにバインドされています。トップレベルのバインディングは、プロジェクト テンプレートの MainPage.xaml ファイルの分離コード ページで、次のコード行により定義されています。

    // Set the data context of the listbox control to the sample data.
    DataContext = App.ViewModel;
    
  5. [ファイル] メニューの [すべてを保存] をクリックします。(Ctrl + Shift + S)

MainPage.xaml.cs 分離コード ページを更新するには

  • MainLongListSelector_SelectionChanged メソッドを次のコードで更新します。

    // Handle selection changed on LongListSelector
    private void MainLongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        // If selected item is null (no selection) do nothing
        if (MainLongListSelector.SelectedItem == null)
        return;
    
        // Navigate to the new page
        NavigationService.Navigate(new Uri("/DetailsPage.xaml?selectedItem=" + MainLongListSelector.SelectedIndex , UriKind.Relative));
    
        // Reset selected item to null (no selection)
        MainLongListSelector.SelectedItem = null;
    }
    

    ここでは、NavigationService.Navigate の呼び出しを、ItemViewModel の ID ではなく、選択した項目のインデックスを使用するように変更しています。これは、このサンプルでは ItemViewModel クラスを使用しないからです。

この手順では、プロジェクト テンプレートから生成された DetailsPage.xaml ファイルと分離コード ファイルの両方を更新し、このページの要素が MainPage.xml の ListView コントロールで選択された Customer オブジェクトにバインドされるようにします。

DetailsPage.xaml と分離コード ページを更新するには

  1. ソリューション エクスプローラーで、DetailsPage.xaml ファイルをダブルクリックします。

    これにより、デザインおよび編集用にファイルが開きます。

  2. トップレベルの phone 要素で、d:DataContext 要素を削除します。

    デザイン時には MainViewModelSampleData.xaml サンプル データ ファイルを結合に使用できないため、この操作を行う必要があります。

  3. LayoutRoot という名前の Grid 要素を検索し、次のコードに置き換えます。

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="PageTitle" Text="NORTHWIND TRADERS" 
                        Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="ListTitle" Text="{Binding CompanyName}" Margin="9,-7,0,0" 
                        Style="{StaticResource PhoneTextTitle1Style}" />
        </StackPanel>
        <ScrollViewer Grid.Row="1">
            <Grid x:Name="ContentPanel" Margin="12,0,12,0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="165"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="Contact name:" Style="{StaticResource PhoneTextNormalStyle}" 
                        VerticalAlignment="Center" Grid.Row="0" Grid.Column="0"/>
                <TextBlock Text="Contact title:" Style="{StaticResource PhoneTextNormalStyle}" 
                        VerticalAlignment="Center" Grid.Row="1" Grid.Column="0"/>
                <TextBlock Text="Phone number:" Style="{StaticResource PhoneTextNormalStyle}" 
                        VerticalAlignment="Center" Grid.Row="2" Grid.Column="0"/>
                <TextBlock Text="Address:" Style="{StaticResource PhoneTextNormalStyle}" 
                        VerticalAlignment="Center" Grid.Row="3" Grid.Column="0"/>
                <TextBlock Text="City:" Style="{StaticResource PhoneTextNormalStyle}" 
                        VerticalAlignment="Center" Grid.Row="4" Grid.Column="0"/>
                <TextBlock Text="Region:" Style="{StaticResource PhoneTextNormalStyle}" 
                        VerticalAlignment="Center" Grid.Row="5" Grid.Column="0"/>
                <TextBlock Text="Postal code:" Style="{StaticResource PhoneTextNormalStyle}" 
                        VerticalAlignment="Center" Grid.Row="6" Grid.Column="0"/>
                <TextBox Text="{Binding ContactName, Mode=TwoWay}" Grid.Row="0" Grid.Column="1"/>
                <TextBox Text="{Binding ContactTitle, Mode=TwoWay}" Grid.Row="1" Grid.Column="1"/>
                <TextBox Text="{Binding Phone, Mode=TwoWay}" Grid.Row="2" Grid.Column="1"/>
                <TextBox Text="{Binding Address, Mode=TwoWay}" Grid.Row="3" Grid.Column="1"/>
                <TextBox Text="{Binding City, Mode=TwoWay}" Grid.Row="4" Grid.Column="1"/>
                <TextBox Text="{Binding Region, Mode=TwoWay}" Grid.Row="5" Grid.Column="1"/>
                <TextBox Text="{Binding PostalCode, Mode=TwoWay}" Grid.Row="6" Grid.Column="1"/>
            </Grid>
        </ScrollViewer>
    </Grid>
    
    
    

    このコードには、MainViewModel で選択された Customer オブジェクトのプロパティにバインドされた TextBox コントロール (ビュー) が含まれます。バインディングは双方向で、Northwind データ サービスの読み書き可能バージョンにアクセスする場合に更新が可能です。

  4. ソリューション エクスプローラーで、DetailsPage.xaml.cs ファイルまたは DetailsPage.xaml.vb ファイルを右クリックし、[コードの表示] をクリックします。

    これにより、ファイルが編集用に開きます。

  5. OnNavigatedTo メソッドの実装を検索し、次のコードに置き換えます。

    // When the page is navigated to, set the data context 
    // to the selected item in the list.
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        
     if (DataContext == null)
                {
                    string selectedIndex = "";
                    if (NavigationContext.QueryString.TryGetValue("selectedItem", out selectedIndex))
                    {
                        int index = int.Parse(selectedIndex);
                        DataContext = App.ViewModel.Customers[index];
                    }
                }
    
    
    
    
    
    }
    
    

    これにより、ビューのバインディング コンテキストが、MainViewModel によって公開され、現在選択されている Customer に設定されます。

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

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

この手順では、ページの状態を維持するためのコードを追加します。通常、ユーザーがアプリから離れると、アプリは休止状態になります。この状態では、アプリはメモリ内に保持されているため、ユーザーがアプリに戻るとすぐに再開できます。この高速なアプリ切り替えは、自動的に有効になります。しかし、アプリは休止状態のときに終了される可能性があります。これらの状態変化を処理できるようにアプリを設計することが重要です。詳細については、「Windows Phone 8 のアプリのアクティブ化および非アクティブ化」を参照してください。

Windows Phone の OData クライアントには、これらの状態遷移を管理するのに役立つ DataServiceState クラスが含まれています。ViewModel では、アプリがこの機能にアクセスして、ViewModel 内のデータの状態を維持できるようにするメソッドも公開する必要があります。

ページの状態を維持するには

  1. ソリューション エクスプローラーで ViewModels フォルダーを展開し、MainViewModel.cs ファイルまたは MainViewModel.vb ファイルを右クリックして、[コードの表示] をクリックします。

  2. MainViewModel クラスに次の SaveState メソッドを追加します。

    // Return a string serialization of the application state.
    public string SaveState()
    {
        if (App.ViewModel.IsDataLoaded)
        {
            // Create a new dictionary to store binding collections. 
            var collections = new Dictionary<string, object>();
    
            // Add the current Customers binding collection.
            collections["Customers"] = Customers;
    
            // Return the serialized context and binding collections.
            return DataServiceState.Serialize(_context, collections);
        }
        else
        {
            return string.Empty;
        }
    }
    
    
  3. MainViewModel クラスに次の RestoreState メソッドを追加します。

    // Restores the view model state from the supplied state serialization.
    public void RestoreState(string appState)
    {
        // Create a dictionary to hold any stored binding collections.
        Dictionary<string, object> collections;
    
        if (!string.IsNullOrEmpty(appState))
        {
            // Deserialize the DataServiceState object.
            DataServiceState state
                = DataServiceState.Deserialize(appState);
    
            // Restore the context and binding collections.
            var context = state.Context as NorthwindEntities;
            collections = state.RootCollections;
    
            // Get the binding collection of Customer objects.
            DataServiceCollection<Customer> customers
                = collections["Customers"] as DataServiceCollection<Customer>;
    
            // Initialize the application with stored data. 
            App.ViewModel.LoadData(context, customers);
        }
    }
    
    
  4. ソリューション エクスプローラーで App.xaml を右クリックしてから、[コードの表示] をクリックします。

    コード エディターに分離コード ファイルが開きます。

  5. Application_Deactivated メソッドを見つけ、以下のコードで置き換えます。

    // Code to execute when the application is deactivated (sent to the background).
    // This code will not execute when the application is closing.
    private void Application_Deactivated(object sender, DeactivatedEventArgs e)
    {
        if (App.ViewModel.IsDataLoaded)
        {
            // Store application state in the state dictionary.              
            PhoneApplicationService.Current.State["ApplicationState"]
                = ViewModel.SaveState();
        }
    }
    
    

    このコードは ViewModel の SaveState メソッドを呼び出します。このメソッドは、DataServiceState オブジェクトのシリアル化である文字列を返します。

  6. Application_Activated メソッドを見つけ、以下のコードで置き換えます。

    // Code to execute when the application is activated (brought to the foreground).
    // This code will not execute when the application is first launched.
    private void Application_Activated(object sender, ActivatedEventArgs e)
    {
        // If data is not still loaded, try to get it from the state store.
        if (!ViewModel.IsDataLoaded)
        {
            if (PhoneApplicationService.Current.State.ContainsKey("ApplicationState"))
            {
                // Get back the serialized data service state from the dictionary.
                string appState =
                    PhoneApplicationService.Current.State["ApplicationState"]
                    as string;
    
                // Use the returned dictionary to restore the state of the data service.
                App.ViewModel.RestoreState(appState);
            }
            else
            {
                // Load the data since it is not persisted in the state dictionary. 
                App.ViewModel.LoadData();
            }
        }
    }
    
    

    このコードは、状態ディクショナリのシリアル化された RestoreState オブジェクトを使用して ViewModel の DataServiceState メソッドを呼び出します。この文字列が状態ディクショナリにない場合、データはデータ サービスから読み込まれます。

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

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

このアプリでは、ユーザーは [Cancel] ボタンをタップして LoadAsync() 操作をキャンセルしたり、[Refresh] ボタンをタップしてデータ サービスからデータを再読み込みしたりすることができます。また、ユーザーは [Save] ボタンをタップして、ユーザー詳細データへの更新を (読み取り/書き込みデータ サービスに) 送信するタイミングも選択します。この手順では、MainPage のアプリ バーに [Cancel] ボタンと [Refresh] ボタンを追加し、DetailPage のアプリ バーに [Save] ボタンを追加します。DataServiceContext クラスのこれらの機能は MainViewModel のメソッドとして公開されます。

重要:重要:

パブリックな読み取り専用の Northwind サンプル データ サービスにアクセスしているときに変更を保存しようとすると、エラーが発生します。変更をデータ サービスに保存するために、Northwind サンプル データ サービスの独自の読み書き可能バージョンを作成する必要があります。さらに、ユーザー Northwind データ サービスの Customers フィードを書き込み可能にする必要もあります。これを実行するには、SetEntitySetAccessRule データ サービスの構成メソッドに渡された EntitySetRights 値を EntitySetRights.AllRead に変更します。

ボタンのアイコンには、標準の Windows Phone アイコンのいずれかを使用します。詳細については、「Windows Phone のアプリケーション バー」を参照してください。

アイコン ファイルを追加するには

  1. ソリューション エクスプローラーで、プロジェクト MVVMTestApp を右クリックし、[追加] をポイントして、[既存の項目] をクリックします。

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

  2. 次の場所を参照して、標準のアイコンを見つけます。

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

  3. save アイコンを選択し、[追加] をクリックします。

  4. 手順 1. ~ 3. を繰り返して、cancel アイコンと refresh アイコンも追加します。

  5. ソリューション エクスプローラーで、新しい save.png ファイルを選択します。

  6. [プロパティ] ウィンドウで、新しいファイルに次のプロパティを設定します。

    プロパティ

    ビルド アクション

    Content

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

    新しい場合はコピーする

    ファイル名

    AppBarSave.png

  7. 手順 5. ~ 6. を繰り返して、新しい cancel.png ファイルに次のプロパティを設定します。

    プロパティ

    ビルド アクション

    Content

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

    新しい場合はコピーする

    ファイル名

    AppBarCancel.png

  8. 手順 5. ~ 6. を繰り返して、新しい refresh.png ファイルに次のプロパティを設定します。

    プロパティ

    ビルド アクション

    Content

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

    新しい場合はコピーする

    ファイル名

    AppBarRefresh.png

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

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

MainViewModel で変更のキャンセル、更新、および保存の機能を公開するには

  1. ソリューション エクスプローラーで ViewModels フォルダーを展開し、MainViewModel.cs ファイルまたは MainViewModel.vb ファイルを右クリックして、[コードの表示] をクリックします。

  2. MainViewModel クラスで、LoadAsync() 操作をキャンセルし、データ サービスからデータを再読み込みし、非同期で変更をデータ サービスに送信する次のメソッドを追加します。

    public void CancelCustomersAsyncLoad()
    {
        // Call the CancelAsyncLoad method on the binding collection.
        this.Customers.CancelAsyncLoad();
    }
    
    
    public void SaveChanges()
    {
        // Start the save changes operation. 
        this._context.BeginSaveChanges(OnChangesSaved, this._context);
    }
    
    private void OnChangesSaved(IAsyncResult result)
    {
        // Use the Dispatcher to ensure that the 
        // asynchronous call returns in the correct thread.
        Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            this._context = result.AsyncState as NorthwindEntities;
    
            try
            {
                // Complete the save changes operation.
                this._context.EndSaveChanges(result);
            }
            catch (DataServiceRequestException ex)
            {
                // Ideally, we should not create a UI element 
                // from the ViewModel. A better way is to use a 
                // service or event to report exceptions to the view.
                MessageBox.Show(string.Format(
                        "{0} The target Northwind data service ('{1}') is read-only.",
                        ex.Message, this._context.BaseUri));
            }
        }
        );
    }
    
    
    重要:重要:

    パブリックな読み取り専用の Northwind サンプル データ サービスにアクセスしているときに変更を保存しようとすると、エラーが発生します。通常の実行時、クライアント ライブラリで、メッセージ ボックスを表示するために処理される DataServiceRequestException が発生します。デバッグ時に読み取り専用データ サービスに変更を保存しようとすると、クライアント ライブラリのバグのため、処理されない例外が発生します。Northwind データ サービスの独自の読み書き可能バージョンを実装するには、「方法: Northwind データ サービスを作成する (WCF Data Services)」の手順を実行します。

    public void Refresh()
    {
        // Cache the current merge option and change 
        // it to MergeOption.OverwriteChanges.
        MergeOption cachedOption = _context.MergeOption;
        _context.MergeOption = MergeOption.OverwriteChanges;
    
        // Reload data from the data service.
        this.LoadData();
    
        // Reset the merge option.
        _context.MergeOption = cachedOption;
    }
    
    
  3. [ファイル] メニューの [すべてを保存] をクリックします。(Ctrl + Shift + S)

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

アプリ バーを追加するには

  1. ソリューション エクスプローラーで、MainPage.xaml を右クリックしてから、[コードの表示] をクリックします。

    コード エディターに分離コード ファイルが開きます。

  2. MainPage クラスに次のメソッドを追加します。

    private void AppBarCancel_Click(object sender, EventArgs e)
    {
        App.ViewModel.CancelCustomersAsyncLoad();
    }
    
    
    private void AppBarRefresh_Click(object sender, EventArgs e)
    {
        // Reload the data from the OData service.
        App.ViewModel.Refresh();
    }
    
    
  3. ソリューション エクスプローラーで、DetailsPage.xaml を右クリックし、[コードの表示] をクリックします。

    コード エディターに分離コード ファイルが開きます。

  4. DetailsPage クラスに、次のメソッドを追加します。

    private void AppBarSave_Click(object sender, EventArgs e)
    {
        App.ViewModel.SaveChanges();
    }
    
  5. ソリューション エクスプローラーで、MainPage.xaml をダブルクリックしてデザイナーで XAML を開きます。

  6. LayoutRoot</Grid> タグの後ろに、次のアプリ バー要素を追加します。

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" >
                <shell:ApplicationBarIconButton IconUri="AppBarRefresh.png" 
                            Text="Refresh" Click="AppBarRefresh_Click" />
                <shell:ApplicationBarIconButton IconUri="AppBarCancel.png" 
                            Text="Cancel" Click="AppBarCancel_Click" />
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>
    
  7. ソリューション エクスプローラーで、DetailsPage.xaml をダブルクリックして XAML をデザイナーで開きます。

  8. LayoutRoot</Grid> タグの後ろに、次のアプリ バー要素を追加します。

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" >
            <shell:ApplicationBarIconButton IconUri="AppBarSave.png" 
                        Text="Save" Click="AppBarSave_Click" />
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>
    
  9. [ファイル] メニューの [すべてを保存] をクリックします。(Ctrl + Shift + S)

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

次の手順でアプリをテストします。

エミュレーターでアプリを実行するには

  1. 標準のツール バー上で、アプリの配置対象を ([Windows Phone デバイス] ではなく) [Windows Phone エミュレーター] に設定します。

    Target on Standard Toolbar selecting emulator

  2. [デバッグ] メニューの [デバッグなしで開始] をクリックします。

    エミュレーターが開き、アプリが開始されます。

表示:
© 2014 Microsoft