DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

DataGridViewのセルに入力された値が正しいか確かめる

注意:DataGridViewコントロールは、.NET Framework 2.0で新しく追加されました。

セルの内容を検証する

ユーザーがセルに入力した値が正しいかどうかを調べ、正しくなければ入力をキャンセルするには、CellValidatingイベントを使用します。CellValidatingイベントハンドラでセルの内容が妥当かを調べ、不正であればユーザーに注意をしたり、前の値に戻したり、正しい値が入力されるまでフォーカスが移動しないようにしたりすることができます。

CellValidatingイベントはそのセルが入力フォーカスを失う時に発生しますので、現在のセルが変わる時や、他のコントロールにフォーカスが移る時に発生します。

以下に示す例では、"Column1"列のセルが空である時、その行にエラーテキストを設定して、別のセルにフォーカスが移らないようにしています。

VB.NET
コードを隠すコードを選択
'CellValidatingイベントハンドラ 
Private Sub DataGridView1_CellValidating(ByVal sender As Object, _
    ByVal e As DataGridViewCellValidatingEventArgs) _
    Handles DataGridView1.CellValidating

    Dim dgv As DataGridView = DirectCast(sender, DataGridView)

    '新しい行のセルでなく、セルの内容が変更されている時だけ検証する 
    If e.RowIndex = dgv.NewRowIndex OrElse Not dgv.IsCurrentCellDirty Then
        Exit Sub
    End If

    If dgv.Columns(e.ColumnIndex).Name = "Column1" AndAlso _
            e.FormattedValue.ToString() = "" Then
        '行にエラーテキストを設定 
        dgv.Rows(e.RowIndex).ErrorText = "値が入力されていません。"
        '入力した値をキャンセルして元に戻すには、次のようにする 
        'dgv.CancelEdit()
        'キャンセルする 
        e.Cancel = True
    End If
End Sub

'CellValidatedイベントハンドラ 
Private Sub DataGridView1_CellValidated(ByVal sender As Object, _
    ByVal e As DataGridViewCellEventArgs) _
    Handles DataGridView1.CellValidated

    Dim dgv As DataGridView = DirectCast(sender, DataGridView)
    'エラーテキストを消す 
    dgv.Rows(e.RowIndex).ErrorText = Nothing
End Sub
C#
コードを隠すコードを選択
//CellValidatingイベントハンドラ
private void DataGridView1_CellValidating(object sender,
    DataGridViewCellValidatingEventArgs e)
{
    DataGridView dgv = (DataGridView)sender;

    //新しい行のセルでなく、セルの内容が変更されている時だけ検証する
    if (e.RowIndex == dgv.NewRowIndex || !dgv.IsCurrentCellDirty)
    {
        return;
    }

    if (dgv.Columns[e.ColumnIndex].Name == "Column1" &&
        e.FormattedValue.ToString() == "")
    {
        //行にエラーテキストを設定
        dgv.Rows[e.RowIndex].ErrorText = "値が入力されていません。";
        //入力した値をキャンセルして元に戻すには、次のようにする
        //dgv.CancelEdit();
        //キャンセルする
        e.Cancel = true;
    }
}

//CellValidatedイベントハンドラ
private void DataGridView1_CellValidated(object sender,
    DataGridViewCellEventArgs e)
{
    DataGridView dgv = (DataGridView)sender;
    //エラーテキストを消す
    dgv.Rows[e.RowIndex].ErrorText = null;
}

CellValidatingイベントハンドラには、DataGridViewCellValidatingEventArgsオブジェクトが渡されます。基本的にはこのFormattedValueプロパティを検査することにより、正しい値であるかを判断します。ただしこの値は、表示用の書式指定済みの値であり、セルの本当に値ではありません。

CancelプロパティをTrueにすることにより、セルに入力された値を確定しないようにします。この時、現在のセルが別のセルに移動できなくなりますし、基本的には他のコントローラの操作や、フォームの閉じるボタン(Xボタン)も無効になります。

行のErrorTextプロパティを使用して、その行のヘッダーセルにエラーアイコンを表示しています。エラーアイコンについては、こちらで説明しています。

補足:編集中のセルにはエラーアイコンが表示されないため、上記の例でセルのErrorTextプロパティにエラーテキストを設定しても、エラーアイコンが表示されません。編集中のセルにエラーアイコンを表示する方法は、「How do I show the error icon when the user is editing the cell?(リンク切れのため、Internet Archiveへのリンク)」で説明されています。

