japan.internet.comThe Internet & IT Network
RSS
  • ニュース
  • コラム
  • リサーチ
  • ヘッドライン
  • 特集
  • ブログ
  • プレスリリース
  • 専門チャンネル
  • イベント
  • ランキング
  • ニュースメール
2008年10月15日
文字サイズ文字サイズ小文字サイズ中文字サイズ大
デベロッパー2007年4月3日 10:00

Windowsフォームの入力チェックを効率化する

海外海外internet.com発の記事
  • このエントリーを含むはてなブックマーク
  • この記事をクリップ!
  • Buzzurlにブックマーク
  • Yahoo!ブックマークに登録
  • newsing it!

はじめに

 入力チェックはどのプログラムにも必要なものであり、どのプログラマにとっても悩みの種です。大抵の場合は、「電話番号が7桁または10桁である」「IPアドレスが4つのオクテット型から成り立つ」「国名が193ある選択肢の1つと一致している」といったことを確認するプログラムロジックをハードコーディングすることになります。.NET 2.0では、入力チェックを合理化するためのサポートがいくつか取り入れられましたが、これは入力チェックプロセスの自動化や単純化を少しばかり手助けするものにすぎません。入力チェックに関してMSDNを検索しても、見つかる情報の大半は、検証コードをハードコーディングする方法を紹介しています。しかし、検証を必要とする個々の要素に手書きのカスタムコードを用意することは、保守という観点から見れば悪夢としか言いようがありません。

 また、検証のステップをプログラミングのステップと同様に「AならばBする」といった形で概念化することは不自然です。それよりも、検証するデータの「質」に焦点を当てた方がずっと分かりやすいはずです。例えば、入力データを説明するときには、「5〜8文字にする」「負でない数字にする」「必ず最後は『5』で終わる」などというのが普通でしょう。

 本稿で紹介する検証エンジンは、検証プロセスよりもデータの質に焦点を当てるという考え方から生まれています。モジュール形式でデータ主導の検証エンジンアプローチを採用することで、より自然なインターフェイスが実現され、柔軟性が向上し、保守も簡単になりました。Visual Studioでは、デザイン時にさまざまなコンポーネントにプロパティ値を指定することができます。このアプローチを検証属性の定義に使用することは自然の流れであり、これによって、開発者は堅牢な検証メカニズムをもっと簡単に導入できるようになります。また、このアプローチでは検証の設定を構成ファイルに格納するという柔軟な仕組みを採用しているため、検証の変更も簡単になり、開発者や管理者はコンパイルやデプロイをやり直したり、ソースコードを書いたりせずに、検証プロパティの修正やカスタマイズを行うことができます。本稿で紹介する検証エンジンを使えば、わずか数行のコードで幅広い検証基準を活用することができます。

目標とするソリューション

 フォームの入力チェックを実行し、ユーザーにフィードバックし、できればその条件を満たすために必要なその他のアクションを実行できるプログラムを実装します。さらに、できるだけ単純かつ簡単な実装にすることを目指します。

本稿のソリューションの制限

 本稿で紹介するソリューションは、有益ではありますが、どのケースにも適した完全なソリューションではありません。むしろ、80対20の法則を採用しています。つまり、この検証エンジンは、対処する必要があるユースケースの約80%に対して役立ちます。さらに、これまた80対20の法則に従い、残りの20%のユースケースをカバーするには労力の80%が必要になると考えられます(つまり、これまで費やしてきた労力の5倍が必要になります)。

 そのため、今回の検証エンジンでは、例えば複数のフィールド間の関係に基づく検証は実装していません。その代わりに、単一フィールドの検証に焦点を当て、基本的な仕組みを見ていくことにします。

基本となるソリューション:ErrorProviderコンポーネント

 まず、ErrorProviderという便利なMicrosoftコンポーネントを知る必要があります。

 ErrorProviderをビジュアルデザイナにドラッグすると(またはコード内でそのインスタンスを作成すると)、検証メッセージを表示するために必要な基本コンポーネントが作成されます。ErrorProviderの代表的な使用例を次に示します(MSDNライブラリの『方法 : WindowsフォームErrorProviderコンポーネントを使用してフォーム妥当性検査でエラーアイコンを表示する』より引用)。

