SharePoint 用 Windows Phone アプリでビジネス ロジックとデータ検証を実装する

Windows Phone の SharePoint List アプリケーション テンプレートを使用して作成した Windows Phone アプリでデータの入力規則を実装します。

実稼働環境での使用を目的とした Windows Phone アプリケーションでは、たとえば、特定の状況に関連するビジネス ロジックを適用したり、入力された値が適切な形式であるかを確認したり、あるいは、単に SharePoint リストに値を保存する前に間違いを検出したりするために、ユーザーの入力データを検証する必要があります。 Windows Phone の SharePoint リスト アプリケーションのテンプレートをベースにして作成したプロジェクトには既定のデータの入力規則ロジックが含まれていますが、それだけでなく、カスタムのデータ入力規則を実装するためのメカニズムも用意されています。

重要

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

既定のデータの入力規則

SharePoint リストのフィールドのデータ型の一部は、簡易なフォーマット設定またはデータ入力規則に既定で関連付けられています。 データ型が SharePoint リストのハイパーリンク型または図型に基づくフィールドに無効な URL を入力して保存しようとすると、入力したアドレスが無効であることを示すメッセージが表示されます。 日付/時刻型のフィールドの値としてカスタマー名を入力すると、そのフィールドで有効とされる範囲の日付を入力するように求めるメッセージが表示されます。

注:

日付の入力検証は SharePoint の日付形式に関する機能です。 電話のロケールの日付形式が必要な場合は、フィールドをカスタマイズし、その内容に応じて検証を追加します。

また、このような基本の入力規則の一部は、Windows Phone SharePoint リスト アプリケーションのテンプレートから作成した Windows Phone アプリケーションに既定で適用されます。 SharePoint リストに基づいて、Windows Phone アプリの編集フォームで日付と時刻の種類の SharePoint フィールドにバインドされているフィールドに日付以外の値を入力すると、フィールドに関連付けられているコントロールからTextBoxフォーカスが移動すると、検証エラー メッセージが表示されます。 を参照)。

図 1. Windows Phone アプリケーションの入力規則エラー キュー

Windows Phone アプリでの検証エラー キュー

編集フォーム内の [開始時刻] という名前のテキスト ボックスは、このサンプル アプリケーションがベースにしている SharePoint リスト内の日付/時刻フィールドにバインドされています。 EditForm.xaml ファイル内の を定義TextBoxする XAML 宣言でコントロールのプロパティに関連付TextTextBoxけられているオブジェクトのBindingプロパティが にTrue設定されているためValidatesOnNotifyDataErrors、図 1 に示す検証エラー キュー (赤いテキスト) は、テキスト ボックスに無効な日付が入力された場合 (その後、テキスト ボックスにフォーカスが失われる) 場合に表示されます。

<StackPanel Orientation="Vertical" Margin="0,5,0,5">
   <TextBlock TextWrapping="Wrap"
              HorizontalAlignment="Left"
              Style="{StaticResource PhoneTextNormalStyle}">Start Time*
   </TextBlock>
   <TextBox Height="Auto"
            Style="{StaticResource TextValidationTemplate}"
            FontSize="{StaticResource PhoneFontSizeNormal}"
            Width="470"
            HorizontalAlignment="Left"
            Name="txtEventDate"
            Text="{Binding [EventDate], Mode=TwoWay, ValidatesOnNotifyDataErrors=True,
                       NotifyOnValidationError=True}"
            TextWrapping="Wrap" />
   <TextBlock FontSize="16"
              TextWrapping="Wrap"
              HorizontalAlignment="Left"
              Style="{StaticResource PhoneTextSubtleStyle}"
              Text="{Binding DateTimeFormat}" />
</StackPanel>

(プロパティが ValidatesOnNotifyDataErrorsFalse設定されている場合、ユーザーは[ 保存] ボタンが選択されるまで、入力されたデータが無効であることを示しません。その時点で、入力された日付値の書式検証はクラスの派生元の基底クラスによって引き続き実行されるため、ユーザーは検証エラーに関するエラー メッセージを EditItemViewModel 表示します)。

