none
DataGridViewでRowValidatingが走らない場合がある RRS feed

  • 質問

  • DataGridViewの動作についでどなたか教えてください。
    【現象】
    DataGridViewのカラムに文字列を「入力中の状態」で、BindingNavigatorのボタンを
    操作すると、1回目はRowValidatingが正しく呼ばれるのですが、その中でe.Cancel=True
    としてキャンセルし、エラーメッセージを表示した後、画面操作を何もせずにもう一度
    BindingNavigatorのボタンを操作するとRowValidatingのイベントが発生しません。

    キャンセル直後のDataGridViewはキー操作を受け付けない状態になっているようです。
    ただし、Tabキーだけは受け付けて、それ以降は正常な状態に戻ります。RowValidatingイベント
    も正しく発生します。
    おそらく、DataGridView内の編集用のコントロールが関係しているようなのですが、
    詳細は不明です。

    そこで、仕方なくRowValidatingのキャンセル時に「SendKeys.Send("{TAB}")」を
    実行して回避していますが、任意のカラムにフォーカスを移す場合など何度も
    SendKeysを実行するなど見っとも無いプログラムになってしまいます。

    原因やもっと良い対処方法をご存知の方がいらっしゃいましたら、宜しくお願い
    いたします。

    2006年11月9日 1:15

回答

  • trapemiyaさん、ありがとうございます。

    再現できて良かったです。が、原因はやはり不明ですか。
    DataGridViewのバグですかね?

    ご提案いただいた回避策ですが、BindingNavigatorの
    ボタンのデフォルト機能を殺して置き換えるしかない
    ということですね。
    この問題は「新規追加」ボタンだけでなく他のボタンでも
    発生しますのですべてのボタンの動作を置き換えることに
    なってしまいます。
    最初に私が回避策として記述した「SendKeys.Send("{TAB}")」
    を使うほうが実装が楽そうですので、当面はこのまま我慢
    することにします。
    どうも有難う御座いました。

    2006年11月13日 0:28

すべての返信

  • ちょっとこちらで試した限りでは再現しなかったのですが、何か特別なことをされているのでしょうか?
    2006年11月9日 7:47
    モデレータ
  • trapemiyaさん、お世話になります。

    少し追試をしてみました。
    RowValidatingが走らないというよりは、別の原因で先に
    エラーが発生していただけかも知れません。

    今回の環境は、
    AccessのMDBに接続して単純なフォームをウィザードで作成し、
    RowValidatingをハンドルするだけです。
    DataGridViewに接続しているテーブルは、NOT NULLの主キー
    ともう数個のテキスト項目があるだけです。
    実はこの主キーの入力有無をチェックしたいがためにRowValidating
    を使っていますが、問題になっている現象のためにNOT NULL違反で
    落ちてしまいます。おそらく先に落ちてしまうために
    RowValidatingが走らないと感じたのかも知れません。

    本来はRowValidatingでキャンセルしているのに、データを(内部的に?)保存
    してしまうからNOT NULL違反が発生するのだと思います。

    いろいろやってみた結果、問題の操作をおこなうとDataGridViewの現在行
    (マーカーのある行といったほうが良いかもしれませんが)とBindingNavigator
    が表示しているRow番号が不一致になってしまうようです。
    例えば、BindingNavigatorの新規追加ボタンを使用すると、DataGridViewは
    元のレコードを指したままなのに、新規行ができていたりします。
    BindingNavigatorのRow番号は新規行を指しています。

    どうなっているのでしょうか?

    2006年11月10日 8:57
  •  fossilman さんからの引用

    例えば、BindingNavigatorの新規追加ボタンを使用すると、DataGridViewは
    元のレコードを指したままなのに、新規行ができていたりします。
    BindingNavigatorのRow番号は新規行を指しています。

    どのように確かめられましたか? 新規追加ボタンを押すと、DataGridViewのレコードセレクタは、ちゃんと新規行を指しているはずです。

    状況から判断して、新規追加ボタンを押した後に、そのまま新規追加ボタンを押すと、レコードにnullの入力が許されていないので、そこでこけているのではないでしょうか?
    であれば、RowValidatingで、DataGridView1(nullじゃだめなカラムのインデックス, e.RowIndex).ValueがDBnull.Value であるかどうかを判断すれば良いと思います。

    2006年11月10日 16:40
    モデレータ
  • 通常はtrapemiyaさんの仰るとおりです。

    RowValidatingの中でカラムがNULLかどうか判断して、
    エラーメッセージを表示した後、e.Cancel=Trueとしています。
    通常の操作では、それで問題なく動作しています。

    問題を単純化するためにNOT NULLのカラムに値が入った状態で
    RowValidatingでキャンセルするように変更して同じ操作をした場合
    に報告した現象となりました。
    (BindingNavigatorとDataGridViewの不一致)

    再現のキーワードは、
    1.DataGridViewで入力状態(エディットコントロール
    が表示されている状態)で新規追加ボタンを押す。
    2.RowValidatingでエラーメッセージを表示してキャンセルする。
    3.他は何の操作もしないで、もう一度新規追加ボタンを押す。
    です。
    「DataGridViewの入力状態での操作」が大前提で、それ以外の状態では
    問題は発生しません。

    再現しないでしょうか?

    2006年11月11日 0:05
  • 再現しました。確かに、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

    2006年11月11日 15:34
    モデレータ
  • trapemiyaさん、ありがとうございます。

    再現できて良かったです。が、原因はやはり不明ですか。
    DataGridViewのバグですかね?

    ご提案いただいた回避策ですが、BindingNavigatorの
    ボタンのデフォルト機能を殺して置き換えるしかない
    ということですね。
    この問題は「新規追加」ボタンだけでなく他のボタンでも
    発生しますのですべてのボタンの動作を置き換えることに
    なってしまいます。
    最初に私が回避策として記述した「SendKeys.Send("{TAB}")」
    を使うほうが実装が楽そうですので、当面はこのまま我慢
    することにします。
    どうも有難う御座いました。

    2006年11月13日 0:28