none
RowChangedイベントハンドラでMsgBoxを表示するとコードが最後まで実行されない RRS feed

  • 質問

  •  WindowsFormにDataTableを編集するDataGridViewと、キャンセルボタンを貼り付けました。

     DataGridViewに入力し、鉛筆マークが出ている状態で、キャンセルボタンを押すと、フォーカスが外れるときに一旦編集中のレコードが確定されるためにRowChangedが1回発生し、その次にRejectChangesが実行されます。

     しかしRowChangedイベントハンドラでMsgBoxを表示するとその後のコードが実行されず、データはRejectChangesされないまま残ってしまいます。

     私はMsgBoxが表示された後にRejectChangesが実行されることを期待したのですが、なぜそうならないのでしょうか。

     vb2005 sp1でテストしています。

    コード ブロック

    Public Class Form1
      Dim WithEvents table As DataTable

      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        table = DataSet1.TestTable
      End Sub

      Private Sub table_RowChanged(ByVal sender As Object, ByVal e As System.Data.DataRowChangeEventArgs) Handles table.RowChanged
        Debug.Print(e.Row.RowState.ToString)
        'MsgBox(e.Row.RowState.ToString)
      End Sub

      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        table.RejectChanges()
        MsgBox("RejectChanges")
      End Sub

    End Class

     

     

    2007年10月10日 7:39

回答

  • モーダルのためウィンドウメッセージが途切れて消失してしまうためかと思います。

     

    特に連鎖するような流れの中でMsgBoxのようにそのようなことが想定される処理の呼び出しは、副作用からわかるように御法度と言えるでしょう。

    メジャーなパターンはMouse系とフォーカス系のイベントの連鎖でしょうか。

    #デバッグでブレークすると当たり前のように発生しますし。

    イベントの性質の観点でおこなってもよい命令かどうかを判断する必要があるでしょう。

    しかし、結果としてそれをやるべきタイミング(イベント)ではない(設計の誤り)ということがほとんどだと思います。

    2007年10月11日 14:52

すべての返信

  • モーダルのためウィンドウメッセージが途切れて消失してしまうためかと思います。

     

    特に連鎖するような流れの中でMsgBoxのようにそのようなことが想定される処理の呼び出しは、副作用からわかるように御法度と言えるでしょう。

    メジャーなパターンはMouse系とフォーカス系のイベントの連鎖でしょうか。

    #デバッグでブレークすると当たり前のように発生しますし。

    イベントの性質の観点でおこなってもよい命令かどうかを判断する必要があるでしょう。

    しかし、結果としてそれをやるべきタイミング(イベント)ではない(設計の誤り)ということがほとんどだと思います。

    2007年10月11日 14:52
  • まどかさんありがとうございます。

    モーダルダイアログによるメッセージの消失が原因らしいということで、追試しました。

    MsgBoxの代わりに、フォームをShowするのとShowDialogしたのですが、ShowDialogのみ問題が発生しました。

    また、RowChangedではなくてRowChaingingでテストしてみたところ、IndexOutOfRangeが発生しました。

    この例外はMsgBoxの代わりにApplication.DoEvents()をいれても発生しました。

    想定外のタイミングでウィンドウメッセージが流れることで正常な連鎖が行われないのは間違いなさそうです。

    今回はデバッグ目的でMsgBoxを入れたので差し迫って困ることはないのですが、

    RowChaingingでユーザに何らかの確認をさせるというロジックは問題ありと判断しました。

    2007年10月12日 1:20
  • この問題いつの間にか修正されていました。
    前回Netframework 2.0 SP1で確認したので、SP2で修正されたのだと思います。
    ライブラリのバグだったんですね。

    訂正
    間違っていました。今でも発生します。SP2
    但しRowChaingingでIndexOutOfRangeは発生しなくなったようです。


    http://www.mahoroba.ne.jp/~mw_ken
    • 回答としてマーク 三輪の牛 2009年9月3日 9:19
    • 回答としてマークされていない 三輪の牛 2009年9月4日 1:16
    2009年9月3日 9:19