protected void textBox1_Validating(object sender, CancelEventArgs e)
{
   try
   {
      int x = Int32.Parse(textBox1.Text);
      errorProvider1.SetError(textBox1, "");
   }
   catch (Exception e)
   {
      errorProvider1.SetError(textBox1, "Not an integer value.");
   }
}

 このコードはTextBoxへの入力を検証し、入力値が整数かどうかを確認します。入力値をテストするため、このコードではInt32.Parseメソッドを使って、TextBoxの文字列値を整数に変換できない場合に例外をスローします。入力が有効な場合は、ErrorProvider.SetError呼び出しにより、エラーメッセージの消去が実行されます。入力が無効な場合はcatchブロックが実行され、「Not an integer value」というメッセージを表示するErrorProvider.SetErrorメソッドが呼び出されます。

 このメソッドを、ビジュアルデザイナを使うか、次のコードをプログラミングすることで、textBox1という特定のTextBoxコントロールのValidatingイベントに関連付けます。

this.textBox1.Validating +=
    new CancelEventHandler(this.textBox1_Validating);

 ここに、MSDNライブラリの情報からはまったくわからない重要な事実があります。

 Validatingイベントは、コントロールが別のコントロールにフォーカスを譲ったときに発生します。つまり、イベントが発生するのは、[Tab]キーを使って現在のコントロールから移動したり、マウスで別のコントロールをクリックしたりしたときです。

 この例のSetErrorメソッドが、1つ目の引数でコントロールを受け取っていることに注意してください。これにより、1つのErrorProviderで同時に複数のコントロールのエラーメッセージを処理することが可能になります。

 SetErrorメソッドの2つ目の引数は表示するメッセージです。空の文字列を渡すと、ErrorProviderはエラーメッセージインジケータを完全に抑止します。従って、エラーメッセージを設定することだけでなく、エラー条件が存在しない場合にエラーメッセージを削除することも重要です。

 ErrorProviderには、他のエラー表示テクニックにはない次のような長所があります。

  • ポップアップダイアログを使った場合は、ユーザーが[OK]をクリックするとメッセージが消えてしまうので、メッセージを再表示するためには特定のコーディングが必要です。ErrorProviderはユーザーが要求すればいつでも自動的にエラーを再表示します。
  • 1つのTextBoxまたはLabelコントロールを使ってエラーメッセージを表示する場合は、ポップアップダイアログよりもエラーメッセージを長い期間表示できますが、1つのエラーメッセージしか表示できないという問題があります。複数のエラーを持つフォームでは、新たなエラーが発生するたびに直前のエラーを置き換えることになります。ErrorProviderは、フォーム上のコントロールと同じ数のエラーメッセージを同時に表示することができます。
  • 検証対象のコントロールごとに専用のTextBoxまたはLabelコントロールを追加することも有効なソリューションです(エラーメッセージを表示しなければならない場合のみ、対応するコントロールを表示します)。この場合、ユーザーはマウスを使ってエラーを表示する必要がなくなるので、ErrorProviderよりもやや好ましい面はありますが、これらのTextBoxとLabelを配置するためのフォーム領域とリソースが必要になりますし、かなりの量のUIコードを作成して保守しなければなりません。

別のコントロールへの移動を制限する

 Validatingイベントハンドラのコードを一工夫すると、ユーザーが無効な値を修正するまでは別のコントロールに移動できないようにすることができます。コントロールにイベントハンドラを割り当てた先ほどのコードを見ると、このメソッドがCancelEventHandlerにラップされています。このため、textBox1_Validatingメソッドのcatchブロック内でエラーメッセージを設定したすぐ後に、次の行を追加することができます。

e.Cancel = true;

 このコード行により、通常はValidatingイベントの後に発生するイベントが発生しなくなります。ユーザー側から見ると、現在のコントロールからカーソルが離れなくなり、エラーを修正するまでは[Tab]キーやマウスを使って別のコントロールに移動できなくなります。Validatingイベントについて詳しくは、MSDNライブラリを参照してください。

