[Tips] Validatingイベントを使用する その3 ~ フォーカス移動時のValidatingイベントを抑制する ~

前回までの記事はこちら


Validatingイベントで入力チェックを実施し、 e.Cancel = true にすることで、他のコントロールへフォーカスが移動できなくなるのはこれまでに説明した通りです。

今回は、Validatingイベント後のフォーカス移動先が、[キャンセル]や[閉じる]ボタンの場合を考えてみます。

前回までに作成したプログラムで実験をしてみましょう。

1.データ1のテキストボックスに「hiros.net」と入力します。
2.[閉じる]ボタンをクリックします。

現在までのコードだと、データ1に不正な文字が入力されている場合は下図のようになり、当然画面を閉じることはできません。
画面を閉じたければ、エラーを修正するしか方法がありません。

実行例

上記の問題を解決するには、Validatingイベントを発生させたくないコントロールの CauseValidationプロパティに falseをセットする必要があります。
このように設定を行うと、データ1のテキストボックスに不正があったとしても、フォーカスが[閉じる]ボタンへ移動しても、Validatingイベントは発生しなくなり、エラーを修正しなくても画面を閉じることができるようになります。

次にフォーム右上の[X]ボタンはどうでしょうか。
これも、データ1のテキストボックスにエラーがある場合は、画面を閉じることができません。
この問題は、Validatingイベント内で ActiveControlをチェックすることで回避することが可能です。
通常、Validatingイベントが発生した場合は、ActiveControlプロパティはすでに次のコントロールになっています。
今回の例では、txtData1のValidatingイベントが発生すると、ActiveControlの値はtxtData2となります。
しかし、[Esc]やフォーム右上の[X]ボタンがクリックされた場合には、ActiveControlプロパティの値は txtData1のままとなっているのです。
これを図にすると以下のようになります。

フォーカス移動時のイメージ

以上のことを利用すると、txtData1のValidatingイベントの中で e.Cancel = true にする条件は

1.不正な文字が含まれている
2.ActiveControlがtxtData1以外のとき
の2つを満たしているときとなります。

コード例は以下の通りです。

VBの例

Private Sub txtData1_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles txtData1.Validating
    ' 不正な文字「.」が含まれている かつ ActiveControlがtxtData1ではない
    If txtData1.Text.IndexOf(".") > -1 AndAlso ActiveControl IsNot txtData1 Then
        MessageBox.Show("不正な文字「.」が含まれています")

        ' 後続のイベントをキャンセル
        e.Cancel = True

        'txtData1 にエラーアイコンとメッセージの表示をセット
        errorProvider1.SetError(txtData1, "不正な文字が入力されています。")
    End If
End Sub

C#の例

private void textBox1_Validating(object sender, CancelEventArgs e)
{
    // 不正な文字「.」が含まれている かつ ActiveControlがtxtData1ではない
    if (txtData1.Text.IndexOf('.') > -1  && ActiveControl != txtData1)
    {                
        MessageBox.Show("不正な文字「.」が含まれています");

        // 後続のイベントをキャンセル
        e.Cancel = true;

        // txtData1 にエラーアイコンとメッセージの表示をセット
        errorProvider1.SetError(txtData1, "不正な文字が入力されています。");
    }
}

以上で、フォームの[X]ボタンクリック時に Validatingイベントを発生することなくフォームを閉じることができるようになります。

[Tips] Validatingイベントを使用する その2 ~ ErrorProviderコントロールとの組み合わせ ~

[Tips] Validatingイベントを使用する その1 では基本的な使い方について説明しました。
今回は、Validatingイベントと ErrorProviderコントロールを組み合わせて、不正な文字が入力さている場合にエラーアイコンを表示する方法について説明します。

デザインは以下のようにします。
前回のデザインに ErrroProviderコントロールを追加しただけです。

画面デザイン

不正な文字の入力チェックは、前回同様 Validatingイベントで行います。
不正な文字が入力されていた場合は、errorProviderコントロールの SetErrorメソッドを呼び出すコードを追加します。
そして、入力チェックにおいて不正な文字が見つからなかった場合(要するに Validatingイベントで e.Cancel = trueにしなかった場合)は、エラーが発生していないことになるので ErrorProviderコントロールの SetErrorメソッドでエラー状態をクリアしてあげます。

以下にコード例を示します。

VBの例

Private Sub txtData1_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles txtData1.Validating
    ' 不正な文字「.」が含まれているか?
    If txtData1.Text.IndexOf(".") > -1 Then
        MessageBox.Show("不正な文字「.」が含まれています")

        ' 後続のイベントをキャンセル
        e.Cancel = True

        'txtData1 にエラーアイコンとメッセージの表示をセット
        errorProvider1.SetError(txtData1, "不正な文字が入力されています。")
    End If
End Sub

Private Sub txtData1_Validated(sender As Object, e As EventArgs) Handles txtData1.Validated
    'txtData1のエラーを解除
    errorProvider1.SetError(txtData1, "")
End Sub

C#の例

