SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

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

ErrorProviderと正規表現を使った入力チェック

実装

 本稿で作成した検証エンジンの名前は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」という検証エンジンの簡易バージョンです。同じエンジンをクライアントとサーバの両方で実行することで、クライアントとサーバの両方で高速応答とセキュリティを実現できます。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Michael Sorens(Michael Sorens)

フリーランスのソフトウェアエンジニア。フェニックス大学やコミュニティカレッジでの指導、2冊の本とさまざまな記事の執筆、さらにオープンソースのWebサイトを通して、優れたデザインの種をまき続けている。Fortune 500企業やベンチャー企業でJava、C#、Perl、C、Lisp、PostScriptなどの...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/1012 2007/02/27 00:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー