【入門編】DataGridViewのセル単位での高度な入力制御:EditingControlShowingイベントをフックして数値専用セルでカンマ自動編集を実現する – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

こんにちは!WindowsフォームアプリケーションのUI設計、そして何より「ユーザーにとって使いやすい入力画面」の構築に日々頭を悩ませていませんか?

Excelのマクロ記録からステップアップし、本格的な業務システムをVisual Basic(VB.NET)で構築し始めると、避けて通れないのが「DataGridViewの入力制御」の壁です。

「数値だけを入力させたいのに、アルファベットが入ってしまう」
「入力中はプレーンな数値にして、フォーカスが外れたり編集中には『3桁ごとのカンマ区切り』を自動で行いたい」

標準のコントロールや簡易的な設定だけでは、この「かゆいところに手が届く」挙動を実現するのは少しコツがいります。今回は、VB.NETのWindows Forms開発において最も強力な武器の一つである`EditingControlShowing`イベントをフックし、セル単位で自由自在に入力コントロールを支配する極意を伝授します。

ここをクリアすれば、あなたの作る業務アプリのUI品質はプロのエンジニア水準に一気に跳ね上がりますよ。一緒にマスターしていきましょう!

—

なぜ標準のDataGridViewだけでは限界があるのか?

DataGridViewは非常に強力なグリッドコントロールですが、テキストボックスセル(`DataGridViewTextBoxColumn`)のデフォルトの振る舞いは、あくまで「ただの文字列入力」です。

「数値を入力させたい」と思ったとき、単に型を数値にするだけでは、ユーザーが文字を入力した瞬間にエラーダイアログがポップアップしたり、入力中にリアルタイムでカンマ(`,`)を入れるようなリッチなUX(ユーザー体験)を実現できません。

そこで登場するのが、「セルが編集状態に入った瞬間(EditingControlShowing)に、裏で動いている実際の入力コントロールを一時的に乗っ取る」というテクニックです。

—

秘伝のアーキテクチャ:EditingControlShowingイベントの正体

ユーザーがDataGridViewのセルをダブルクリックしたり、キーボードで入力を始めたりした瞬間、DataGridViewはセルの上に一時的に実際の入力用コントロール(通常は `TextBox`)を生成して配置します。これが「編集コントロール(EditingControl)」です。

普段、私たちはこの裏側のコントロールを直接触ることはできませんが、`EditingControlShowing`イベントを使うと、「今まさにセルの上に生成されたTextBox」を直接捕獲し、独自のイベント(キー入力制限など)をフックさせることができます。

全体像のイメージ

1. ユーザーがセル編集を開始する。
2. `EditingControlShowing`イベントが発生する。
3. 渡されたコントロールが`TextBox`であるか型チェックし、キャストする。
4. そのTextBoxに対して、数値以外の入力を弾くイベントや、カンマを整形するイベントを動的に紐付ける。
5. 編集が完了したらイベントを解除し、綺麗にクリーンアップする。

—

実践!カンマ自動編集&数値限定セルの実装コード

それでは、実際のVB.NETコードを見ていきましょう。
今回は、フォームに配置した`DataGridView1`の特定の列(例えば2列目、インデックスが `1` の列)を対象として、この高度な入力制御を実装します。

Public Class Form1

‘ 編集中のコントロールを一時的に保持するための変数
Private targetTextBox As TextBox = Nothing

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
‘ テスト用の初期データを設定(2列目を数値入力列とする)
DataGridView1.Columns.Add(“ColName”, “商品名”)

Dim numCol As New DataGridViewTextBoxColumn()
numCol.Name = “ColPrice”
numCol.HeaderText = “単価(自動カンマ)”
DataGridView1.Columns.Add(numCol)

‘ ダミー行の追加
DataGridView1.Rows.Add(“ノートPC”, “128000”)
DataGridView1.Rows.Add(“マウス”, “3500”)
End Sub

‘ 1. セルが編集状態に入った瞬間に呼ばれるイベント
Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing

‘ 現在編集中の列が、対象の数値列(ここではインデックス 1:単価列)か判定
If DataGridView1.CurrentCell.ColumnIndex = 1 Then

‘ 編集コントロールがTextBoxであるか確認してキャスト
targetTextBox = TryCast(e.Control, TextBox)

If targetTextBox IsNot Nothing Then
‘ 既存のイベント重複登録を防ぐため、一度確実に解除してから紐付ける
RemoveHandler targetTextBox.KeyPress, AddressOf NumberOnly_KeyPress
RemoveHandler targetTextBox.Leave, AddressOf FormatComma_Leave
RemoveHandler targetTextBox.Enter, AddressOf RemoveComma_Enter

‘ イベントを動的にアタッチ(結びつけ)する
AddHandler targetTextBox.KeyPress, AddressOf NumberOnly_KeyPress
AddHandler targetTextBox.Leave, AddressOf FormatComma_Leave
AddHandler targetTextBox.Enter, AddressOf RemoveComma_Enter
End If
Else
targetTextBox = Nothing
End If
End Sub

‘ 2. キー入力制限:数字とバックスペース以外を受け付けない
Private Sub NumberOnly_KeyPress(sender As Object, e As KeyPressEventArgs)
‘ バックスペース(ControlChars.Back)は許可する
If Char.IsControl(e.KeyChar) Then
Return
End If

‘ 数字以外が入力された場合は入力を無効化(キャンセル)する
If Not Char.IsDigit(e.KeyChar) Then
e.Handled = True
End If
End Sub

‘ 3. セルからフォーカスが外れた時(Leave):3桁カンマ区切りにフォーマットする
Private Sub FormatComma_Leave(sender As Object, e As EventArgs)
Dim txt As TextBox = TryCast(sender, TextBox)
If txt IsNot Nothing AndAlso Not String.IsNullOrWhiteSpace(txt.Text) Then
Dim rawValue As Long
‘ 文字列を数値に変換できたら、カンマ区切りの文字列に変換し直す
If Long.TryParse(txt.Text.Replace(“,”, “”), rawValue) Then
txt.Text = rawValue.ToString(“N0”) ‘ “N0” は3桁区切りフォーマット
End If
End If
End Sub

‘ 4. セルにフォーカスが入った時(Enter):編集しやすいようにカンマを除去する
Private Sub RemoveComma_Enter(sender As Object, e As EventArgs)
Dim txt As TextBox = TryCast(sender, TextBox)
If txt IsNot Nothing Then
‘ 編集時はカンマが邪魔なので取り除く
txt.Text = txt.Text.Replace(“,”, “”)
‘ テキスト全体を選択状態にしておくとユーザーが入力しやすい
txt.SelectAll()
End If
End Sub

‘ 5. 編集モードが終了したときのクリーンアップ(メモリリーク防止の極意)
Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
If targetTextBox IsNot Nothing Then
‘ イベントの紐付けを必ず解除する(これを行わないとメモリリークや多重イベント発火のバグの温床になります)
RemoveHandler targetTextBox.KeyPress, AddressOf NumberOnly_KeyPress
RemoveHandler targetTextBox.Leave, AddressOf FormatComma_Leave
RemoveHandler targetTextBox.Enter, AddressOf RemoveComma_Enter
targetTextBox = Nothing
End If
End Sub

End Class

—

コードの深掘り解説:ここがプロの技

初心者がハマりやすいポイントや、アーキテクチャ上の重要な設計思想をいくつか解説します。

① なぜイベントの「解除(RemoveHandler)」が必要なのか?

DataGridViewの内部アーキテクチャでは、編集用TextBoxコントロールは使い回し(リサイクル)されます。
もしイベントの登録(`AddHandler`)だけを行って解除(`RemoveHandler`)を忘れると、セルを移動するたびに同じイベントが何重にも重複して登録されてしまい、「1回キーを押しただけで文字が何重にも入力される」「予期せぬ多重イベントによるパフォーマンス低下」という深刻なバグを引き起こします。
`CellEndEdit`などで確実に後始末をすること、これがプロとアマを分ける分水嶺です。

② `Enter` と `Leave` による「編集時と非表示時のモード切り替え」

  • 編集中(Enter時): ユーザーが計算や修正をしやすいよう、カンマを取り除いた「純粋な数字のみ(例: `128000`)」の状態にします。さらに `txt.SelectAll()` で既存の数値を全選択状態にすることで、上書き入力をスムーズにします。
  • 閲覧・確定時(Leave時): 視認性を高めるため、`ToString(“N0”)` を使って「3桁カンマ区切り(例: `128,000`)」の美しいフォーマットに変換します。

—

まとめ:ここをクリアすれば、VB.NETの基本はバッチリ!

今回は、DataGridViewのセル入力制御という、実務で100%直面する壁を`EditingControlShowing`イベントのフックによって華麗に解決する方法を解説しました。

  • コントロールのライフサイクル(生成・使い回し・破棄)を意識する
  • 動的なイベントの紐付け(`AddHandler`)と確実な後始末(`RemoveHandler`)
  • ユーザー視点に立ったUXの設計(編集中はプレーン、非難時はフォーマット)

これらの概念は、DataGridViewだけでなく、Windows Formsアプリケーション全般のカスタムコントロール開発や高度なUI設計において、強力な基礎体力となります。

「マクロの記録」の世界から一歩抜け出し、コントロールの裏側の挙動までを自分の手足のようにコントロールできるようになったあなたなら、どんな複雑な業務システム要件も怖くありません。ぜひ実際のプロジェクトにこの知見を取り入れてみてくださいね。あなたの開発ライフを、心から応援しています!

タイトルとURLをコピーしました