ソースあんならすぐ出せ

2020/03/10

投げっぱなし

つまり大阪人がせっかちだから生まれたと。>エスカレーター片側空けるの ごきげんよう。

[Visual Studio] DataGridViewの行選択時のイベント


重大なことだと思うのにどこにも情報見つからなかったのでメモ。

DataGridViewで行が選択されたら何か処理をするようなときにはRowEnterイベントを監視します。
ところが、挙動を観察しているとRowEnterが発生するタイミングがよくわからないことがあります。
一度の選択で2回発生したり、選択を変更していないのに発生したり。
最初はビューにフォーカスが当たっていないと2回なのかと思いましたが、1回のこともあります。

きちんと確認したところ以下の発生順となっていました。

行選択時のイベント発生順

#ビューがActiveか行選択済みか選択した行発生イベント
a××
  1. Enter
  2. RowEnter
b×別の行
  1. Enter
  2. RowEnter(e.RowIndexは選択済みの行)
  3. RowEnter(e.RowIndexは新たに選択した行)
c×同じ行
  1. Enter
  2. RowEnter
d×
  1. RowEnter
e別の行
  1. RowEnter
f同じ行なし

RowEnterイベントの発生タイミング

上のマトリックスから、RowEnterの発生条件をまとめると以下の通り。

  1. ビューにフォーカスが移ったとき、すでに行選択済みならばその行に対して発生する
  2. ビューがActiveの状態で、新たにもしくは選択済みの行とは別の行が選択されたときに新しい選択行に対して発生する



正しく処理する方法

では、どんな操作で行が選択されても正しい回数だけ処理を行うにはどうすればよいか。
上表のa、b、d、eは1回だけ実行し(bは2回目のRowEnterのみ)、cとfは選択済みの行の再選択ですから何も処理しないようにしたいです。

一案ですが、Enterイベントの中で行が選択済みかを判断して、選択済みならばフラグを立てます。
その直後に発生するRowEnterイベントの中でフラグを見て、立っていたら以降の処理をスキップしてフラグを下ろします。
これでフォーカスインに伴い発生するイベントは処理せず、行選択が変更されたときのみ処理を行うことができます。

さらなる問題

実装していると、起動して最初のうちだけイベント処理がうまくいかないことがあります。
フォーム内の最初の要素がDataGridViewだった場合です。
この場合、フォームが開く前にEnterイベントが発生して、見た目上は先頭の行が選択されるのですがRowEnterイベントは発生しないというおかしな状態になります。
この矛盾した状態を解消するには、フォーム表示時にビューの選択をクリアしておきます。

さらにさらに、TabPageの最初にDataGridViewがあってそのタブを開いたときも同じことが(ry

ソーシャル/購読

このブログを検索

コメント

ブログ アーカイブ