次の方法で共有


Windows Phone の SharePoint リスト アイテムを保存および取得する

Windows Phone アプリケーションのライフ サイクルと、ネットワーク データをローカルに保存する方法について説明します。

Windows Phone アプリの開発における最も重要な考慮事項の 1 つは、アプリケーション全体と、アプリケーション内の個々のページまたはデータ項目の両方に対する状態情報の管理です。 Windows Phone アプリを開発する場合は、アプリのユーザーがネットワーク リソース (SharePoint リストなど) への接続を失う可能性があることを考慮する必要があります。 Windows Phone アプリの開発インフラストラクチャは、アプリのライフ サイクルのさまざまな段階で状態情報を処理するためのメカニズムを提供します。

重要

Windows Phone 8 用のアプリを開発する場合は、Visual Studio 2010 Express ではなく Visual Studio Express 2012 を使用する必要があります。 開発環境を除き、この記事のすべての情報は、Windows Phone 8 用アプリと Windows Phone 7 用アプリを作成する場合に適用されます。 > 詳細については、「 方法: SharePoint 用モバイル アプリを開発するための環境を設定する」を参照してください。

Windows Phone 上に SharePoint リスト データをローカルに保存する

Windows Phone では、一度に 1 つのアプリのみが実行され、ユーザーが電話で別のアプリに切り替わると (たとえば、電話の [スタート ] ボタンを押すことによって)、現在実行されているアプリは非アクティブ化されるか、Windows Phone 開発の観点から廃棄されます。 ユーザーが非アクティブ化されたアプリに戻った場合 ( [戻る ] ボタンを押すことによって)、アプリを再アクティブ化できますが、アプリライフ サイクルの過程でアプリケーションの状態情報を処理するロジックを指定しない限り、アクティブ化から非アクティブ化への移行では、その状態情報は既定では保持されません。 (Windows Phone アプリのアプリケーション ライフ サイクルの詳細については、「Windows Phone の 実行モデルの概要」を参照してください)。

Windows Phone アプリでは、 PhoneApplicationService クラスが、アプリケーション状態の管理に使用できる標準的なライフサイクル イベントを提供しています。 Windows Phone SharePoint リスト アプリケーション テンプレートから作成したプロジェクトでは ( Silverlight for Windows Phone テンプレートのいずれかから作成したプロジェクトと同様)、これらの標準 Windows Phone アプリケーション ライフサイクル イベントが App.xaml ファイルで宣言され、分離コード ファイル App.xaml.cs でイベント ハンドラーに関連付けられています。 SharePoint リスト アプリの場合、App.xaml ファイルでの宣言は次のようなマークアップになります。

<Application.ApplicationLifetimeObjects>
    <!--Required object that handles lifetime events for the application-->
    <shell:PhoneApplicationService
        Launching="Application_Launching" Closing="Application_Closing"Activated="Application_Activated" Deactivated="Application_Deactivated"/>
</Application.ApplicationLifetimeObjects>

App.xaml ファイルで宣言された Application_Activated イベント ハンドラーと Application_Deactivated イベント ハンドラーは、アプリが終了しない限り、電話アプリで使用するアプリケーション状態情報をキャッシュする既定のロジックを使用して、App.xaml.cs分離コード ファイルに実装されます。 これらのイベントのハンドラーの実装では、PhoneApplicationService クラスの State プロパティ (Dictionary オブジェクトへのアクセスを提供します) を使用してデータを格納します。 この State プロパティに格納されているデータは一時的です。 つまり、アプリが非アクティブ化または廃棄された場合は保持されますが、アプリが終了した場合は保持されません。 ユーザーが別のアプリに切り替えたときに Windows アプリが非アクティブ化された場合、非アクティブ化されたアプリは状況に応じて Windows Phone オペレーティング システムによって終了される可能性があることに注意してください。 固定ストレージに保存されていない電話上のデータは、PhoneApplicationServiceState プロパティを使用して一時的なストレージに保存された場合でも失われます。

SharePoint リストからデータを取得する Windows Phone アプリでは、複数のセッションを通してスマートフォン上で使用するデータは、サーバーが使用可能である場合は当然、SharePoint Server を実行しているサーバーから取得されます。 しかし、場所やその他の要因によってサービスの対応範囲はさまざまであるため、Windows Phone デバイスで SharePoint Server への継続的な接続が使用可能でない場合もあります。 SharePoint Server を実行しているサーバーへの接続がない場合でもアプリのユーザーがデータにアクセスできるようにするには、または単純に、サーバーが使用できるかどうかにかかわらずアプリの複数のセッションを通して使用するデータを永続的ストレージに保存するには、 PhoneApplicationService クラスの Closing イベントと Launching イベントを使用します。

これらのイベントの Application_Launching ハンドラーと Application_Closing ハンドラーは App.xaml で宣言され、App.xaml.cs ファイルで定義されますが、実装されません。 アプリ終了のコンテキストでのアプリケーション状態情報の格納と取得を処理するには、 Application_Closing イベント ハンドラーの実装を提供して、アプリ用に指定された分離ストレージにデータを格納し、アプリのセッション間でデータが保持されるようにし、Application_Launchingの実装を提供できます データの元のソースである SharePoint Server を実行しているサーバーへの接続が使用できない場合でも、アプリの新しいセッションが開始されたときに分離ストレージからデータを取得するイベント ハンドラー。

ヒント

データは、暗号化してからローカル デバイスに保存することが推奨されます。 データを暗号化する方法の詳細については、「方法: Windows Phone アプリケーションでデータを暗号化する」を参照してください。

アプリケーション状態を保存および取得するためのイベント ハンドラーを実装する

  1. 「方法: Windows Phone SharePoint リスト アプリを作成する」の手順に従って、Visual Studio で Windows Phone SharePoint リスト アプリケーション テンプレートを使用して Windows Phone アプリを作成します

  2. ソリューション エクスプローラーでApp.xaml ファイルを選択します。

  3. F7 を押して、編集用の分離コード ファイルApp.xaml.csを開きます。

  4. Application_Launching エベント ハンドラーの実装 (空の実装) の場所を探し、それを以下のコードに置き換えます。

    private void Application_Launching(object sender, LaunchingEventArgs e)
    {
        if (IsolatedStorageSettings.ApplicationSettings.Contains(DataProvider.ListTitle))
        {
            App.MainViewModel = (ListViewModel)IsolatedStorageSettings.ApplicationSettings
                                                  [DataProvider.ListTitle];
            App.MainViewModel.Initialize();
        }
    }
    
  5. Application_Closing イベント ハンドラーの実装 (空の実装) の場所を探し、それを以下のコードに置き換えます。

    private void Application_Closing(object sender, ClosingEventArgs e)
    {
        if (IsolatedStorageSettings.ApplicationSettings.Contains(DataProvider.ListTitle))
        {
            IsolatedStorageSettings.ApplicationSettings[DataProvider.ListTitle] = App.MainViewModel;
        }
        else
        {
            IsolatedStorageSettings.ApplicationSettings.Add(DataProvider.ListTitle, App.MainViewModel);
        }
        IsolatedStorageSettings.ApplicationSettings.Save();
    }
    
  6. ファイルを保存します。

これらを実装したら、アプリを実行し、SharePoint Server を実行しているサーバーからのデータでアプリ内のメインの ViewModel を初期化します。 スマートフォン上でアプリを終了し ([ 戻る] ボタンを押してアプリの最初のページを越えて戻ることにより) Application_Closing イベントを発生させます。 その後、サーバーに接続せずにアプリを実行すると、 IsolatedStorageSettingsDictionary オブジェクト ( Application_Closing イベント内) に保存された ViewModel が取得され、初期化されます。 アプリの前回のセッションで分離ストレージに保存された SharePoint リスト アイテムがアプリのリスト フォーム (List.xaml) に表示されます。

リスト アイテムをオフラインで編集するメカニズムを実装する

前のセクションの手順に従って、アプリで Closing イベントと Launching イベントのハンドラーを実装した場合、接続が利用可能になったときにサーバーから取得された SharePoint リスト データは、アプリの後続のセッションでサーバーへの接続が失われた場合でも、リスト アイテムが電話のローカル永続ストレージから取得されるため、アプリに表示できます。 ただし、前のセクションの実装に基づいて、オフライン中に表示するためにこの方法で使用できるリスト アイテムは、接続が復元されない限り、編集およびサーバーに保存できません。 次の手順では、接続が使用できないときに編集されたバージョンのリスト アイテムをローカルに格納するためのメカニズムをアプリに追加します。 サーバーへの接続が再び使用可能になったら、これらの編集済みリスト 項目を取得し、変更をサーバーに保存し直すことができます。

このセクションの手順では、Windows Phone SharePoint リスト アプリケーション テンプレートから作成した Windows Phone アプリ プロジェクトで作業していることを前提とします。また、表 1 に示されている列とフィールド型を含む、サーバー上のカスタム リスト テンプレートから作成された商品注文リストを使用しているものとします。

表 1. サンプルの商品注文リスト

Column 種類 必須
商品 (名称など) 1 行テキスト (Text) はい
説明 1 行テキスト (Text) いいえ
数量 Number はい
注文日 日付/時刻 (DateTime) いいえ
Fulfillment Date 日付/時刻 (DateTime) いいえ
連絡先番号 1 行テキスト (Text) いいえ

オフラインでのアイテムの編集をサポートするクラスを実装する

  1. 表 1 に示した商品注文リストを基に作成した Visual Studio プロジェクトから始めます。 ソリューション エクスプローラーで、このプロジェクトを表すノード (たとえば SPListAppLocalStorage など) を選択します。

  2. [ プロジェクト] メニューの [ クラスの追加] を選択します。

    [ 新しい項目の追加] ダイアログ ボックスが表示され、C# の クラス テンプレートが選択されています。

  3. クラス ファイルの名前を DraftItemStore.cs として、[ 追加 ] をクリックします。

    クラス ファイルがプロジェクトに追加され、それが編集できるように開かれます。

  4. クラス ファイルの内容を次のコードに置き換えます。

    using System;
    using System.Net;
    using System.Windows;
    using System.Collections.Generic;
    using System.IO.IsolatedStorage;
    
    namespace SPListAppLocalStorage // Based on project name by default.
    {
        public class DraftItemStore
        {
            const string DraftsKey = "Drafts";
    
            public static void AddDraftItem(string id, EditItemViewModel model)
            {
                Dictionary<string, EditItemViewModel> draftCollection = GetDraftItemCollection();
                draftCollection[id] = model;
                SaveDrafts(draftCollection);
            }
    
            public static void RemoveDraftItem(string id)
            {
                Dictionary<string, EditItemViewModel> draftCollection = GetDraftItemCollection();
                draftCollection.Remove(id);
                SaveDrafts(draftCollection);
            }
    
            public static void SaveDrafts(Dictionary<string, EditItemViewModel> draft)
            {
                if (IsolatedStorageSettings.ApplicationSettings.Contains(DraftsKey))
                {
                    IsolatedStorageSettings.ApplicationSettings[DraftsKey] = draft;
                }
                else
                {
                    IsolatedStorageSettings.ApplicationSettings.Add(DraftsKey, draft);
                }
            }
    
            public static List<EditItemViewModel> Drafts
            {
                get
                {
                    Dictionary<string, EditItemViewModel> draftCollection = GetDraftItemCollection();
    
                    List<EditItemViewModel> modelCollection = new List<EditItemViewModel>();
                    foreach (KeyValuePair<string, EditItemViewModel> entry in draftCollection)
                    {
                        modelCollection.Add(entry.Value);
                    }
    
                    return modelCollection;
                }
            }
    
            public static Dictionary<string, EditItemViewModel> GetDraftItemCollection()
            {
                Dictionary<string, EditItemViewModel> draftCollection = null;
                if (IsolatedStorageSettings.ApplicationSettings.Contains(DraftsKey))
                    draftCollection = (Dictionary<string,
                    EditItemViewModel>)IsolatedStorageSettings.ApplicationSettings[DraftsKey];
    
                if (draftCollection == null)
                    draftCollection = new Dictionary<string, EditItemViewModel>();
    
                return draftCollection;
            }
    
            public static EditItemViewModel GetDraftItemById(string id)
            {
                Dictionary<string, EditItemViewModel> draftCollection = GetDraftItemCollection();
                return !draftCollection.ContainsKey(id) ? null : draftCollection[id];
            }
        }
    }
    

    このコードに指定された名前空間は、プロジェクトの名前 (この例の場合は SPListAppLocalStorage) に基づいています。 各自のプロジェクトの名前に応じて、他の名前空間を指定できます。

  5. ファイルを保存します。

