みなさんこんにちは!ヒロポンです!
私の周りでも「CellClickイベントが全く起きないんだけどわかります?」とか、「CellClickで取った値をTextBoxに渡す方法がわかんないです」とか。。。CellEnterに悩まされてるって嘆いてる人や、「CellEnterとCellLeaveの動きが残念、Leaveのタイミングがズレてる」って愚痴ってる人も見かけます。
要するにクリック・セル移動の挙動が想像と違うってやつ。3アクション分岐の実装パターン1枚を手元に置いとけば、本来30分で終わる話なんですよね。
今回はDataGridViewのクリック3アクション(左/右/ダブルクリック)を分ける実装パターンを、verify-dotnet9で分岐ロジック動作確認しつつ並列展示します。
💡 DataGridViewの編集モード切替の基本 (ReadOnly / EditMode / RowValidatingの使い分け)は別記事 WinForms DataGridViewの編集モード完全ガイドで解説しました。今回はクリック分岐の応用編で、編集モードと組み合わせる時の罠も触れます。
💡 MenuStrip / ContextMenuStrip / ToolStripの使い分けは別記事 WinFormsメニュー3兄弟— MenuStrip / ToolStrip / ContextMenuStripの使い分けで解説しました。今回はDataGridView上での右クリック分岐に絞ります。
忙しいあなたのために!最初にまとめ!!!
- 3アクション分岐: ①左クリック(CellClick / CellContentClick) / ②右クリック(CellMouseDown + MouseButtons.Right判定+ ContextMenuStrip連携) / ③ダブルクリック(CellDoubleClick)
- 全アクション共通のヘッダ判定 (
if (e.RowIndex == -1) return;)を入れ忘れるとNullReferenceException - 右クリックは
MouseDown+CurrentCell明示設定の二段実装がコツ - ダブルクリックは編集モード中(
EditOnEnter/EditOnKeystroke)では編集確定にしか効かないので、編集モード解除のロジックを別途実装 - Docker (verify-dotnet9)検証は分岐ロジックの言語仕様レベルのみ。DataGridView UI本体はWindows + Visual Studio実機環境で別途確認してください
以上!!!!!
補完関係— post 44 / post 57との位置付け
DataGridView関連記事は3本セットで読むと知識が広がるので、ついでに別タブ開いて後で呼んでおいてくださいませ!
| 記事 | 守備範囲 | 今回との関係 |
|---|---|---|
| post 44 DataGridView編集モード完全ガイド | 編集モード切替の基本はこちら (ReadOnly / EditMode / RowValidating) | 今回H2「ダブルクリック」で前提として参照 |
| post 57 WinFormsメニュー3兄弟 | ContextMenuStripの使い分けはこちら (MenuStrip / ToolStrip / ContextMenuStrip) | 今回H2「右クリック」で連携先として参照 |
| 今回(クリック3アクション分岐) | クリック分岐の実装パターン | post 44 / 57をくっつけて応用 |
3アクション比較表
3つのクリック種別をイベント/用途/実装難度/ハマりポイントの4軸で並べたのが下の表です。どうぞ!

💡 PNGは視覚的な俯瞰用。「CellClick CellDoubleClick」「DataGridView右クリックCurrentCell」等の具体文字列で検索した時のSEOマッチ用に、同じ対応関係を下の表でも書きます。
| クリック種別 | イベント名 | 主な用途 | 実装難度 | ハマりポイント |
|---|---|---|---|---|
| 左クリック(単発) | CellClick / CellContentClick | 行選択・詳細画面オープン | 低 | RowIndex==-1ヘッダ判定漏れ→ NullReferenceException |
| 右クリック | CellMouseDown + Button判定 | コンテキストメニュー表示・削除確認 | 中 | MouseDownとCellClickの競合→ CurrentCell明示設定が必要 |
| ダブルクリック | CellDoubleClick | 編集モード切替・詳細展開 | 中 | 編集モード中のDoubleClickは編集確定にしか効かない |
①左クリック— CellClick / CellContentClick
最も基本的なクリック分岐。
ヘッダ判定だけ気をつければシンプルです。

CellClickとCellContentClickの違い:
- CellClick:セル領域内のどこでも発火(空白部分含む)
- CellContentClick:セル内のコンテンツ(文字列・ボタン等)を直接クリックした時のみ発火
リンクセルやDataGridViewLinkColumnを使ってる場合はCellContentClickのほうが意図に近い動作になります。
②右クリック— CellMouseDown + ContextMenuStrip連携
業務SEが一番踏む罠の領域。
CellClickは左クリックでしか発火しないので、右クリックはCellMouseDownで拾います。

ポイント:
- 右クリックでは
dgv.CurrentCellが自動更新されないので、明示的にCurrentCell = ...を呼ぶ - これを忘れると「右クリックしたセル」と「現在選択中のセル」が別物になって、メニューの削除確定で別の行を削除する事故が起きる
ContextMenuStrip.Show(dgv, ...)の座標はDataGridViewのクライアント座標に変換する必要あり
これがマジで罠の正体。
③ダブルクリック— CellDoubleClick +編集モード
最後、ダブルクリックで編集画面を開く/編集モードに切り替える実装。

