3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(.Net)DataGridViewでの入力チェックはCellValidatingだけではダメ

現在、CellValidatingイベントでセルの入力チェックを行っていたのですが、どうやら CellValidating だけでチェックしたのではダメっぽいです。

たとえば複数列の DataGridView で全列Null不可の条件かつ登録ボタンを押下すれば、DBに反映するというような場合、新規行のどっかのセルに値を入れて、そのまま登録ボタンを押下すれば、null値がDBに登録されてしまい、DBがnullを許してないため、例外が発生します。

なので、入力チェックは CellValidating イベントだけでなく、RowValidating も使ってやる必要ありそうです。

RowValidating なら、ここで全セルをチェックしてやればいいだけですからね。

ということで、簡単なサンプルです。

これは、CellValidating と、RowValidating で入力チェックを行っています。

RowValidating だけでもいいんでしょうが、こまかい制御をかけさせたいという要件もあると思うので CellValidating でもチェックさせます。

DBにはMDBを、列IDはオートナンバー型なのでここの値の割り振りはJETエンジンに任せてます。

列name1は文字列、列name2は数値型で、両方とも空値は認めません。

DataSetは下記のようなイメージで作ってます。

Public Class Form1

 

'DataTable

Private mTable1Dtbl As New Database1DataSet.table1DataTable()

'TableAdapter

Private mTable1Adp As New Database1DataSetTableAdapters.table1TableAdapter()

 

'''

''' フォームロード

'''

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

'DataTableにDBの情報を取得し、DataGridViewにバインドさせる

mTable1Adp.Fill(mTable1Dtbl)

Me.DataGridView1.DataSource = mTable1Dtbl

End Sub

 

'''

''' 登録ボタン押下

'''

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

'DataGridView-->DataTableの情報をDBに反映

mTable1Adp.Update(mTable1Dtbl)

'DBから情報取得し、DataGridViewに表示

mTable1Adp.Fill(mTable1Dtbl)

End Sub

 

'''

''' セルのValidating

'''

Private Sub DataGridView1_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating

Dim dgv As DataGridView = CType(sender, DataGridView)

'入力チェックに引っ掛かれば、イベントをキャンセルする

'新規行はチェックしない

If dgv.Rows(e.RowIndex).IsNewRow Then

Return

End If

If dgv.Columns(e.ColumnIndex).Name = "name1" Then

If Not InputCheck_name1(e.FormattedValue) Then

Console.WriteLine("CellError")

e.Cancel = True

Return

End If

End If

If dgv.Columns(e.ColumnIndex).Name = "name2" Then

If Not InputCheck_name2(e.FormattedValue) Then

Console.WriteLine("CellError")

e.Cancel = True

Return

End If

End If

End Sub

 

 

'''

''' 行のValidating

'''

Private Sub DataGridView1_RowValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles DataGridView1.RowValidating

Dim dgv As DataGridView = CType(sender, DataGridView)

'入力チェックに引っ掛かれば、イベントをキャンセルする

'新規行、コミットされてない行がない場合はチェックしない

If dgv.Rows(e.RowIndex).IsNewRow OrElse Not dgv.IsCurrentRowDirty Then ' OrElse e.RowIndex = dgv.NewRowIndex OrElse dgv("id", e.RowIndex).Value Is Nothing Then

Return

End If

 

If Not InputCheck_name1(dgv.Rows(e.RowIndex).Cells("name1").Value.ToString()) OrElse Not InputCheck_name2(dgv.Rows(e.RowIndex).Cells("name2").Value.ToString()) Then

Console.WriteLine("RowError")

e.Cancel = True

End If

 

End Sub

 

'''

''' name1列の入力チェック

'''

Private Function InputCheck_name1(ByVal value As String) As Boolean

If String.IsNullOrEmpty(value) Then

MessageBox.Show("入力エラーname1")

Return False

End If

Return True

End Function

 

'''

''' name2列の入力チェック

'''

Private Function InputCheck_name2(ByVal value As String) As Boolean

If String.IsNullOrEmpty(value) Then

MessageBox.Show("入力エラーname2")

Return False

End If

If Not Integer.TryParse(value, 0) Then

MessageBox.Show("入力エラーname2")

Return False

End If

Return True

End Function

End Class

この場合だと、一つでも入力エラーとなれば、正しい値を入れるまで何もできない(フォームを閉じることさえ)ので、実装には工夫が必要ですね。

参考:

MSDNフォーラム:レコードにNull値があるか調べる方法