EditItemViewModel クラスの特定のインスタンスは、電話で編集されている SharePoint リスト アイテムを表します。 アイテムに対する変更がサーバーに保存される前に、"下書きアイテム" として編集されたリスト アイテムを検討できます。 このクラスのコードでは、AddDraftItem メソッドによって、EditItemViewModel クラスの特定のインスタンス (つまり下書きアイテム) が値として Dictionary オブジェクトに追加され、DictionaryEditItemViewModel が、指定されたリスト アイテムの識別子に基づくキーに関連付けられます。 (識別子は SharePoint Server によってリスト内の各項目に割り当てられます。Windows Phone SharePoint リスト アプリケーション テンプレートに基づくプロジェクトでは、その識別子は、リスト アイテムを表す EditItemViewModelDisplayItemViewModel など、指定された ViewModel クラスの ID プロパティに格納されます。RemoveDraftItem メソッドは、指定した識別子に基づいて Dictionary オブジェクトから EditItemViewModel を削除します。 どちらのメソッドでも、GetDraftItemCollection メソッドを使用して、分離ストレージから EditItemViewModel オブジェクトを含む Dictionary オブジェクトを取得し、両方のメソッドで SaveDrafts メソッドを使用して、変更された Dictionary オブジェクト (下書き項目が追加または削除された) を分離ストレージに保存します。 GetDraftItemCollection メソッドは、最初に"Drafts" Dictionary オブジェクトが分離ストレージに保存されているかどうかを判断します。 その場合、メソッドはその Dictionary オブジェクトを 返します。それ以外の場合、メソッドは新しい Dictionary オブジェクトを初期化して返します。 クラスの Drafts プロパティは、下書きアイテムのリスト (つまり、List<T> ジェネリックに基づくオブジェクト) を EditItemViewModel オブジェクトとして返すことによって、下書き項目のディクショナリにアクセスできます。 GetDraftItemById メソッドは、指定した識別子値に基づいて Dictionary オブジェクトから指定された下書き項目を返します。

スマートフォン アプリのユーザー インターフェイスに要素を追加し、 DraftItemStore クラスを使用するようにそれを構成することで、リスト アイテムをオフラインで編集できるようにします。 以降の手順では、次のことを行います。

  • 下書きアイテムとしてスマートフォン上の分離ストレージに保存されたすべてのリスト アイテムを表示する Windows Phone ページを追加し、構成します。
  • さらに、個々の下書きアイテムを編集するためのページを追加し、構成して、 EditItemViewModel にバインドします。これは、リスト アイテム用の編集フォーム (EditForm.xaml) と同様のものです。
  • SaveAsDraft メソッドを EditItemViewModel クラスに追加します。これは、前の手順で実装した DraftItemStore クラスの AddDraftItem メソッドを実行します。
  • SaveAsDraft メソッドを呼び出す ApplicationBar ボタンを EditForm.xaml ファイルに追加します。
  • 下書きとして保存されたすべてのリスト アイテムを表示するページに移動する ApplicationBar ボタンを List.xaml ファイルに追加します。

スマートフォン上に保存されたすべての下書きアイテムを表示するページを追加する

  1. ソリューション エクスプローラーViews フォルダーを選択します。

  2. [ プロジェクト] メニューの [ 新しい項目の追加] を選択します。

    [ 新しい項目の追加] ダイアログ ボックスが開きます。

  3. [ 新しい項目の追加] ダイアログ ボックスの Visual C# ノードの下にある Silverlight for Windows Phone ノードを選択します。

  4. [ テンプレート] ウィンドウで、[ Windows Phone Portrait Page] テンプレートを選択します。

  5. ファイルに「Drafts.xaml」という名前を付けて、[ 追加] をクリックします。

    ファイルが、プロジェクトの Views ノードの下に追加され、編集用に開かれます。

  6. デザイナーの [XAML] ウィンドウで、ファイルのコンテンツを次の XAML に置き換えます。

    <phone:PhoneApplicationPage
        x:Class="SPListAppLocalStorage.Views.Drafts"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
        xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        FontFamily="{StaticResource PhoneFontFamilyNormal}"
        FontSize="{StaticResource PhoneFontSizeNormal}"
        Foreground="{StaticResource PhoneForegroundBrush}"
        SupportedOrientations="Portrait" Orientation="Portrait"
        mc:Ignorable="d" d:DesignHeight="696" d:DesignWidth="480"
        shell:SystemTray.IsVisible="True">
    
        <!--LayoutRoot is the root grid where all page content is placed-->
        <Grid x:Name="LayoutRoot" Background="Transparent">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
    
            <!--TitlePanel contains the name of the application and page title-->
            <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
                <TextBlock x:Name="ApplicationTitle" Text="Product Orders"
                                        Style="{StaticResource PhoneTextNormalStyle}"/>
                <TextBlock x:Name="PageTitle" Text="Draft Items" Margin="9,-7,0,0"
                                          Style="{StaticResource PhoneTextTitle1Style}"/>
            </StackPanel>
    
            <!--ContentPanel - place additional content here-->
            <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
                <ListBox x:Name="lstBoxDraftItems" ItemsSource="{Binding}"
                                      SelectionChanged="lstBoxDraftItems_SelectionChanged">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="{Binding [Title]}" Style="
                                               {StaticResource PhoneTextTitle2Style}"></TextBlock>
                                <TextBlock Text="{Binding [Description]}" Style="
                                                {StaticResource PhoneTextNormalStyle}"></TextBlock>
                                <TextBlock Text="{Binding [Contact_x0020_Number]}" Style="
                                               {StaticResource PhoneTextNormalStyle}"></TextBlock>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </Grid>
    
        <phone:PhoneApplicationPage.ApplicationBar>
            <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
                <shell:ApplicationBarIconButton x:Name="btnCancel"
                 IconUri="/Images/appbar.cancel.rest.png" Text="Cancel" Click="OnCancelButtonClick" />
            </shell:ApplicationBar>
        </phone:PhoneApplicationPage.ApplicationBar>
    
    </phone:PhoneApplicationPage>
    

    このコードで <x:Class> 名前空間指定の値 ("SPListAppLocalStorage.Views.Drafts") は、プロジェクトの名前によって異なります。

  7. ソリューション エクスプローラーで選択された Drafts.xaml ファイルで、F7 キーを押して、関連する分離コード ファイル Drafts.xaml.cs を編集用に開きます。

  8. ファイルのコンテンツを次のコードで置き換えます。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using Microsoft.Phone.Controls;
    
    namespace SPListAppLocalStorage.Views
    {
        public partial class Drafts : PhoneApplicationPage
        {
            public Drafts()
            {
                InitializeComponent();
                this.Loaded += new RoutedEventHandler(Drafts_Loaded);
            }
    
            private void lstBoxDraftItems_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                ListBox lstBox = sender as ListBox;
                if (lstBox.SelectedIndex == -1)
                    return;
    
                EditItemViewModel selectedDraftItem = lstBox.SelectedItem as EditItemViewModel;
                NavigationService.Navigate(new Uri(string.Format("/Views/DraftItemEditForm.xaml?ID={0}",
                                                       selectedDraftItem.ID), UriKind.Relative));
    
                lstBox.SelectedIndex = -1;
            }
    
            void Drafts_Loaded(object sender, RoutedEventArgs e)
            {
                this.DataContext = DraftItemStore.Drafts;
            }
    
            private void OnCancelButtonClick(object sender, EventArgs e)
            {
                // Navigate back to initial List View form.
                NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative));
            }
        }
    }
    
  9. ファイルを保存します。

