DataGridView:セル編集時の入力制限(サンプルあり)

📋 目次(クリックで展開)

DataGridView でユーザーに直接データを編集させる際、価格の列には数値以外を入力させないようにする、コードの列は5文字以内に制限するようなシナリオがあります。

DataGridView の各列には KeyPress イベントや MaxLength プロパティが用意されていないため、個別の制御には手順が必要です。

今回は、セルが編集状態になったタイミングを捉える EditingControlShowing イベントを利用し、特定の列に対して数値のみの許可や最大文字数の制限を適用する実装方法について解説します。

編集用コントロールを制御する仕組み

DataGridView のセルが編集状態になると、セルの内部には一時的に TextBox コントロールが配置されます。

この編集用のテキストボックスが表示される瞬間に発生するのが EditingControlShowing イベントです。このイベントハンドラ内で内部のテキストボックスを捕捉し、通常の TextBox と同様に KeyPress イベントの追加や MaxLength プロパティの設定を行います。

ここでのポイントは、DataGridView 内の編集用テキストボックスは、セルを切り替えるたびに新しく生成されているわけではなく、すべてのセルで共通の1つのインスタンスが内部で使い回されるという点です。そのため、特定の列で設定したイベントやプロパティが他の列の編集時にも残った状態になります。

列ごとに異なる制限をかけるには、「編集が始まる瞬間に一度イベントを解除して初期状態に戻し、必要な列のときだけイベントを再登録する」という着脱の制御を行います。

実装コード

以下は、DataTable をデータソースとしてバインドし、「Code」列には最大5文字までの入力を、「Price」列には数値のみかつ最大7文字までの入力を制限するコード例です。

Form1.cs

Form1.cs
using System.Data;
namespace DataGridView_Input_Restriction
{
public partial class Form1 : Form
{
private DataTable _dataTable = new DataTable();
public Form1()
{
InitializeComponent();
InitializeSomeDataGridView();
}
private void InitializeSomeDataGridView()
{
// テスト用データの準備
_dataTable.Columns.Add("Code", typeof(string));
_dataTable.Columns.Add("Name", typeof(string));
_dataTable.Columns.Add("Price", typeof(int));
_dataTable.Rows.Add("P001", "ノートパソコン", 120000);
_dataTable.Rows.Add("P002", "USBメモリ", 2500);
dataGridView1.DataSource = _dataTable;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
// 編集開始時のイベントを購読
dataGridView1.EditingControlShowing += DataGridView1_EditingControlShowing;
}
/// <summary>
/// セルが編集状態になったときに発生するイベント
/// </summary>
private void DataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
// 編集用コントロールが TextBox であるか確認
if (e.Control is TextBox textBox)
{
// 過去のセルで登録された数値制限イベントを一律で解除する
// これにより、どの列に移動しても一度「通常の文字入力ができる状態」に戻ります
textBox.KeyPress -= Cell_KeyPress;
// 現在編集中の列名を取得
string columnName = dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex].Name;
if (columnName == "Code")
{
// Code列:最大文字数を5文字に制限(イベントは追加しないため、英数字などが入力可能)
textBox.MaxLength = 5;
}
else if (columnName == "Price")
{
// Price列:最大文字数を7文字に制限し、数値のみ許可するイベントを再登録
textBox.MaxLength = 7;
textBox.KeyPress += Cell_KeyPress;
}
else
{
// その他の列(Name列など):文字数制限をデフォルト(制限なし)に戻す
textBox.MaxLength = 32767;
}
}
}
/// <summary>
/// テキストボックスへのキー入力を制御するイベント(数値のみ許可)
/// </summary>
private void Cell_KeyPress(object sender, KeyPressEventArgs e)
{
// 入力された文字が「数字」でも「コントロールキー(BackSpaceなど)」でもない場合は入力を無効化
if (!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar))
{
e.Handled = true;
}
}
}
}

ソースコード

サンプルアプリケーション

DataGridView_Input_Restriction.zip
※サンプルアプリケーションは、.NET 10 をターゲットに作成しています。

実行結果

「Code」列は最大 5 桁の英数字、「Price」列は最大 7 桁の数値のみが入力できます。

留意すべき注意点と実装の背景

DataGridView 内の編集用テキストボックスを扱う際、仕様上の特性に起因する動作を防ぐために把握しておくとよい点が2つあります。

イベントハンドラの重複登録と列ごとの切り替え

前述の通り、編集用テキストボックスのインスタンスは使い回される仕様です。そのため、イベントの追加処理のみを記述すると、セルを編集するたびに同じイベントハンドラが重複して登録されてしまいます。

イベントが重複して登録されると、キー入力時に同じメソッドが何度も呼び出され、動作の不安定化につながる場合があります。

また、今回は「数字以外の入力を無効化する」という処理を Price 列にのみ適用し、アルファベットを扱う Code 列や日本語を扱う Name 列では通常の入力を許可する必要があります。

これらを両立させるため、サンプルコードでは列の判定を行う前に textBox.KeyPress -= Cell_KeyPress; を実行しています。一度イベントを解除してテキストボックスを無制限の状態にリセットした上で、数値制限を行いたい Price 列の条件分岐内でのみ、改めてイベントを再登録する構成をとっています。

他のセルへ移動した際の MaxLength の初期化

特定のセルで textBox.MaxLength = 5; のように制限をかけた後、別のセルへ移動した際にもその設定が残る現象があります。これもテキストボックスのインスタンスが使い回される仕様によるもので、他の列の編集に移ったときにも制限が引き継がれます。

制限を行わない列に対しては、サンプルコードの else 句にあるように、textBox.MaxLength = 32767;(デフォルト値)を設定して文字数制限をリセットする処理を記述します。

まとめ

今回は、DataGridView のセル編集時に入力制限(数値のみ許可・最大文字数の制限)を行う方法について解説しました。

EditingControlShowing イベントを利用することで、ひとつのテキストボックスインスタンスを制御し、TextBox のプロパティやイベントを DataGridView 内の各セルに切り替えて適用できます。

  • e.Control を TextBox にキャストして操作する
  • テキストボックスが使い回されるため、列の判定前にイベントを一度解除する
  • 数値制限が必要な特定の列でのみ、イベントの再登録を行う
  • 他の列へ影響が出ないよう、制限の不要な列では MaxLength を初期値に戻す

これらの手順を整えることで、意図しない入力を防ぎ、操作性を考慮した一覧画面の構築が可能になります。入力チェック処理を実装する際の参考になりましたら幸いです。


💬 コメント