none
CausesValidation と Validating イベント RRS feed

  • 質問

  • FormにTextBox1とButtonを配置し、

    Button1のCausesValidationプロパティをFalseに設定し、以下のコードを書きました。

     

    Public Class Form1

        Private Sub TextBox1_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles TextBox1.Validating
            e.Cancel = True
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Me.Close()
        End Sub
    End Class

     

    TextBox1に文字を入力してButton1をクリックしてもTextBox1_Validatingイベントが発生してしまって(Debug文などで確認)終了することができません。

    CausesValidation = False って効かないのでしょか?

     

    環境

    VS2005 SP1

    WinXP Pro SP3

    VPC2007 SP1

    2008年11月14日 2:22

回答

  •  コリン星人 さんからの引用

    CausesValidation = False って効かないのでしょか?

     

    Button1 に対しては効きますよ。

     

    あるコントロール (A とします) にフォーカスが移動した時に、A の CausesValidation プロパティが評価され、False であれば検証イベントは発生しませんが、その後別のコントロールにフォーカスが移った場合は A の CausesValidation プロパティの値は関係ありません。

     

    今回の例ですと Button1 で Form.Close しているのが原因なのではないでしょうか。
    Form が Close されるということはフォーカスは Button1 に留まらないということになります。

    2008年11月14日 6:27
  •  コリン星人 さんからの引用

    CausesValidationプロパティって検証が必要な他のコントロールに対してValidatingイベントを発生させるんじゃなかったですか?

    つまり、もしButton1.CausesValidation=Trueであったならば、フォーカスがButton1に移動した時点で他の(この場合はTextBox1の)Validatingイベントを発生させるんじゃなかったですか?

     

    そうです。 私が疑っているのは、その後、Button1 から別の何かにフォーカスが移っているのではないかというところです。

    なので今回の場合はButton1.CausesValidation=FalseですからTextBox1のValidatingイベントは発生しないで無事にフォームを閉じることができると思っていたのですが。

     

    必要最小限のコードで試すと自明のとおりで、通常であればそうなります。
    (私も .NET Framework 2.0 で今試してみましたが、思惑どおり閉じることができました)

     

    Button1がクリックされた後でForm.CloseなのでButton1にはフォーカスが移動する(CausesValidationプロパティが評価される)ように思うのですけど。フォームを必ず閉じることができるボタン(よくある[終了]ボタンなど)は作成できないってことですか?

     

    Me.Close か何かのタイミングで、フォーカスが Button1 からどこかへ移動してしまうような要因があるのではないかと思います。

     

    # こういう時は最小限のコードで試して原因を探るか、デバッグをうまく活用した方が早いです。

    # ただしフォーカスがらみはデバッグでインライン実行すると結果が変わるので注意が必要です。

    2008年11月14日 10:04
  • #言うだけ言ってみる

     

    Me.Closeは単なるメソッドなのでその直後にコードが走らないということはありませんので

    そういう意味では、FormClosingイベントなどに影響のある記述はないでしょうか?

    あとは親子関係のフォームが表示されているなど。
    2008年11月14日 19:31
  •  コリン星人 さんからの引用

    Me.Close()を削除してみると仰る通りにフォーカスがButton1に移動することができました。でもMe.Close()が入るとだめです。

     

    やはり Close メソッドのせいですか...

     

     コリン星人 さんからの引用

    話はそれますが、ValidatingイベントのeとFrom_Closingイベントのeは同じものなんですね。初めて知りました。

     

    せっかく .NET Framework 2.0 を使っているのですから Form.Closing イベントではなく Form.FormClosing イベントを使うようにしましょう。 ちなみに Form.FormClosing イベントの引数 e は CancelEventArgs ではないので別のものになります。

    2008年11月16日 7:27