ErrorProviderの出力

 次に、ErrorProviderが実際にどのような出力をするのかを見てみましょう。図1のシンプルなフォームを見てください。このシンプルなフォームには、バインドされていないDataGridView、2つのTextBoxコントロール、OKボタン、Cancelボタンが含まれています。以降ではこのフォームを中心に話を進めていきます。

図1 サンプルフォーム
図1 サンプルフォーム

 先ほど説明したValidatingメソッドを左側のテキストボックスに関連付け、数字以外の文字を入力すると、ErrorProviderは小さいエラーアイコンを表示します。このエラーアイコンをマウスでポイントすると、対応するエラーメッセージ(この場合は「Not an integer value」)がヒントとして表示されます(図2を参照)。

図2 ErrorProviderのUI
図2 ErrorProviderのUI

 お分かりのように、ErrorProviderを使えば、フォーム入力チェック用のユーザーインターフェイスを簡単に作成することができます。とはいえ、これまでのことをすべて実現するには、フォーム上の個々のコントロールにxxx_Validatingメソッドを手作業でコーディングしなければなりません。Larry Wallが『Programming Perl』(Larry Wall・Tom Christiansen・Jon Orwant 著、Oreilly & Associates Inc、2000年10月)で述べているように、プログラミングの3大美徳の1つは怠け者であることです。

「エネルギーの総支出を減らすために、多大な努力をするように、あなたをかりたてる性質。こうして労力を省くために書いたプログラムは他人も使うようになり、そのプログラムに関する質問にいちいち答えずに済ますためにドキュメントを書くようになる。」

 つまり、この場合で言えば、もっと良い方法があるはずだ、ということです。そして、実際にあるのです。そのためには、CleanCode.Forms.Validatorクラスを利用します。

より優れたソリューション

 今度は、ErrorProviderを利用しつつ、柔軟性も高い検証エンジンの実装方法を考えてみます。具体的には、エラーメッセージをLabelコントロールに表示するようにします(マウスでポイントするのが嫌いな方向けです)。開発者が限界を感じることがないよう、このエンジンでは、カスタムの検証機能と自動的な検証機能を(統合させないまでも)共存させることができなければなりません。

 これを踏まえて、検証の性質とビジネスルールの概念を考えてみましょう。例えば、米国内の電話番号を入力するフォームフィールドがあるとします。この要件の影にあるのが、電話番号が何で構成されているかについての多くの前提条件です。ビジネスルールとしては、次のようなものが挙げられます。

  • 数字とハイフンのみを認める。
  • ハイフンを使う場合、入力はちょうど12文字(10桁の数字と2つのハイフン)でなければならない。
  • ハイフンは3桁目と7桁目の後ろに入れなければならない。
  • ハイフンを使わない場合、入力はちょうど10桁でなければならない。

 一般に、ビジネスルールとは、すべてのビジネスに当てはまるものではなく、個別のビジネスに当てはまるものと考えられていますが、ここで挙げたルールも、データの意味を問うという広い意味でのビジネスルールです。今度は、米国内の電話番号という汎用的な特徴ではなく、このサンプルビジネスのみに当てはまるビジネスルールをもう1つ追加します。

  • 市外局番はカリフォルニア州のものだけでなければならない。

 フォームの入力を処理する多くのソフトウェアアプリケーションは、次の仮想コードのようなロジックを使って、ビジネスルールのチェックをフォームの処理と一緒にハードコーディングしています。

read phoneNumber
if (phoneNumber contains only digits and hyphens) and
    getAreaCode(phoneNumber) is on the California list of area codes
then
    store phoneNumber