個々の下書きアイテムを編集するためのページを追加する

  1. ソリューション エクスプローラーViews フォルダーを選択します。

  2. [ プロジェクト] メニューの [ 新しい項目の追加] を選択します。

    [ 新しい項目の追加] ダイアログ ボックスが開きます。

  3. [ 新しい項目の追加] ダイアログ ボックスの Visual C# ノードの下にある Silverlight for Windows Phone ノードを選択します。

  4. [ テンプレート] ウィンドウで、[ Windows Phone Portrait Page] テンプレートを選択します。

  5. ファイルに「DraftItemEditForm.xaml」という名前を付けて、[ 追加] をクリックします。

    ファイルが、プロジェクトの Views ノードの下に追加され、編集用に開かれます。

  6. デザイナーの [XAML] ウィンドウで、ファイルのコンテンツを次の XAML に置き換えます。

    <phone:PhoneApplicationPage
        x:Class="SPListAppLocalStorage.DraftItemEditForm"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
        xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="696"
        FontFamily="{StaticResource PhoneFontFamilyNormal}"
        FontSize="{StaticResource PhoneFontSizeNormal}"
        Foreground="{StaticResource PhoneForegroundBrush}"
        SupportedOrientations="Portrait" Orientation="Portrait"
        shell:SystemTray.IsVisible="True" x:Name="DraftItemEditPage">
    
        <!--LayoutRoot is the root grid where all page content is placed-->
        <Grid x:Name="LayoutRoot" Background="Transparent"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=
                    Microsoft.Phone.Controls">
            <StackPanel>
                <ProgressBar Background="Red" x:Name="progressBar" Opacity="1"
                                        HorizontalAlignment="Center" VerticalAlignment="Top"
                                        Height="15" Width="470" IsIndeterminate="{Binding IsBusy}"
                                        Visibility="{Binding ShowIfBusy}" />
                <ScrollViewer HorizontalScrollBarVisibility="Auto" Height="700">
                    <Grid x:Name="ContentPanel" Width="470">
                        <StackPanel Margin="0,5,0,5">
                            <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                                <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left"
                                    Style="{StaticResource PhoneTextNormalStyle}">Product*</TextBlock>
                                <TextBox Style="{StaticResource TextValidationTemplate}"
                             FontSize="{StaticResource   PhoneFontSizeNormal}" Width="470"
                             HorizontalAlignment="Left" Name="txtTitle" Text="{Binding [Title],
                                       Mode=TwoWay,ValidatesOnNotifyDataErrors=True,NotifyOnValidationError=True}"
                                                                             TextWrapping="Wrap" />
                            </StackPanel>
                            <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                                <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left"
                                   Style="{StaticResource PhoneTextNormalStyle}">Description</TextBlock>
                                <TextBox Style="{StaticResource TextValidationTemplate}"
                                   FontSize="{StaticResource PhoneFontSizeNormal}" Width="470"
                                    HorizontalAlignment="Left" Name="txtDescription"
                                                               Text="{Binding [Description],
                                                               Mode=TwoWay, ValidatesOnNotifyDataErrors=True,
                                                               NotifyOnValidationError=True}"
                                           TextWrapping="Wrap" />
                            </StackPanel>
                            <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                                <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left"
                                   Style="{StaticResource PhoneTextNormalStyle}">
                                                               Product Category</TextBlock>
                                <ListBox MaxHeight="400" Width="Auto" x:Name="lstBoxProduct_x0020_Category"
                                                  ItemsSource="{Binding [Product_x0020_Category]}">
                                    <ListBox.ItemTemplate>
                                        <DataTemplate>
                                            <RadioButton FontSize="{StaticResource PhoneFontSizeNormal}"
                                              HorizontalAlignment="Left" GroupName="Product_x0020_Category"
                                                                     Content="{Binding Name}"
                                   IsChecked="{Binding IsChecked, Mode=TwoWay}" />
                                        </DataTemplate>
                                    </ListBox.ItemTemplate>
                                </ListBox>
                            </StackPanel>
                            <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                                <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left"
                                           Style="{StaticResource PhoneTextNormalStyle}">Quantity*</TextBlock>
                                <TextBox Style="{StaticResource TextValidationTemplate}"
                                       FontSize="{StaticResource PhoneFontSizeNormal}" Width="470"
                                          HorizontalAlignment="Left" Name="txtQuantity" Text="{Binding [Quantity],
                                            Mode=TwoWay, ValidatesOnNotifyDataErrors=True,
                                               NotifyOnValidationError=True}"
                                                 TextWrapping="Wrap" />
                            </StackPanel>
                            <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                                <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left"
                                    Style="{StaticResource PhoneTextNormalStyle}">Order Date</TextBlock>
                                <TextBox Height="Auto" Style="{StaticResource TextValidationTemplate}"
                                                   FontSize="{StaticResource PhoneFontSizeNormal}" Width="470"
                                                             HorizontalAlignment="Left" Name="txtOrder_x0020_Date"
                             Text="{Binding [Order_x0020_Date], Mode=TwoWay, ValidatesOnNotifyDataErrors=True,
                                               NotifyOnValidationError=True}" TextWrapping="Wrap" />
                                <TextBlock FontSize="16" TextWrapping="Wrap" HorizontalAlignment="Left"
                                                     Style="{StaticResource PhoneTextSubtleStyle}"
                                                                 Text="{Binding DateTimeFormat}" />
                            </StackPanel>
                            <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                                <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left"
                             Style="{StaticResource PhoneTextNormalStyle}">Fulfillment Date</TextBlock>
                                <TextBox Height="Auto" Style="{StaticResource TextValidationTemplate}"
                                              FontSize="{StaticResource PhoneFontSizeNormal}" Width="470"
                                              HorizontalAlignment="Left" Name="txtFulfillment_x0020_Date"
                            Text="{Binding [Fulfillment_x0020_Date], Mode=TwoWay,
                         ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True}"
                             TextWrapping="Wrap" />
                                <TextBlock FontSize="16" TextWrapping="Wrap" HorizontalAlignment="Left"
                                                        Style="{StaticResource PhoneTextSubtleStyle}" Text="{Binding
                                                               DateTimeFormat}" />
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock TextWrapping="Wrap" Width="150" HorizontalAlignment="Left"
                                                      Style="{StaticResource PhoneTextNormalStyle}">Rush
                                                                       :</TextBlock>
                                <CheckBox Name="txtRush" FontSize="{StaticResource PhoneFontSizeNormal}"
                                              HorizontalAlignment="Left" IsChecked="{Binding [Rush], Mode=TwoWay,
                                   ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True}" />
                            </StackPanel>
                            <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                                <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left"
                            Style="{StaticResource PhoneTextNormalStyle}">Contact Number</TextBlock>
                                <TextBox Style="{StaticResource TextValidationTemplate}"
                                       FontSize="{StaticResource PhoneFontSizeNormal}" Width="470"
                                                  HorizontalAlignment="Left" Name="txtContact_x0020_Number"
                                                             Text="{Binding [Contact_x0020_Number],
                                                             Mode=TwoWay, ValidatesOnNotifyDataErrors=True,
                                                             NotifyOnValidationError=True}"
                                                                               TextWrapping="Wrap" />
                            </StackPanel>
                        </StackPanel>
                    </Grid>
                </ScrollViewer>
            </StackPanel>
        </Grid>
    
        <phone:PhoneApplicationPage.ApplicationBar>
            <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
                <shell:ApplicationBarIconButton x:Name="btnSubmit"
                                    IconUri="/Images/appbar.save.rest.png"
                                    Text="Submit" Click="OnSubmitButtonClick"/>
                <shell:ApplicationBarIconButton x:Name="btnBack"
                                    IconUri="/Images/appbar.back.rest.png"
                                     Text="Back to List" Click="OnBackButtonClick"/>
            </shell:ApplicationBar>
        </phone:PhoneApplicationPage.ApplicationBar>
    
    </phone:PhoneApplicationPage>
    

    このページを定義するための XAML は、 EditForm.xaml ファイルの XAML と似ています。 EditForm.xaml ファイルをコピーして DraftItemEditForm.xaml の基礎として使用し、このマークアップで示されているようにファイルに変更を加えることができます。

  7. ソリューション エクスプローラーDraftItemEditForm.xaml ファイルを選択した状態で、F7 キーを押して、関連する分離コード ファイル DraftItemEditForm.xaml.cs を開いて編集します。

  8. ファイルの内容を次のコードに置き換えます。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using Microsoft.Phone.Controls;
    using Microsoft.SharePoint.Client;
    using Microsoft.Phone.Tasks;
    using System.Device.Location;
    using Microsoft.Phone.Shell;
    using Microsoft.SharePoint.Phone.Application;
    
    namespace SPListAppLocalStorage
    {
        public partial class DraftItemEditForm : PhoneApplicationPage
        {
            EditItemViewModel viewModel;
    
            /// <summary>
            /// Constructor for Draft Item Edit Form.
            /// </summary>
            public DraftItemEditForm()
            {
                InitializeComponent();
            }
    
            protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
     // Include initialization of ViewModel here rather than in constructor to be able to use QueryString value.
                if (viewModel == null)
                {
                    viewModel = DraftItemStore.GetDraftItemById(NavigationContext.QueryString["ID"].ToString());
                }
    
                viewModel.Initialize();
                this.DataContext = viewModel;
    
                base.OnNavigatedTo(e);
                viewModel.ItemUpdated += new EventHandler<ItemUpdatedEventArgs>(OnItemUpdated);
            }
    
            protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
            {
                base.OnNavigatedFrom(e);
                viewModel.ItemUpdated -= new EventHandler<ItemUpdatedEventArgs>(OnItemUpdated);
            }
    
            private void OnViewModelInitialization(object sender, InitializationCompletedEventArgs e)
            {
                this.Dispatcher.BeginInvoke(() =>
                {
                    // If initialization has failed show error message and return.
                    if (e.Error != null)
                    {
                        MessageBox.Show(e.Error.Message, e.Error.GetType().Name, MessageBoxButton.OK);
                        return;
                    }
    
                    // Set Page's DataContext to current ViewModel instance.
                    this.DataContext = (sender as EditItemViewModel);
                });
            }
    
            private void OnCancelButtonClick(object sender, EventArgs e)
            {
                NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative));
            }
    
            private void OnSubmitButtonClick(object sender, EventArgs e)
            {
                viewModel.UpdateItem();
            }
    
            private void OnItemUpdated(object sender, ItemUpdatedEventArgs e)
            {
                this.Dispatcher.BeginInvoke(() =>
                {
                    if (e.Error != null)
                    {
                        MessageBox.Show(e.Error.Message, e.Error.GetType().Name, MessageBoxButton.OK);
                        return;
                    }
    
                    // Remove Draft Item from local storage if update to server succeeds.
                    DraftItemStore.RemoveDraftItem(viewModel.ID.ToString());
                    this.NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative));
                });
            }
    
            private void OnBackButtonClick(object sender, EventArgs e)
            {
                NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative));
            }
        }
    }
    

    コードを見るとわかるように、このファイルで使用されている名前空間はプロジェクトの名前 (SPListAppLocalStorage) に基づいています。

  9. DraftItemEditForm.xaml ファイルで宣言されている ApplicationBar ボタン (btnBack) の appbar.back.rest.png イメージをプロジェクトに追加します。 ソリューション エクスプローラーで、プロジェクトの Images フォルダーを選択します。

  10. [ プロジェクト] メニューの [ 既存の項目の追加] を選択します。

  11. 開いているブラウザーで、Windows Phone SDK 7.1 によって標準の Windows Phone アイコン画像がインストールされているフォルダーに移動します。

    注:

    前景が明るく背景が暗い画像は、SDK の標準インストールで %PROGRAMFILES%(x86)\\Microsoft SDKs\\Windows Phone\\v7.1\\Icons\\dark されています。

  12. という名前のイメージ ファイル appbar.back.rest.png選択し、[追加] を選択 します。 画像がプロジェクトの Images ノードの下に追加されます。

  13. ソリューション エクスプローラーで、今追加した画像を選択します。そのファイルの [ プロパティ ウィンドウ] で、画像ファイルの [ ビルド アクション] プロパティを [ コンテンツ] に設定し、[ 出力ディレクトリにコピー] プロパティを [ 新しい場合はコピーする] に設定します。

  14. ファイルを保存します。

アイテムを下書きとして保存するための ApplicationBar ボタンを編集フォームに追加する

  1. ソリューション エクスプローラーで、プロジェクトの [ViewModels] ノードの下にあるEditItemViewModel.cs ファイルを選択します。 F7 キーを押して編集用のファイルを開きます。

  2. EditItemViewModel クラスを実装するコード ブロック (左中かっこと右中かっこで区切られる) について、次の public メソッドをファイルに追加します。

    public void SaveAsDraft()
    {
        DraftItemStore.AddDraftItem(this.ID.ToString(), this);
    }
    
  3. ソリューション エクスプローラーで、プロジェクトの Views ノードの下の EditForm.xaml ファイルをダブルクリックします。

    ファイルが編集用にデザイナーに開かれます。

  4. デザイナーの [XAML] ウィンドウで、次の XAML に示すように、(既存の [送信] ボタンと [キャンセル] ボタンに加えて) <shell:ApplicationBar> タグに別のボタンを追加します。

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
            <shell:ApplicationBarIconButton x:Name="btnSubmit"
                  IconUri="/Images/appbar.save.rest.png"
                  Text="Submit" Click="OnBtnSubmitClick"/>
            <shell:ApplicationBarIconButton x:Name="btnSaveDraft"            IconUri="/Images/appbar.save.rest.png" Text="Save Draft"            Click="OnSaveDraftButtonClick"/>
            <shell:ApplicationBarIconButton x:Name="btnCancel"
                          IconUri="/Images/appbar.cancel.rest.png"
                          Text="Cancel" Click="OnCancelButtonClick"/>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>
    
  5. ソリューション エクスプローラーで EditForm.xaml ファイルを選択した状態で、F7 キーを押して、関連する分離コード ファイル (EditForm.xaml.cs) を開いて編集します。

  6. EditForm 部分クラスを実装するコード ブロック (左中かっこと右中かっこで区切られる) について、次のイベント ハンドラーをファイルに追加します。

    private void OnSaveDraftButtonClick(object sender, EventArgs e)
    {
        viewModel.SaveAsDraft();
    }
    
  7. ファイルを保存します。