private void textBox1_Validating(object sender, CancelEventArgs e)
{
    // 不正な文字「.」が含まれているか?
    if (txtData1.Text.IndexOf('.') > -1 && this.ActiveControl != txtData1)
    {                
        MessageBox.Show("不正な文字「.」が含まれています");

        // 後続のイベントをキャンセル
        e.Cancel = true;

        // txtData1 にエラーアイコンとメッセージの表示をセット
        errorProvider1.SetError(txtData1, "不正な文字が入力されています。");
    }
}

private void txtData1_Validated(object sender, EventArgs e)
{
    // txtData1のエラーを解除
    errorProvider1.SetError(txtData1, "");
}

実行例は以下の通りです。
実行例

[ErrorProvider][Tips] いつエラーアイコンが点滅するかを設定する


ErroProviderのエラーアイコンは、BlinkStyleプロパティを使用して、点滅するタイミングを設定することができます。

BlinkStyleプロパティには、ErrorBlinkStyle列挙体の値を設定します。

メンバ名 説明
AlwaysBlink エラー アイコンが最初に表示されたとき、またはエラーを説明する文字列がコントロールに対して設定されている状態でエラー アイコンが既に表示されている場合は、常に点滅します。
BlinkIfDifferentError アイコンが既に表示されていて、新しいエラー文字列がコントロールに対して設定されると、点滅します。
NeverBlink エラー アイコンは点滅しません。

下記は、いつエラーアイコンが点滅するかを設定する例です。

フォームロード時にAlwaysBlinkを設定して、常に点滅するようにしています。

VBの例

' フォームロード時の処理
Private Sub Form6_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    '★★★常に点滅させる★★★
    ErrorProvider1.BlinkStyle = ErrorBlinkStyle.AlwaysBlink
End Sub

' テキストボックスの内容検証処理
Private Sub txtAge_Validating(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles txtAge.Validating
    Try
        '入力値を数値に変換する
        Dim iNum As Integer = Integer.Parse(txtAge.Text)

        '正常に整数に変換できた場合はエラーをクリアする
        ErrorProvider1.SetError(txtAge, "")
    Catch ex As Exception
        'イベントをキャンセルする
        e.Cancel = True

        '例外が発生したのでエラーを表示する
        ErrorProvider1.SetError(txtAge, "整数値以外の文字が入力されました!!")
    End Try
End Sub

C#の例

// フォームロード時の処理
private void Form6_Load(object sender, EventArgs e)
{
    // ★★★常に点滅させる★★★
    errorProvider1.BlinkStyle = ErrorBlinkStyle.AlwaysBlink;
}

// テキストボックスの内容検証処理
private void txtAge_Validating(object sender, CancelEventArgs e)
{
    try
    {
        // 入力値を数値に変換する
        int iAge = int.Parse(txtAge.Text);

        // 正常に整数に変換できた場合はエラーをクリアする
        errorProvider1.SetError(txtAge, "");
    }
    catch (Exception)
    {
        e.Cancel = true;

        // ★★★例外が発生したのでエラーを表示する★★★
        errorProvider1.SetError(txtAge, "整数値以外の文字が入力されました!!");
    }
}

[ErrorProvider][Tips] アイコンの点滅速度を調整する


アイコンの点滅速度を調整するにはBlinkRateプロパティ(単位mSec)を使用します(既定値は250mSec)。

下記は、アイコンの点滅速度を調整する例です。

フォームロード時に、点滅速度を500mSecに設定しています。

VBの例

' フォームロード時の処理
Private Sub Form5_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    '★★★点滅速度を0.5秒間隔にする★★★
    ErrorProvider1.BlinkRate = 500
End Sub

' テキストボックスの内容検証処理
Private Sub txtAge_Validating(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles txtAge.Validating
    Try
        '入力値を数値に変換する
        Dim iNum As Integer = Integer.Parse(txtAge.Text)

        '正常に整数に変換できた場合はエラーをクリアする
        ErrorProvider1.SetError(txtAge, "")
    Catch ex As Exception
        'イベントをキャンセルする
        e.Cancel = True

        '例外が発生したのでエラーを表示する
        ErrorProvider1.SetError(txtAge, "整数値以外の文字が入力されました!!")
    End Try
End Sub

C#の例

// フォームロード時の処理
private void Form5_Load(object sender, EventArgs e)
{
    // ★★★点滅速度を0.5秒間隔にする★★★
    errorProvider1.BlinkRate = 500;
}

// テキストボックスの内容検証処理
private void txtAge_Validating(object sender, CancelEventArgs e)
{
    try
    {
        // 入力値を数値に変換する
        int iAge = int.Parse(txtAge.Text);

        // 正常に整数に変換できた場合はエラーをクリアする
        errorProvider1.SetError(txtAge, "");
    }
    catch (Exception)
    {
        e.Cancel = true;

        // ★★★例外が発生したのでエラーを表示する★★★
        errorProvider1.SetError(txtAge, "整数値以外の文字が入力されました!!");
    }
}