詳細は WinForms DataGridViewの編集モード完全ガイド(post 44)で書いたEditModeの3パターン(EditOnEnter / EditOnKeystroke / EditProgrammatically)が前提です。
これも別タブで開いて一緒に読んでおいて!
EditOnEnterのままだとダブルクリックを編集モード切替に使えないので、デフォルトをEditProgrammaticallyにしておくのが定石。
ハマりポイント—そうじゃないケースが3つあります
ここまで「3イベント使い分ければいい」みたいに書いてきましたが、そうじゃないケースが3つあります。
あなたのために特別に共有しておきます。
①ヘッダクリックでNullReferenceException
CellClickイベントハンドラを書いて、行データを取りに行く実装。ユーザーが列ヘッダをクリックした瞬間、dgv.Rows[e.RowIndex]でe.RowIndex == -1になり、Rows[-1]でNullReferenceExceptionが出てアプリが落ちる、というやつ。
私もある日、リリース後の業務系画面でユーザーがソート目的でヘッダをクリック →全画面落ちで「動かないんだけど」と内線がなんと飛んできて、背中に冷や汗。
速攻で修正したけど、、、ちょっと焦った
学び!!!全イベントハンドラの先頭にif (e.RowIndex == -1) return;を入れる。
IsNewRow判定も合わせて入れると新規行追加プレースホルダもスキップできて安全。
②右クリックでセル選択が動かない(CurrentCell競合)
CellMouseDownで右クリックを拾ってContextMenuStrip.Showする実装。メニューの「削除」をクリックすると別の行が削除される、という事象。
ユーザーは右クリックした行を削除したつもりが、実はその前に選択されていた行が消える。
経験ないですか??ありますよね。多分あるはず。
私もある月末バッチ画面で、ユーザーから「削除メニューが効かない」と報告を受けて、デバッガで追ったらCurrentCellが右クリック時に更新されてないことが原因と判明。
半日コードを追って気付いた事象で、終わってみれば1行の追加で済む話でした。
これもやらかしの原因。
学び!!! CellMouseDownで右クリックを判定したら、dgv.CurrentCell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex]を明示的に呼ぶ。
これで右クリックでもセル選択が動き、メニューの削除確定が正しい行に効く。
③ EditMode=EditOnEnterでDoubleClickが編集確定にしか効かない
DataGridViewのEditModeをデフォルトのEditOnEnterのままにして、ダブルクリックで別Formを開こうとした時の話。CellDoubleClickイベントが発火しない。
セルに進入した瞬間に編集モードに入っているため、ダブルクリックは編集セルの確定アクションとして消費される。
私もある日、後輩が組んだ画面で「ダブルクリック効きません」と相談を受けて、EditModeがEditOnEnterだったのに気付くまでなんと1時間かかった経験があります。
ダブルクリック動作よりも先に編集モードに入ってる、という構造を脳内モデルで持ってないと辿り着けない。
学び!!! DataGridViewのEditModeをデフォルトでEditProgrammaticallyにしておくのが定石。
編集モードに入るタイミングをdgv.BeginEdit(true)で明示的に制御する。
これでダブルクリックを編集モード切替トリガとして自由に使える。
まとめ
DataGridViewのクリック3アクション分岐は、業務SEが画面リリース直前の仕様追加で一番焦る領域。
ポイントを3つだけ!!!
- 全イベントハンドラ先頭に
if (e.RowIndex == -1) return;を入れる(ヘッダ判定) - 右クリックは
CellMouseDown+CurrentCell明示設定の二段実装 - ダブルクリックはEditModeをEditProgrammaticallyにして、編集モード制御を明示的に持つ
これで月末バッチ画面のリリース直前に「右クリック削除追加」を言われても、こんな感じで「ん??CurrentCell明示設定さえ忘れなければ30分で終わる」と即判断できるようになります!!!!
ぶっちゃけ、DataGridViewのクリック分岐はこんな感じで3イベントの優先順位を脳内で持っておくだけで、ユーザー要望に即対応できる業務SEになれます。
いい感じにこの雰囲気を知識として習得できると、次の現場でも資産として使えますよ!!
よくある質問
Q1. DataGridViewのヘッダクリックでNullReferenceExceptionが出るのはなぜですか?
A. CellClickイベントはヘッダクリック時も発火し、その時e.RowIndex == -1が返ります。
ヘッダ判定を入れずにdgv.Rows[e.RowIndex]にアクセスするとNullReferenceExceptionで落ちます。
冒頭でif (e.RowIndex == -1) return;を入れるのが鉄則です。詳細はハマりポイント①参照。
Q2. DataGridViewで右クリックしたセルが選択されません
A. CellMouseDownはMouseButtons.Rightでも発火しますが、CurrentCellの更新は左クリックのみです。
右クリック時にdgv.CurrentCell = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex]を明示的に呼ぶと選択も連動します。詳細はハマりポイント②参照。
Q3.編集モード中のDoubleClickが編集確定にしか効かないのは仕様ですか?
A.そうです。
EditModeがEditOnEnterやEditOnKeystrokeの場合、DoubleClickは編集セルの確定アクションとして消費されます。
編集モード解除のロジックをCellDoubleClickで別途実装するか、EditModeをEditProgrammaticallyにしてダブルクリックを編集モード切替トリガとして使う方法が定石です。
関連記事
- WinForms DataGridViewの編集モード完全ガイド— 編集モード切替の基本(ReadOnly / EditMode / RowValidating)はこちら。今回③ダブルクリックの前提
- WinFormsメニュー3兄弟— MenuStrip / ToolStrip / ContextMenuStrip— ContextMenuStripの使い分けはこちら。今回②右クリックの連携先
- C# DataGridViewのDataSourceを後から変更する全パターン— DataSource変更系の応用パターンはこちら
以上!


コメント