トップ回答者
CausesValidation と Validating イベント

質問
-
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 SubPrivate Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.Close()
End Sub
End ClassTextBox1に文字を入力してButton1をクリックしてもTextBox1_Validatingイベントが発生してしまって(Debug文などで確認)終了することができません。
CausesValidation = False って効かないのでしょか?
環境
VS2005 SP1
WinXP Pro SP3
VPC2007 SP1
回答
-
コリン星人 さんからの引用 CausesValidation = False って効かないのでしょか?
Button1 に対しては効きますよ。
あるコントロール (A とします) にフォーカスが移動した時に、A の CausesValidation プロパティが評価され、False であれば検証イベントは発生しませんが、その後別のコントロールにフォーカスが移った場合は A の CausesValidation プロパティの値は関係ありません。
今回の例ですと Button1 で Form.Close しているのが原因なのではないでしょうか。
Form が Close されるということはフォーカスは Button1 に留まらないということになります。 -
コリン星人 さんからの引用 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 からどこかへ移動してしまうような要因があるのではないかと思います。
# こういう時は最小限のコードで試して原因を探るか、デバッグをうまく活用した方が早いです。
# ただしフォーカスがらみはデバッグでインライン実行すると結果が変わるので注意が必要です。
-
コリン星人 さんからの引用 Me.Close()を削除してみると仰る通りにフォーカスがButton1に移動することができました。でもMe.Close()が入るとだめです。
やはり Close メソッドのせいですか...
コリン星人 さんからの引用 話はそれますが、ValidatingイベントのeとFrom_Closingイベントのeは同じものなんですね。初めて知りました。
せっかく .NET Framework 2.0 を使っているのですから Form.Closing イベントではなく Form.FormClosing イベントを使うようにしましょう。 ちなみに Form.FormClosing イベントの引数 e は CancelEventArgs ではないので別のものになります。
すべての返信
-
コリン星人 さんからの引用 CausesValidation = False って効かないのでしょか?
Button1 に対しては効きますよ。
あるコントロール (A とします) にフォーカスが移動した時に、A の CausesValidation プロパティが評価され、False であれば検証イベントは発生しませんが、その後別のコントロールにフォーカスが移った場合は A の CausesValidation プロパティの値は関係ありません。
今回の例ですと Button1 で Form.Close しているのが原因なのではないでしょうか。
Form が Close されるということはフォーカスは Button1 に留まらないということになります。 -
じゃんぬねっと様
レスありがとうございます。
CausesValidationプロパティって検証が必要な他のコントロールに対してValidatingイベントを発生させるんじゃなかったですか?
つまり、もしButton1.CausesValidation=Trueであったならば、フォーカスがButton1に移動した時点で他の(この場合はTextBox1の)Validatingイベントを発生させるんじゃなかったですか?
なので今回の場合はButton1.CausesValidation=FalseですからTextBox1のValidatingイベントは発生しないで無事にフォームを閉じることができると思っていたのですが。
じゃんぬねっと さんからの引用 今回の例ですと Button1 で Form.Close しているのが原因なのではないでしょうか。
Form が Close されるということはフォーカスは Button1 に留まらないということになります。これ、ちょっと理解ができなかったです。
Button1がクリックされた後でForm.CloseなのでButton1にはフォーカスが移動する(CausesValidationプロパティが評価される)ように思うのですけど。
フォームを必ず閉じることができるボタン(よくある[終了]ボタンなど)は作成できないってことですか?
-
コリン星人 さんからの引用 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 からどこかへ移動してしまうような要因があるのではないかと思います。
# こういう時は最小限のコードで試して原因を探るか、デバッグをうまく活用した方が早いです。
# ただしフォーカスがらみはデバッグでインライン実行すると結果が変わるので注意が必要です。
-
別のPC(といっても環境はほとんど同じですが)で最小コードで試してみましたがやはり同じ現象になります。
Me.Close()を削除してみると仰る通りにフォーカスがButton1に移動することができました。
でもMe.Close()が入るとだめです。
じゃんぬねっとさんの環境では無事に終了できたということですので私の環境に何かだめな点があるのかな。
とりあえず思いつくのはVirtualPC上で開発しているってことですが、残念ながら今私のとことでは素の開発環境がありません。
そこで実行環境だけでもと思い、ビルドしてそのEXEを素のWindowsXPSP3の環境で実行しましたがやはり同じ現象になります。
ということは作成されたアセンブリ自体が既に駄目ってことですね。
今のところ、ちょっと手の打ちようがありません。
-
いろいろググっていると以下のページを見つけました。
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は同じものなんですね。初めて知りました。
-
コリン星人 さんからの引用 Me.Close()を削除してみると仰る通りにフォーカスがButton1に移動することができました。でもMe.Close()が入るとだめです。
やはり Close メソッドのせいですか...
コリン星人 さんからの引用 話はそれますが、ValidatingイベントのeとFrom_Closingイベントのeは同じものなんですね。初めて知りました。
せっかく .NET Framework 2.0 を使っているのですから Form.Closing イベントではなく Form.FormClosing イベントを使うようにしましょう。 ちなみに Form.FormClosing イベントの引数 e は CancelEventArgs ではないので別のものになります。
-
じゃんぬねっと さんからの引用 せっかく .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