すべての返信

  •  コリン星人 さんからの引用

    CausesValidation = False って効かないのでしょか?

     

    Button1 に対しては効きますよ。

     

    あるコントロール (A とします) にフォーカスが移動した時に、A の CausesValidation プロパティが評価され、False であれば検証イベントは発生しませんが、その後別のコントロールにフォーカスが移った場合は A の CausesValidation プロパティの値は関係ありません。

     

    今回の例ですと Button1 で Form.Close しているのが原因なのではないでしょうか。
    Form が Close されるということはフォーカスは Button1 に留まらないということになります。

    2008年11月14日 6:27
  • じゃんぬねっと様

    レスありがとうございます。

     

    CausesValidationプロパティって検証が必要な他のコントロールに対してValidatingイベントを発生させるんじゃなかったですか?

    つまり、もしButton1.CausesValidation=Trueであったならば、フォーカスがButton1に移動した時点で他の(この場合はTextBox1の)Validatingイベントを発生させるんじゃなかったですか?

    なので今回の場合はButton1.CausesValidation=FalseですからTextBox1のValidatingイベントは発生しないで無事にフォームを閉じることができると思っていたのですが。

     じゃんぬねっと さんからの引用

    今回の例ですと Button1 で Form.Close しているのが原因なのではないでしょうか。
    Form が Close されるということはフォーカスは Button1 に留まらないということになります。

    これ、ちょっと理解ができなかったです。

    Button1がクリックされた後でForm.CloseなのでButton1にはフォーカスが移動する(CausesValidationプロパティが評価される)ように思うのですけど。

    フォームを必ず閉じることができるボタン(よくある[終了]ボタンなど)は作成できないってことですか?

    2008年11月14日 9:29
  •  コリン星人 さんからの引用

    CausesValidationプロパティって検証が必要な他のコントロールに対してValidatingイベントを発生させるんじゃなかったですか?

    つまり、もしButton1.CausesValidation=Trueであったならば、フォーカスがButton1に移動した時点で他の(この場合はTextBox1の)Validatingイベントを発生させるんじゃなかったですか?

     

    そうです。 私が疑っているのは、その後、Button1 から別の何かにフォーカスが移っているのではないかというところです。

    なので今回の場合はButton1.CausesValidation=FalseですからTextBox1のValidatingイベントは発生しないで無事にフォームを閉じることができると思っていたのですが。

     

    必要最小限のコードで試すと自明のとおりで、通常であればそうなります。
    (私も .NET Framework 2.0 で今試してみましたが、思惑どおり閉じることができました)

     

    Button1がクリックされた後でForm.CloseなのでButton1にはフォーカスが移動する(CausesValidationプロパティが評価される)ように思うのですけど。フォームを必ず閉じることができるボタン(よくある[終了]ボタンなど)は作成できないってことですか?

     

    Me.Close か何かのタイミングで、フォーカスが Button1 からどこかへ移動してしまうような要因があるのではないかと思います。

     

    # こういう時は最小限のコードで試して原因を探るか、デバッグをうまく活用した方が早いです。

    # ただしフォーカスがらみはデバッグでインライン実行すると結果が変わるので注意が必要です。

    2008年11月14日 10:04
  • 別のPC(といっても環境はほとんど同じですが)で最小コードで試してみましたがやはり同じ現象になります。

    Me.Close()を削除してみると仰る通りにフォーカスがButton1に移動することができました。

    でもMe.Close()が入るとだめです。

    じゃんぬねっとさんの環境では無事に終了できたということですので私の環境に何かだめな点があるのかな。

    とりあえず思いつくのはVirtualPC上で開発しているってことですが、残念ながら今私のとことでは素の開発環境がありません。

    そこで実行環境だけでもと思い、ビルドしてそのEXEを素のWindowsXPSP3の環境で実行しましたがやはり同じ現象になります。

    ということは作成されたアセンブリ自体が既に駄目ってことですね。

    今のところ、ちょっと手の打ちようがありません。

    2008年11月14日 11:18
  • #言うだけ言ってみる

     

    Me.Closeは単なるメソッドなのでその直後にコードが走らないということはありませんので

    そういう意味では、FormClosingイベントなどに影響のある記述はないでしょうか?

    あとは親子関係のフォームが表示されているなど。
    2008年11月14日 19:31
  • まどか様

    レスありがとうございます。

     

    最初に書いたとおりの最小コードでテストしていますのでMe.Close()しかありません。

     

    ご指摘で「ひょっとしてアプリケーションフレームワークが悪さしてるのかな」とちょっと気になったのでアプリケーションフレームワークのチェックを外し、自分でSub Mainを記述してやってみましたが結果は同じでした。

    2008年11月15日 10:44
  • 念のためにC#でも同じことを試してみましたが同様の現象になります。

    根本的に環境が何かおかしいみたいですね。

    2008年11月16日 5:07
  • いろいろググっていると以下のページを見つけました。

    http://blog.livedoor.jp/akf0/archives/51212288.html

    このページを見るとすでにVisual Studio 2005 Beta 2の時点でMicrosoftにフィードバックされて(よく目にするJittaさんがフィードバックされているようです)、「これは製品の仕様」となっているようです。

    ここで示されている解決方法のFrom_Closingイベント内でe.Cancel=Falseとすることで終了させることができました。

     

    話はそれますが、ValidatingイベントのeとFrom_Closingイベントのeは同じものなんですね。初めて知りました。

    2008年11月16日 5:45
  •  コリン星人 さんからの引用

    Me.Close()を削除してみると仰る通りにフォーカスがButton1に移動することができました。でもMe.Close()が入るとだめです。

     

    やはり Close メソッドのせいですか...

     

     コリン星人 さんからの引用

    話はそれますが、ValidatingイベントのeとFrom_Closingイベントのeは同じものなんですね。初めて知りました。

     

    せっかく .NET Framework 2.0 を使っているのですから Form.Closing イベントではなく Form.FormClosing イベントを使うようにしましょう。 ちなみに Form.FormClosing イベントの引数 e は CancelEventArgs ではないので別のものになります。

    2008年11月16日 7:27
  •  じゃんぬねっと さんからの引用

    せっかく .NET Framework 2.0 を使っているのですから Form.Closing イベントではなく Form.FormClosing イベントを使うようにしましょう。

    あ、すみません。書き間違いです。Form.FormClosing イベントを使っております。

     

     じゃんぬねっと さんからの引用

     ちなみに Form.FormClosing イベントの引数 e は CancelEventArgs ではないので別のものになります。

    あ、そうですね。型が違いますもんね。

    以下のコードでTextBox1_Validatingのe.Cancel = Trueを通さないでForm1_FormClosingでe.Cancel をチェックするとFalseで渡されてきて、TextBox1_Validatingのe.Cancel = Trueを通してForm1_FormClosingでe.Cancel をチェックするとTrueで渡されてくるんです。

    FormクラスがTextBox1_Validatingイベントを発生させた後でTextBox1_ValidatingのCancelEventArgs.CancelをForm1_FormClosingを発生させるときにFormClosingEventArgs.Cancelプロパティにコピーしているってことですかね?



    Public Class Form1
        Private Sub TextBox1_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles TextBox1.Validating
            e.Cancel = True
        End Sub
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Me.Close()
        End Sub
        Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            e.Cancel = False
        End Sub
    End Class


     

    2008年11月16日 8:35