else
    flag invalid phone number

 しかし、この会社がオレゴン州やワシントン州にも拡大するとしたらどうなるでしょうか。ビジネスルールの変更に伴い、コードの変更も必要になります。これは、9月のレイバーデイが過ぎてもまだ夏用の白い靴を履いているのと同じくらい格好悪いことであり、きちんとした人々――つまりここで言えばクリーンなコード――ならば絶対にしてはならないことです。データをプログラムの外部に置くソフトウェア開発者はたくさんいますが、ルールを外部化する人は意外に少数です。そしてここが、うまく設計された検証エンジンの力の見せどころになります。ビジネスルールをプログラムの外部に置くことによって、ソフトウェア設計者ではなくビジネスアナリストによる管理を実現することができます。

 従って、本稿の検証エンジンが最終的に目指すところは次のようになります。

  • ビジネスルールを外部でカプセル化する。
  • フォーム全体で利用できるErrorProviderまたはコントロール固有のLabelのいずれかを使って検証エラーを明示する。
  • 共存する検証エンジンの機能範囲を越えたカスタムな検証を実現できるようにする。

ビジネスルールを外部で保守する

 これは本稿の検証エンジンの機能で最も重要な部分ですが、Visual Studio 2005のビジュアルデザイナを使えば非常に簡単に実現できます。とはいえ、学ぶことがないわけではありません。.NETでの永続的な設定については、MSDNライブラリの『方法 : アプリケーション設定を追加または削除する』などを参照してください。

 簡単に言えば、.NETは永続的な設定をローカルシステム上のapplication.exe.configまたはuser.configのいずれかに格納します。これらの設定にアクセスするには、コード内でProperties.Settings.Defaultオブジェクトを使用するか、プロジェクトプロパティの[Settings]ペインのビジュアルデザイナを使用します。ビジネスルールを永続的な設定として格納するということは、それらのルールをuser.configファイルに入れ、必要に応じて自由に編集できる、ということです。さらに一歩進めて、永続的な設定をWindowsフォーム上のコントロールに直接バインドし、ビジネスルールを編集するためのユーザーフレンドリなインターフェイスを作成することも可能です。つまり、ユーザーがフォームの値を編集したときに、その値が自動的にuser.configに格納されるようにすることができます。

 Visual Studio 2005のビジュアルデザイナでは、コードから独立した形でアプリケーションのユーザーインターフェイス層にアクセスすることができます。ビジュアルデザイナ上での操作はコードに自動的に反映されますが、形としては別々に保持されています。フォーム検証用のビジネスルールは、当然、ユーザーインターフェイスに密接に結び付けられます。つまり、フォーム上のコントロールのほとんどに1つ以上の固有のフォーム検証用のビジネスルールが割り当てられます。では、ユーザーインターフェイスを指定するビジュアルデザイナで検証用のビジネスルールを指定してはどうでしょうか。

 ビジュアルデザイナには、フォーム上のコントロールごとにプロパティペインが用意されています。ここで必要なことは、プロパティとしてビジネスルールを追加することだけです。しかし、プロパティペインにはプロパティを追加することができないので、そこが問題です。この問題を簡単に回避する1つの方法は、ユーザー定義可能なプロパティとして提供されているTagプロパティを使用することです。このようなプロパティは1つのコントロールにつき1つだけなので、複数のビジネスルールを1つのパッケージにまとめて、Tagプロパティコンテナに割り当てるようにします。このスキーマを使うことで、コントロールを定義するときにビジネスルールを定義し、永続的な設定と組み合わせてビジネスルールを外部化することができます。

 ビジネスルールに関連付けるには、検証対象の各コントロールに、次のような形式の一連の属性から構成されるTagプロパティ値を割り当てます。

<attr1>=<value1>;<attr2>=<value2>;...;<attrn>=<valuen>

 さらに高度なソリューションとして、ExtenderProviderコントロールを使って、利用可能な属性に対応する実際のプロパティを定義し、Tagプロパティを他の用途に使えるように解放しておく方法もありますが、ここでは簡潔かつシンプルにしておくことにしました。

 表1に、利用可能な属性とその型を示します。

表1 検証属性:利用可能な検証属性とその型および簡単な説明
属性説明
maxLenint > 0フィールド内の文字数は指定された数以下でなければならない。
minLenint > 0フィールド内の文字数は指定された数以上でなければならない。
maxValFloatフィールド内の数字は指定された値以下でなければならない。
minValFloatフィールド内の数字は指定された値以上でなければならない。
pattern正規表現フィールドは指定された正規表現に一致しなければならない。

 最初の2つ(minLenmaxLen)では、文字列として取得する値の長さを制御することができます。同様に、その次の2つ(minValmaxVal)では、数値入力の範囲を制御することができます。最後の属性(pattern)には、正規表現の引数が必要です(正規表現については『Regular-Expressions.info』を参照)。ニーズに合わせて属性を「組み合わせて一致」させることができます。表2に、役に立つ一般的な属性の組み合わせを示します。minValmaxValで表すことができる制約は、正規表現のpatternでも表すことができます。

表2 一般的な検証属性の組み合わせ:よく使われる一般的な属性の組み合わせ
属性の一覧意味
maxLen=10値は10文字以下でなければならない。
minVal=0値を負にすることはできない。
minVal=0;maxVal=100値は0以上100以下でなければならない。
minLen=1値は非空でなければならない。
pattern=.値は非空でなければならない。
minLen=5;maxLen=5値はちょうど5文字でなければならない。
pattern=.{5}値はちょうど5文字でなければならない。
pattern=^S+$値にスペースを入れることはできない。
pattern=^-?(?:d*.?d+|d+.)$値は数値でなければならない。
pattern=^d{3}-d{3}-d{4}$値は標準的な米国内の電話番号でなければならない。
pattern=^w[w.]*@w+.w[w.]*$値は電子メールアドレスでなければならない。

 Visual Studioのビジュアルデザイナでフォームをデザインしながら、各コントロールのプロパティペインにビジネスルールを入力することができます。次に、そのプロパティをアプリケーション設定に関連付け、アプリケーションが実行されたときに外部化されるようにする必要があります。ステップは次のとおりです。

 まず、コントロールのTagプロパティにビジネスルールを入力します。次に、プロパティペインで[(ApplicationSettings)]項目を探します(プロパティペインがカテゴリ別に分類されている場合は、[Data]ノードの下にあります)。[(ApplicationSettings)]を展開すると[(PropertyBinding)]項目が表示されます。値フィールドをクリックすると、プロパティエディタを表示するための省略記号([...])ボタンが表示されます(図3を参照)。また、Tagプロパティにはpattern型のビジネスルール(正規表現)が入力されています。

図3 アプリケーション設定
図3 アプリケーション設定

 [(PropertyBinding)]の省略記号ボタンをクリックします。選択したコントロールに関する[Application Settings]ダイアログボックスが開きます(図4を参照)。このダイアログボックスを使って、プロパティ値をコントロールの個々のアプリケーション設定に割り当てます。

図4 新規のApplication Settingsダイアログボックス
図4 新規のApplication Settingsダイアログボックス

 Tagプロパティを探して、対応するドロップダウンリストを開き、[New]をクリックします。リスト内のTagプロパティに入力した値が、既定値(DefaultValue)として表示されます(図5を参照)。[Name]には、この新しい設定の名前を入力します。例えば図5では、この設定はサンプルアプリケーションのleftTextBoxコントロールに関連付けられているので、「leftTextBoxBusinessRules」という名前を使いました。[Scope]には、「Application」または「User」を指定します。「Application」を指定した場合、この設定の値はprogram.exe.configに格納され、単一のコンピュータ上のすべてのユーザーに共通の読み取り専用の値となります。「User」を指定した場合、この設定の値はプログラム内で変更可能になり、変更した値はユーザーの「Application Data」フォルダ内のユーザー固有のuser.configファイルにオーバーライドとして格納されます。

