DataGridView#CellEnterイベントに注意

名前通り、WindowsFormsにおけるDataGridViewクラスでセルがフォーカスを取得した時に発生するイベントだが、直感的では無いイベントの発火条件があるので注意が必要だ。

このイベントが発生する事象としては

  • マウスで該当のセルをクリックする
  • キーボードで該当のセルに移動する

ここまでは当たり前だが、

  • DataGridView#CurrentCellプロパティを変更する

ことによってもCellEnterイベントが発生する。当たり前だろうと思う方もいるだろうが、私は最初これを知らなかった。
なお、更に注意が必要なのはMSDN及びヘルプにも記述されているが、

コントロールに入力フォーカスがなく、クリックされたセルが以前に現在のセルではなかった場合、このイベントが 1 回のクリックに対して 2 回発生することがあります。

という仕様だ。CellEnterが二度発生する、という仕様はこのイベントに関してのドキュメントを見ていないとバグに見えるだろう。また、今回に限ったことでは無いが、デバッグセッションではフォーカスの関係でこのヘルプの通りに二度のCellEnterイベントが発生しないことも罠になるので注意する。(一時これではまった。)

このイベントには更に注意すべき点がある。
CellEnterイベントでは以下のようにフォーカスを持つセルのカラム番号を取得する処理をよく書くと思うが、

void GridCellEnterHandler(object sender, DataGridViewCellEventArgs e)
{
    Debug.WriteLine("ColumnIndex =  " + e.ColumnIndex);
}

この時、上述したようにCellEntereイベントが2度発生するケースで、1度目のCellEnter発火時に取得できるDataGridViewCellEventArgs#ColumnIndexは、カレントセルのカラムを指しているとは限らないので注意が必要である。(1度目のColumnIndexは恐らく、DataGridViewがフォーカスを消失する前に設定されていたCurrentCellのカラム番号がセットされていることだろう)

このようにDataGridViewクラスのイベントは罠だらけなので、自らの経験や直感に頼らずMSDN又はヘルプを引きながら書く必要がある。