トップ回答者
DataGridViewでRowValidatingが走らない場合がある

質問
-
DataGridViewの動作についでどなたか教えてください。
【現象】
DataGridViewのカラムに文字列を「入力中の状態」で、BindingNavigatorのボタンを
操作すると、1回目はRowValidatingが正しく呼ばれるのですが、その中でe.Cancel=True
としてキャンセルし、エラーメッセージを表示した後、画面操作を何もせずにもう一度
BindingNavigatorのボタンを操作するとRowValidatingのイベントが発生しません。キャンセル直後のDataGridViewはキー操作を受け付けない状態になっているようです。
ただし、Tabキーだけは受け付けて、それ以降は正常な状態に戻ります。RowValidatingイベント
も正しく発生します。
おそらく、DataGridView内の編集用のコントロールが関係しているようなのですが、
詳細は不明です。そこで、仕方なくRowValidatingのキャンセル時に「SendKeys.Send("{TAB}")」を
実行して回避していますが、任意のカラムにフォーカスを移す場合など何度も
SendKeysを実行するなど見っとも無いプログラムになってしまいます。原因やもっと良い対処方法をご存知の方がいらっしゃいましたら、宜しくお願い
いたします。
回答
-
trapemiyaさん、ありがとうございます。
再現できて良かったです。が、原因はやはり不明ですか。
DataGridViewのバグですかね?ご提案いただいた回避策ですが、BindingNavigatorの
ボタンのデフォルト機能を殺して置き換えるしかない
ということですね。
この問題は「新規追加」ボタンだけでなく他のボタンでも
発生しますのですべてのボタンの動作を置き換えることに
なってしまいます。
最初に私が回避策として記述した「SendKeys.Send("{TAB}")」
を使うほうが実装が楽そうですので、当面はこのまま我慢
することにします。
どうも有難う御座いました。
すべての返信
-
trapemiyaさん、お世話になります。
少し追試をしてみました。
RowValidatingが走らないというよりは、別の原因で先に
エラーが発生していただけかも知れません。今回の環境は、
AccessのMDBに接続して単純なフォームをウィザードで作成し、
RowValidatingをハンドルするだけです。
DataGridViewに接続しているテーブルは、NOT NULLの主キー
ともう数個のテキスト項目があるだけです。
実はこの主キーの入力有無をチェックしたいがためにRowValidating
を使っていますが、問題になっている現象のためにNOT NULL違反で
落ちてしまいます。おそらく先に落ちてしまうために
RowValidatingが走らないと感じたのかも知れません。本来はRowValidatingでキャンセルしているのに、データを(内部的に?)保存
してしまうからNOT NULL違反が発生するのだと思います。いろいろやってみた結果、問題の操作をおこなうとDataGridViewの現在行
(マーカーのある行といったほうが良いかもしれませんが)とBindingNavigator
が表示しているRow番号が不一致になってしまうようです。
例えば、BindingNavigatorの新規追加ボタンを使用すると、DataGridViewは
元のレコードを指したままなのに、新規行ができていたりします。
BindingNavigatorのRow番号は新規行を指しています。どうなっているのでしょうか?
-
fossilman さんからの引用
例えば、BindingNavigatorの新規追加ボタンを使用すると、DataGridViewは
元のレコードを指したままなのに、新規行ができていたりします。
BindingNavigatorのRow番号は新規行を指しています。
どのように確かめられましたか? 新規追加ボタンを押すと、DataGridViewのレコードセレクタは、ちゃんと新規行を指しているはずです。状況から判断して、新規追加ボタンを押した後に、そのまま新規追加ボタンを押すと、レコードにnullの入力が許されていないので、そこでこけているのではないでしょうか?
であれば、RowValidatingで、DataGridView1(nullじゃだめなカラムのインデックス, e.RowIndex).ValueがDBnull.Value であるかどうかを判断すれば良いと思います。 -
通常はtrapemiyaさんの仰るとおりです。
RowValidatingの中でカラムがNULLかどうか判断して、
エラーメッセージを表示した後、e.Cancel=Trueとしています。
通常の操作では、それで問題なく動作しています。問題を単純化するためにNOT NULLのカラムに値が入った状態で
RowValidatingでキャンセルするように変更して同じ操作をした場合
に報告した現象となりました。
(BindingNavigatorとDataGridViewの不一致)再現のキーワードは、
1.DataGridViewで入力状態(エディットコントロール
が表示されている状態)で新規追加ボタンを押す。
2.RowValidatingでエラーメッセージを表示してキャンセルする。
3.他は何の操作もしないで、もう一度新規追加ボタンを押す。
です。
「DataGridViewの入力状態での操作」が大前提で、それ以外の状態では
問題は発生しません。再現しないでしょうか?
-
再現しました。確かに、RowValidatingが走りませんね。
原因はわからないのですが、回避策としては、以下のようにすれば逃げられるようです。1.BindingNavigatorのAddNewItemを(なし)にする。
2.BindingNavigatorAddNewItemのClickイベントに、次のコードを記述する。Private Sub BindingNavigatorAddNewItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BindingNavigatorAddNewItem.Click
If Me.Table1BindingSource IsNot Nothing Then
Try
Me.Table1BindingSource.AddNew()
Me.Table1BindingNavigator.EndInit()
Catch ex As NoNullAllowedException
MsgBox(ex.Message)
End Try
End If
End Sub
-
trapemiyaさん、ありがとうございます。
再現できて良かったです。が、原因はやはり不明ですか。
DataGridViewのバグですかね?ご提案いただいた回避策ですが、BindingNavigatorの
ボタンのデフォルト機能を殺して置き換えるしかない
ということですね。
この問題は「新規追加」ボタンだけでなく他のボタンでも
発生しますのですべてのボタンの動作を置き換えることに
なってしまいます。
最初に私が回避策として記述した「SendKeys.Send("{TAB}")」
を使うほうが実装が楽そうですので、当面はこのまま我慢
することにします。
どうも有難う御座いました。