図5 New Application Settingダイアログボックス:新しい設定に名前を割り当てる
図5 New Application Settingダイアログボックス:新しい設定に名前を割り当てる

 [OK]をクリックして[New Application Setting]ダイアログボックスを閉じ、再度[OK]をクリックして[Application Settings]ダイアログボックスを閉じます。これでプロパティペインは図6のようになります。先ほど入力したTagプロパティの値が削除されて代わりに小さいアイコンが表示され、[(ApplicationSettings)]セクションの下にTagプロパティが指定の名前で表示されていることに注意してください。プロパティをアプリケーション設定に割り当てると、そのプロパティ(この場合はTag)はプロパティペインの[(ApplicationSettings)]項目の下に移動し、元のプロパティ値は小さいアイコンに置き換えられます。

図6 設定の完了
図6 設定の完了

 理論上は、これでプロパティのバインディング作業は終わりですが、実際にはまだ終わっていません。実行しなければならないステップがもう1つあります。プロジェクトプロパティウィンドウの[Settings]タブを開いてください。leftTextBoxコントロールの例で言えば、先ほど作成したleftTextBoxBusinessRulesの設定が表示されているはずですが、図7を見ると、Tagプロパティの値(ビジネスルール)がプロジェクトプロパティウィンドウの[Settings]ペインから消えています。

図7 値の削除
図7 値の削除

 Tagプロパティをアプリケーション設定に割り当てたときに、Visual StudioがコントロールのTagプロパティから値を削除したのです。そのため、このアプリケーション設定の既定値として指定されていても、プロジェクトプロパティウィンドウの[Settings]タブには表示されません。

 これを表示するのは簡単です。設定の型をSystem.Objectからstringに変更するだけで、既定値が表示されます(図8を参照してください)。

図8 Tag値の強制表示
図8 Tag値の強制表示