すべての下書きアイテムを表示する ApplicationBar ボタンをリスト表示フォームに追加する

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

    ファイルが編集用にデザイナーに開かれます。

  2. デザイナーの XAML ペインで、次の XAML マークアップに示すように、(既存の [新規] ボタンと [更新] ボタンに加えて) <shell:ApplicationBar> タグに別のボタンを追加します。

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
            <shell:ApplicationBarIconButton x:Name="btnNew"
            IconUri="/Images/appbar.new.rest.png" Text="New"
                        Click="OnNewButtonClick"/>
            <shell:ApplicationBarIconButton x:Name="btnRefresh"
                       IconUri="/Images/appbar.refresh.rest.png"
            Text="Refresh" IsEnabled="True" Click="OnRefreshButtonClick"/>
            <shell:ApplicationBarIconButton x:Name="btnDrafts"            IconUri="/Images/appbar.folder.rest.png"            Text="View Drafts" IsEnabled="True"            Click="OnDraftsButtonClick"/>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>
    
  3. Drafts ボタン用のアイコン画像をプロジェクトに追加します。 ソリューション エクスプローラーで、プロジェクトの Images フォルダーを選択します。

  4. [ プロジェクト] メニューの [ 既存の項目の追加] を選択します。

  5. 開いているブラウザーで、Windows Phone SDK 7.1 によって標準の Windows Phone アイコン画像がインストールされているフォルダーに移動します。

    注:

    前景が明るく背景が暗い画像は、SDK の標準インストールで %PROGRAMFILES%(x86)\\Microsoft SDKs\\Windows Phone\\v7.1\\Icons\\dark されています。

  6. appbar.folder.rest.png という名前の画像ファイルを選択して [追加] を選択します。

    イメージ ノードの下のプロジェクトに画像が追加されます。

  7. ソリューション エクスプローラーで、今追加した画像を選択します。そのファイルの [ プロパティ ウィンドウ] で、画像ファイルの [ ビルド アクション] プロパティを [ コンテンツ] に設定し、[ 出力ディレクトリにコピー] プロパティを [ 新しい場合はコピーする] に設定します。

  8. ソリューション エクスプローラーで、[ビュー] ノードの下にある List.xaml ファイルを選択し、F7 キーを押します。 関連付けられている分離コード ファイル (List.xaml.cs) が開き、編集が行われます。

  9. ListForm 部分クラスを実装するコード ブロック (左中かっこと右中かっこで区切られる) について、次のイベント ハンドラーをファイルに追加します。