しかし、フィールドによっては、Windows Phone アプリケーションに無効なデータが入力されても通知を一切行いません。 さらに、適切に設計された Visual Studio プロジェクト テンプレートであれば、多様なアプリケーションのスタート地点として使用されるべく、必然的に一般化されています。 Windows Phone SharePoint リスト アプリケーションのテンプレートには特定のコンテキストに関連する入力規則を含めることはできませんが、一般化されたテンプレートとしてなら値を保持できます。 自分のニーズと、開発した Windows Phone アプリケーションが使用される状況によっては、カスタムのデータ入力規則を実装したい場合もあります。

カスタムのデータ入力規則の実装

開発した Windows Phone アプリケーションにユーザーが入力したデータを検証するには、さまざまな方法があります。 Windows Phone SharePoint リスト アプリケーションのテンプレートを使用して作成したプロジェクトには、Windows Phone アプリケーション内のデータのフォーム (ビュー。 これらのクラスは、 Model-View-ViewModel デザイン パターン の ViewModel コンポーネントの実装と見なすことができます (図 2)。 (Windows Phone SharePoint リスト アプリケーション テンプレートが MVVM ソフトウェア設計パターンにどのように準拠しているかの詳細については、「Windows Phone SharePoint リスト アプリケーション テンプレートのアーキテクチャ」を参照してください)。

注:

SharePoint リスト テンプレートには既定の入力規則 (SharePoint タスク リストの達成率、チーム ディスカッション リストの事後チェック、および SP 10 進数フィールド型の入力規則など) は含まれませんが、これらの入力規則を実装することができます。

図 2. ViewModel コンポーネントのテンプレート ファイル

ViewModel コンポーネントのテンプレート ファイル

MVVM パターンに基づいて設計されたアプリケーションでは、データの入力規則はしばしば、データ層 (Model コンポーネント) によって処理されます。 Windows Phone SharePoint リスト アプリケーションのテンプレートから作成したプロジェクトでは、開発者がデータ入力規則を管理しやすいように、データ入力規則のための拡張可能なメカニズムがレイヤーにプッシュされ、ViewModel コンポーネントに実装されています。 したがって、このテンプレートに基づいたプロジェクトでは、ユーザー入力を検証するかあるいは別の方法でデータを管理するカスタム コードに最適な場所は、これらの ViewModel クラス内です。 データ検証の観点では、 EditItemViewModel クラスと NewItemViewModel クラス (リスト データの編集と更新が含まれる可能性が最も高いフォームに関連付けられているクラス) は、両方とも、これら 2 つのクラスが派生するクラスの基本検証メソッドをオーバーライドする検証メソッド (という名前 Validate()) のオープン実装を提供します。

public override void Validate(string fieldName, object value)
{
  base.Validate(fieldName, value);
}

このメソッドは、個別のフィールドを対象とするカスタム入力規則ロジックを追加したい開発者向けの便利なメカニズムを提供します。 一般的な方法は、メソッドに渡される引数の fieldName 値を Validate() 確認して、カスタム検証コードに関連付けるフィールドを識別することです。 たとえば、このメソッドの実装で ステートメントを switch 使用して、Windows アプリの編集フォーム (EditForm.xaml) のさまざまなフィールドに固有の検証ロジックを指定できます。

次のコード例では、SharePoint Server のインストールに、カスタム リストのテンプレートから作成した製品注文リストが含まれていると仮定しています。 このリストは、表 1 に示す列とフィールドのデータ型から成ります。

表 1. 製品注文リスト

Column 種類 必須
Product (すなわち、タイトル) 1 行テキスト (Text) はい
説明 1 行テキスト (Text) いいえ
数量 Number はい
注文日 日付/時刻 (DateTime) いいえ
Fulfillment Date 日付/時刻 (DateTime) いいえ
連絡先番号 1 行テキスト (Text) いいえ

繰り返しますが、この例の目的は、Contoso, Ltd. という架空の企業で採用されているビジネス ロジックに基づき、指定された製品注文システムで、次のシンプルな入力規則が適用されるようにすることです。

  • 注文の納品日は、発注日よりも後の日付である必要があります。
  • Fuzzy Dice という製品を注文する場合、ペアで注文する必要があります。 Contoso, Ltd 固有の入力規則に従うと、Fuzzy Die という単数の製品は存在しません。
  • 製品注文リストで、連絡先電話番号フィールドのデータ型は "1 行のテキスト" (テキスト型) であり、任意のテキストを入力できます (既定では 255 文字以内まで)。 この例では、一般的な電話番号フォーマットの 1 つである "(555) 555-5555" の形式によるデータの入力を求めるフォーマット入力規則が適用されます。

カスタムの入力規則を実装するには

  1. 表 1 で指定した列と種類を含むカスタム リスト テンプレートに基づいて SharePoint リストを作成したと仮定して、「方法: Windows Phone SharePoint リスト アプリを作成する」の手順に従って、Visual Studio で Windows Phone SharePoint リスト アプリケーション テンプレートを使用してWindows Phone アプリを作成します。

  2. ソリューション エクスプローラー、プロジェクトの ViewModels フォルダーで、EditItemViewModel.cs ファイルをダブルクリックします (または、ファイルを選択して F7 キーを押します)。

  3. ファイルの先頭にあるディレクティブの一覧に次 using のディレクティブを追加します。

    using System.Globalization;
    using System.Text.RegularExpressions;
    
  4. ファイル内の メソッドの既定の Validate() 実装を次のコードに置き換えます。

    public override void Validate(string fieldName, object value)
    {
        string fieldValue = value.ToString();
        if (!string.IsNullOrEmpty(fieldValue)) //Allowing for blank fields.
        {
            bool isProperValue = false;
    
            switch (fieldName)
            {
                case "Quantity":
                    // Enforce ordering Fuzzy Dice in pairs only.
                    int quantityOrdered;
                    isProperValue = Int32.TryParse(fieldValue, out quantityOrdered);
                    if (isProperValue)
                    {
                        if ((quantityOrdered % 2) != 0) // Odd number of product items ordered.
                        {
                            if ((string)this["Title"] == "Fuzzy Dice")
                            {
                                AddError("Item[Quantity]", "Fuzzy Dice must be ordered in pairs.
                                                                       No such thing as a Fuzzy Die!");
                            }
                            else
                            {
                                // Restriction on ordering in pairs doesn't apply to other products.
                                RemoveAllErrors("Item[Quantity]");
                            }
                        }
                        else
                        {
                            RemoveAllErrors("Item[Quantity]");
                        }
                    }
                    break;
                case "Fulfillment_x0020_Date":
                    // Determine whether fulfillment date is later than order date.
                    DateTime fulfillmentDate;
                    isProperValue = DateTime.TryParse(fieldValue, CultureInfo.CurrentCulture,
                                  DateTimeStyles.AssumeLocal, out fulfillmentDate);
                    if (isProperValue)
                    {
                        DateTime orderDate;
                        isProperValue = DateTime.TryParse((string)this["Order_x0020_Date"],
                                   CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal, out orderDate);
    
                        if (fulfillmentDate.CompareTo(orderDate) > 0)
                        {
                            RemoveAllErrors("Item[Fulfillment_x0020_Date]");
                        }
                        else
                        {
                            AddError("Item[Fulfillment_x0020_Date]",
                                    "Fulfillment Date must be later than Order Date.");
                        }
                    }
                    break;
                case "Contact_x0020_Number":
                    // Check that contact number is in an appropriate format.
                    Regex rx = new Regex(@"^\\(?([0-9]{3})\\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$");
                    if (rx.IsMatch(fieldValue))
                    {
                        RemoveAllErrors("Item[Contact_x0020_Number]");
                    }
                    else
                    {
                        //Specified Contact Number is not a valid phone number.
                        AddError("Item[Contact_x0020_Number]", "Specified Contact Number is invalid.");
                    }
                    break;
                default:
                    // Not adding custom validation for other fields.
                    break;
            }
        }
    
        //And then proceed with default validation from base class.
        base.Validate(fieldName, value);
    }
    

    このコード例で指定したフィールド名は、表 1 に指定したサンプルの製品注文リストのプロパティに基づいていることを覚えておいてください。 (SharePoint Server のリスト フィールドの XML スキーマでは、フィールドの名前のスペースは、指定されたフィールドを定義する Field 要素の Name 属性の文字列 "x0020" に置き換えられます。テンプレートは、DisplayName 属性ではなく、サーバー上の XML スキーマで定義されているため、Field 要素の Name 属性を使用します)。EditForm.xaml で定義されている TextBox オブジェクトの Text プロパティの Binding 宣言を調べるか、ListProvider.cs ファイルの CamlQueryBuilder クラスの ViewFields 文字列を調べることで、検証ロジックを実装するフィールドのフィールド名を特定できます。

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

このサンプルのカスタム検証コードは、Validate メソッドに渡された value 引数が null 値または空の文字列でない場合にのみ実行されます。 表 1 に示されているように、納品日および連絡先フィールドにはデータを含める必要はありません (このサンプルでは、リストが SharePoint Server に定義されているため) ので、これらのフィールドは空白にしてください。 渡された値が長さ 0 の文字列 (null 値とは異なる) である可能性があるため、value 引数が null 値かどうかを判断する単純なチェックでは不十分です。このサンプルの場合、空白になりうるフィールドに対しては、長さ 0 の文字列を無効にすることが望ましいです。 数量および納品日フィールドの検証ロジックには、渡された値が適切なタイプであることを確認するための追加チェックが含まれています。 ここでの最初のチェック (switch ステートメントの前) で、渡された値が null でないことを確認した場合 (長さが 0 の文字列であるというより狭い条件に対してチェックするのではなく)、値が長さ 0 の文字列の場合でも、これらの検証は実行されませんが、渡された値が長さ 0 の文字列の場合、連絡先番号フィールドのデータを検証するロジックは引き続き実行されます。 このサンプルでは、特にユーザーが編集フォームを開いてリスト アイテムの編集を始めるときは、連絡先フィールドを空白 (長さ 0 の文字列) にできるようにするのが望ましいです。

プロジェクトをビルドしてエミュレーター Windows Phone配置して実行する場合は、ビジネス ルールに違反するデータをアプリの [編集] フォームのリストのフィールドに入力することで、検証ロジックをテストできます。 (図 3 を参照)。

図 3. カスタムの入力規則エラー キュー

カスタム検証のエラー キュー

このサンプルのコードが EditItemViewModel.cs ファイルのみに含まれる場合には、これらの入力規則は、編集フォームにユーザーが入力したデータに対してのみ適用されます。 ユーザーが新しい項目を 追加 するときと編集時の両方で検証規則を適用する場合は、NewItemViewModel.cs ファイル内 Validate() のメソッドに同じ検証ロジックを含める必要があります (または、この検証ロジックを含む関数を使用して別のクラス ファイルを作成し、EditItemViewModel.cs ファイルと NewItemViewModel.cs ファイルの両方のメソッドから Validate() 同じ関数を呼び出します)。

このサンプルの入力規則ロジックは、ユーザーが入力したデータが入力規則によって許可されている形式ではないことを示すことによって、特定のビジネス ルールを適用しますが、入力データがこのコードによって妨害されたり、変更されることはありません。 SharePoint リストにデータを保存する前に、たとえば電話番号を一貫性のある形式に揃えるためにデータを妨害するには、入力された電話番号用のカスタムのデータ変換を実装できます。 リスト アイテム フィールドのカスタム データ変換の詳細については、「方法: Windows Phone アプリの SharePoint フィールドの種類をサポートおよび変換する」を参照してください。

関連項目