実装

 本稿で作成した検証エンジンの名前はValidatorです。これは私のオープンソースのWebサイトからダウンロードできます(Products >> Documentation >> C# と選択してください)。このエンジンは、前述のTagプロパティで指定した属性を使って、フォーム上のコントロール(TextBoxコントロールやDataGridViewコントロール)を検証します。エラーが発生すると、無効な入力ごとに個別にエラーメッセージを表示するだけでなく、指定された共通のフォーム提出ボタン(通常は[OK]ボタン)を操作不能にすることもできます。検証エラーの表示には、コントロールごとに異なる固有のLabelコントロールでも、標準のErrorProviderコンポーネントでも使用できます。どちらを使うかは、開発者の判断次第です。ErrorProviderには、Labelコンポーネントをわざわざ作成して検証コンポーネントに関連付ける必要がないという長所もありますが、既に説明したように、検証エラーを表示するにはマウスを使わなければならないという欠点もあります。

 コントロールを検証するには、そのコントロールをValidatorインスタンスに追加し、コントロールのTextChangedイベントハンドラまたはValidatingイベントハンドラの中でValidate()メソッドを呼び出します。MSDNライブラリではValidatingイベントハンドラが推奨されていますが、Validatingはフォーカスがコントロールから離れたときしか起動しません。もっと繊細なコントロール(キー操作を要するものなど)が必要な場合は、TextChangedをお勧めします。

 検証エンジンは、指定されたコントロールのすべての検証属性(ビジネスルール)を評価しますが、1つのコントロールにつき一度に1つのエラーしか報告しません。例えば、1つの入力が最大長テストと最大値テストの両方に不合格だったとしても、エンジンがユーザーに報告するのはそのうちの一方のエラーだけです。そのため、ユーザーがそのエラーを修正した後で、もう一方のエラー条件が表示される可能性があります。

サンプルのコーディング

 では、実際のコーディングについて説明しましょうょう。これまで使ってきたシンプルなサンプルフォームのユーザーコードは次のとおりです(デザイナで生成したコードとは異なります)。個々の短いメソッドはイベントハンドラなので、適切なイベントに関連付ける必要があります(どのイベントに関連付けるかは、メソッドの名前から分かるはずです)。

using System;
using System.ComponentModel;
using System.Windows.Forms;
using CleanCode.Forms;

namespace ValidationDemo
{
   public partial class Form1 : Form
   {
      private Validator validator;

      public Form1()
      {
         InitializeComponent();
      }

      private void Form1_Load(object sender, EventArgs e)
      {
         validator = new Validator(okButton, errorProvider);
         validator.Add(dataGridView);
         validator.Add(leftTextBox);
         validator.Add(rightTextBox);
      }

      private void okButton_Click(object sender, EventArgs e)
      {
         MessageBox.Show("OK clicked");
      }

      private void cancelButton_Click(object sender, EventArgs e)
      {
         MessageBox.Show("cancel clicked");
      }

      private void leftTextBox_Validating(object sender, 
                                          CancelEventArgs e)
      {
         if (!validator.Validate(leftTextBox)) { e.Cancel = true; }
      }

      private void rightTextBox_TextChanged(object sender, 
                                            EventArgs e)
      {
         validator.Validate(rightTextBox);
      }

      private void dataGridView_CellValidating(
         object sender, DataGridViewCellValidatingEventArgs e)
      {
         if (!validator.Validate((DataGridView)sender, e))
         {
            // e.Cancel = true; // this really traps the user in there!
         }
      }
   }
}

 これが、図1のサンプルアプリケーションに関してVisual Studio 2005内で記述する検証コードのすべてです。実際の検証コードはValidatorに含まれています。この他に必要なのはビジネスルールだけです。次に、これについて簡単に説明します。

 前述のコードで、Form1_Loadイベントハンドラは検証エンジンのインスタンスを作成し、検証する各コントロールをそのインスタンスに追加しています。Validatorコンストラクタがフォームの[OK]ボタンの参照を受け取ることに注意してください。Validatorはその参照を使って、すべてのコントロールが入力チェックに合格した場合は[OK]ボタンを選択可能にし、いずれかのコントロールが入力チェックに合格しなかった場合は[OK]ボタンを選択不能(グレーアウト)にします。また、Validatorコンストラクタは、エラー表示用のErrorProviderも受け取ります。

 leftTextBoxコントロールとrightTextBoxコントロールで異なるイベントハンドラを使っているのは、単に前述の動作の違いを示すためです。前者はフォーカスがフィールドを離れたときに検証を行い、後者はキー操作のたびに検証を行います。また、leftTextBoxハンドラでは、エラーがある限りユーザーが別のコントロールに移動できないようにしています。実際には、すべてのコントロールを同じイベントで同じように動作させたい場合は、同じイベントハンドラのメソッドを使用してかまいません。

 DataGridViewコントロールのような複数のデータ値を含むコントロールの場合でも、メソッドを呼び出して検証を実行する処理は、単一値のコントロールの場合とほぼ同じです。ただし、ビジネスルールセットに指定する情報の量は多くなります(詳しくは後述)。DataGridView検証の処理は、特にDataGridViewがバインドされている場合にはかなり複雑になる可能性がありますが、本稿では説明を省きます。

サンプルアプリケーションのビジネスルール

 前述のコードに加えて、leftTextBoxコントロール、rightTextBoxコントロール、dataGridViewコントロールをビジネスルールに関連付ける必要があります。具体的には、これらのコントロールのTagプロパティを表3のように設定します。

表3 サンプルアプリケーションのTagプロパティ値:サンプルアプリケーションの3つのTextBoxコントロールに対するTagの設定
コントロールTagプロパティ
leftTextBoxpattern=^w[w.]*@w+.w[w.]*$;minLen=2
rightTextBoxpattern=^-?(?:d*.?d+|d+.)$
dataGridView[Column]pattern=^w+$;[MatchExpr]pattern=(.*)

 これらのルールでは、正規表現を用いて、各コントロールに入力すべき値を記述しています。leftTextBoxには、電子メールアドレス形式の値を入力しなければなりません(「foo@bar.com」も「e@a.b.c.d」も有効です)。rightTextBoxには、5、-25、-3.9999、.81などの数値を入力しなければなりません。dataGridViewでは、列ごとにビジネスルールを割り当てることも可能ですが、必須ではありません。この場合、このルールは、「Column」という名前の列では文字または数字のみを受け付け、「MatchExpr」という列では入力のどこかに1組の始めかっこと終わりかっこが必要であることを表しています。

著者メモ
 表3で、複数のビジネスルールセットを1つのプロパティに埋め込む場合の入力形式に注意してください。各列の名前を大かっこで囲んで指定し、その後ろにビジネスルールを記述しています。

サンプルを実行する場合の注意事項

 アプリケーションをビルドして実行し、どうなるか見てみましょう。入力チェックに不合格であるとボタンは選択不能になります。この場合、ValidatorはErrorProviderを使って検証エラーを表示します。今回のコードではErrorProviderの作成を分離化しているので、検証エンジンに実装されているビジネスルールカテゴリの範囲に含まれない独自の検証チェックをイベントハンドラに自由に追加することができます。

 ここでは、ビジネスルールとコードをどのように切り離すか、なぜ切り離すのかを理解していただけるように、検証エンジンを利用しました。検証エンジンそのもののメカニズムについては、ソースコードを参照してください。これは、以前にWebサイト用にPerlとJavaScriptを使って実装した「PageValidator」という検証エンジンの簡易バージョンです。同じエンジンをクライアントとサーバの両方で実行することで、クライアントとサーバの両方で高速応答とセキュリティを実現できます。

著者紹介

Michael Sorens(Michael Sorens)
フリーランスのソフトウェアエンジニア。フェニックス大学やコミュニティカレッジでの指導、2冊の本とさまざまな記事の執筆、さらにオープンソースのWebサイトを通して、優れたデザインの種をまき続けている。Fortune 500企業やベンチャー企業でJava、C#、Perl、C、Lisp、PostScriptなどのプログラミングに従事。お気に入りのプロジェクトは、シリコン製でプリンタヘッドにレーザーを使用した、独立宣言を文字どおりピンの頭に印字できる世界最小のワープロの設計と実装。
最新トップニュース
データメーション
【データメーション】
次の「Beverly Hills Chihuahua」はDVD違法コピー対策犬(10月15日)
ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」
【ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」】
「情報が気持ちよく伝わる世界を作る!」/アスカティースリー株式会社(10月15日)
Graphic Design Forum
【Graphic Design Forum】
あなたならどうする - 倫理にかかわる問題 (10月14日)
エンジニアの独り言
【エンジニアの独り言】
得体の知れない情報(?)との向き合い方(9月17日)
最新テクノロジーの意外な処方箋
【最新テクノロジーの意外な処方箋】
昆虫と退屈なことについて(9月16日)
「IT の耳」
「IT の耳」
【書評】『メディアの実験集「モノサシに目印」』 ――デザインを遊ぶ(10月15日)
Eメールマーケティング事情
Eメールマーケティング事情
企業メルマガ担当者(10月15日)
日本と韓国のインターネットビジネス最新動向調査
日本と韓国のインターネットビジネス最新動向調査
日本と韓国の Blog 比較2―展望(10月15日)
百式のネットビジネス研究
百式のネットビジネス研究
iPhone 用アプリを毎日作ってソースコードごと公開している「Apps Amuck」(10月15日)
SNSをビジネスに活用しよう
SNSをビジネスに活用しよう
周到に Hype(ハイプ)を迎えないと「幻滅期」は超えられない。(後篇)(10月14日)
developer.com
developer.com
デザインパターンの使い方: Builder(10月14日)
エンジニア転職ノウハウ開発室
エンジニア転職ノウハウ開発室
職種別 採用天気予報 [08年10〜12月期](10月14日)
アイレップの SEM フロンティア
アイレップの SEM フロンティア
キーワードとプレースメントの併用で Google AdWords 広告の最適化を進めよう(10月14日)
台湾企業が席巻する電子製品製造
台湾企業が席巻する電子製品製造
蔓延する市場の不透明感、不況の今だからこそ考える生産アウトソーシング(10月10日)
IT マネジメント
IT マネジメント
「後戻りできない」 Windows 7(10月10日)
海外のインターネットコムアメリカ韓国ドイツトルコ
Copyright 2008 Jupitermedia Corporation All Rights Reserved.http://www.internet.com/