このエラーテキストは適当なタイミング(正しい値が入力された時)で消す必要があります。CellValidatedやCellEndEditイベントハンドラで消すのが適当でしょう。上記の例では、CellValidatedイベントを使用しています。

行単位でセルの内容を検証する

そのセルの内容だけでなく、同じ行の別のセルの内容によって検証結果が異なるケースでは、CellValidatingイベントではなく、RowValidatingイベントを使うとよいでしょう。RowValidatingイベントはCellValidatingイベントと違い、同じ行の別のセルにフォーカスが移動しても発生せず、別の行や、別のコントロールに移動するときに発生します。よって、同じ行のセルを一度に検証したい時に便利です。

以下の例では、空のセルがあると別の行に移動できないようにしています。

VB.NET
コードを隠すコードを選択
'RowValidatingイベントハンドラ 
Private Sub dataGridView1_RowValidating(ByVal sender As Object, _
    ByVal e As DataGridViewCellCancelEventArgs) _
    Handles DataGridView1.RowValidating

    Dim dgv As DataGridView = DirectCast(sender, DataGridView)

    '新しい行でなく、行の内容が変更されている時だけ検証する 
    If e.RowIndex = dgv.NewRowIndex OrElse Not dgv.IsCurrentRowDirty Then
        Exit Sub
    End If

    '行のセルが空かを調べる 
    For Each cell As DataGridViewCell In dgv.Rows(e.RowIndex).Cells
        If cell.Value Is Nothing OrElse cell.Value.ToString() = "" Then
            '行にエラーテキストを設定 
            dgv.Rows(e.RowIndex).ErrorText = _
                "すべてのセルに値を入力してください。"
            'キャンセルする 
            e.Cancel = True
        End If
    Next
End Sub

'RowValidatedイベントハンドラ 
Private Sub dataGridView1_RowValidated(ByVal sender As Object, _
    ByVal e As DataGridViewCellEventArgs) _
    Handles DataGridView1.RowValidated

    Dim dgv As DataGridView = DirectCast(sender, DataGridView)
    'エラーテキストを消す 
    dgv.Rows(e.RowIndex).ErrorText = Nothing
End Sub
C#
コードを隠すコードを選択
//RowValidatingイベントハンドラ
private void dataGridView1_RowValidating(object sender,
    DataGridViewCellCancelEventArgs e)
{
    DataGridView dgv = (DataGridView)sender;

    //新しい行でなく、行の内容が変更されている時だけ検証する
    if (e.RowIndex == dgv.NewRowIndex || !dgv.IsCurrentRowDirty)
    {
        return;
    }

    //行のセルが空かを調べる
    foreach (DataGridViewCell cell in dgv.Rows[e.RowIndex].Cells)
    {
        if (cell.Value == null || cell.Value.ToString() == "")
        {
            //行にエラーテキストを設定
            dgv.Rows[e.RowIndex].ErrorText =
                "すべてのセルに値を入力してください。";
            //キャンセルする
            e.Cancel = true;
        }
    }
}

//RowValidatedイベントハンドラ
private void dataGridView1_RowValidated(object sender,
    DataGridViewCellEventArgs e)
{
    DataGridView dgv = (DataGridView)sender;
    //エラーテキストを消す
    dgv.Rows[e.RowIndex].ErrorText = null;
}

CellValidatingとRowValidatingイベントの発生する順番は、CellValidating、CellValidated、RowValidating、RowValidatedとなります。

CellValidatingでチェックしても不正な値が入力される

CellValidatingイベントでセルに不正な値が入力されないようにチェックしていたとしても、セルに不正な値が設定される可能性があります。プログラムでセルに直接値を設定した場合は言うまでもありませんが、それ以外にも、新しい行が追加された時に不正な値が設定される恐れがあります。

例えば、一番初めに紹介したCellValidatingイベントを使ったサンプルコードのケースでは、新しい行の"Column1"以外のセルに値を入力して新しい行を作成した時、"Column1"のセルにはフォーカスが移動していませんので、このセルのCellValidatingイベントは発生しません。そのため、新しい行の"Column1"のセルの初期値が不正な値であったならば、不正な値のまま新しい行が追加されてしまいます。

これを防ぐには、「DataGridViewに新しく追加される行のセルの既定値を指定する」で紹介したような方法でセルの既定値が不正な値にならないようにしたり、RowValidatingイベントでチェックを行うようにすればよいでしょう。

  • 履歴:
  • 2009/12/25 「行単位でセルの内容を検証する」と「CellValidatingでチェックしても不正な値が入力される」を追加。
  • 2016/5/30 リンク切れを修正。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。