private void OnDraftsButtonClick(object sender, EventArgs e)
{
    NavigationService.Navigate(new Uri("/Views/Drafts.xaml", UriKind.Relative));
}
  1. ソリューション内のすべてのファイルを保存し、 F6 キーを押してソリューションをコンパイルします。

プロジェクトを開始して Windows Phone エミュレーターに展開すると、[ View Drafts] ボタンがリスト フォームの ApplicationBar に表示されます (図 1)。このボタンは、下書きとして保存されたすべてのリスト アイテムを表示します。

図 1. [View Drafts] ボタンを含むように変更されたリスト フォーム

[下書き表示] ボタンを含むように変更されたリスト フォーム

最初は、下書きが保存されていないので、下書きを表示するページは空になります。 リスト フォームからアイテムを選択し (アイテムの表示フォーム (DisplayForm.xaml) を表示し)、[ Edit] ボタンを押して編集フォームを表示します。 SharePoint Server との接続がない場合は、編集フォームの [ Save Draft] ボタンを押し (図 2)、リスト アイテムに加えた変更内容を分離ストレージに保存できます。

図 2. [Save Draft] ボタンを含むように変更された編集フォーム

[下書きの保存] ボタンを含むように変更された編集フォーム

サーバーが再び使用できるようになったら、リスト フォームの [ View Drafts] ボタンを押して下書きページを表示します (図 3)。

図 3. 下書きとして分離ストレージに保存されたアイテムを表示する下書きページ

下書きとして保存したリスト項目が表示されている下書きページ

[下書き] ページで項目を選択すると、[下書き項目の編集] フォーム (DraftItemEditForm.xaml) が表示され (図 4)、追加の変更を加えた後、[ 送信 ] ボタンをクリックして、編集した項目をサーバーに保存できます。 その時点で、アイテムは分離ストレージから削除されます。これは、サーバーへの変更と共に保存された後、下書きアイテムとして扱われなくなったためです。

図 4. 下書きアイテム編集フォーム

下書きアイテム編集フォーム

アプリ内の下書きアイテム編集フォーム (図 4) と、通常の編集フォーム (図 2) がほぼ同じであることに注目してください。 下書きアイテムの編集エクスペリエンスは、編集フォームでのアイテムの編集エクスペリエンスとほぼ同じであることが推奨されます。

関連項目