補完しておきます。 えっと、 テーマは、 DataGridView で表示編集する 数値型データ。
DataGridView で、数字の桁数で 調整出来る場合は、前回 も参照して下さい。
今回は、 既定の範囲を超える値のエラー と 文字から数字のエラー と 一意制約違反 を捉えます。
先ず、前提条件。
DataBase で、主キー に設定した列に対して、 DataBase: MyDatabase ColumnName: ID Type: INT32
自動生成で 型付データセット を作り、 DataSet: MyDatabaseDataSet
更に DataGridView に表示します。 DataGridView: TestDataGridView
INT32 ですから、値の範囲は -2147483648 ~ 2147483647 。
主キー制約ですから、値の重複 は不可。
数値型ですから、勿論、アルファベットや文字 は不可。 数字だけ。
この条件下で、標準的に用意される DataGridView は、
該当 Column ( Cell ) に、 文字でも、数字でも、えらく長い数字(例:20桁)でも、入ります。
勿論、列や行を移動すれば、 本来、不正な値ですから、 エラー! と弾かれてしまいますね。
大元の DataBase の構造を反映している証拠なのですが、
出来れば、入力・編集している Column ( Cell ) の中で、 エラーを潰したいですよね。
では、コードですが、
Private Sub TestDataGridView_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) Handles TestDataGridView.CellValidating
If Not TestDataGridView.IsCurrentCellDirty Then
Exit Sub
End If
'test
Dim headerText As String = Me.TestDataGridView.Columns(e.ColumnIndex).HeaderText
If headerText = "ID" Then
Const escapeMsg As String = " [Esc]:Cancel"
Try
Integer.Parse(CType(Me.TestDataGridView.EditingControl, TextBox).Text)
Catch ex As System.ArgumentNullException
Me.TestDataGridView.Rows(e.RowIndex).ErrorText = "Null" & " (INT32) " & CType(Me.TestDataGridView.EditingControl, TextBox).Text & escapeMsg
CType(Me.TestDataGridView.EditingControl, TextBox).ForeColor = Color.Crimson
e.Cancel = True
Catch ex As System.FormatException
Me.TestDataGridView.Rows(e.RowIndex).ErrorText = "NotCorrect" & " (INT32) " & CType(Me.TestDataGridView.EditingControl, TextBox).Text & escapeMsg
CType(Me.TestDataGridView.EditingControl, TextBox).ForeColor = Color.Crimson
e.Cancel = True
Catch ex As System.StackOverflowException
'Me.TestDataGridView.Rows(e.RowIndex).ErrorText = "OverFlow" & " (INT32) " & CType(Me.TestDataGridView.EditingControl, TextBox).Text
CType(Me.TestDataGridView.EditingControl, TextBox).ForeColor = Color.Crimson
e.Cancel = True
Catch ex As System.OverflowException
Me.TestDataGridView.Rows(e.RowIndex).ErrorText = "OverFlow" & " (INT32) " & CType(Me.TestDataGridView.EditingControl, TextBox).Text & escapeMsg
CType(Me.TestDataGridView.EditingControl, TextBox).ForeColor = Color.Crimson
e.Cancel = True
End Try
' for Commit Error Catching
Me.TestBindingSource.EndEdit()
End If
End Sub
Private Sub TestDataGridView_CellValidated(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles TestDataGridView.CellValidated
Me.TestDataGridView.Rows(e.RowIndex).ErrorText = String.Empty
End Sub
Private Sub TestDataGridView_DataError(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles TestDataGridView.DataError
Dim headerText As String = Me.TestDataGridView.Columns(e.ColumnIndex).HeaderText
If (e.Context = DataGridViewDataErrorContexts.Commit) Then
If headerText = "ID" Then
Const escapeMsg As String = " [Esc]:Cancel"
Me.TestDataGridView.Rows(e.RowIndex).ErrorText = "CommitUnique" & " (INT32) " & CType(Me.TestDataGridView.EditingControl, TextBox).Text & escapeMsg
CType(Me.TestDataGridView.EditingControl, TextBox).ForeColor = Color.Crimson
e.Cancel = True
End If
End If
End Sub
この様なコードでは如何でしょうか。
エラーメッセージをそのまま流用する場合には、 Const ~ の行は 外に出して ひとつに纏めた方がいいかもです。
また、当然、複数の列 ( Column / Cell ) があるでしょうから、 他の列で、違反を潰しきれていない場合、
DataError イベント ハンドラ が捕捉してしまい、 本来、対処すべき処理が 毀れてしまう可能性も否定出来ません。
ご注意!を。
それから、 それから、 上の例では、一意違反の場合、単に、メッセージを示すのみで、
有効な値が入力される迄、該当列を 抜けれません。
実際には、何か、対応方法を検討すべきでしょう、 ね。
と、ここ迄 書いてきて、 以前、日付型の扱い方について書いた事を思い出しました。
立ち位置が違うので、少し、違う展開ですが、 まぁ、参考にはなるかも です。
一応、 リンクを載せて置きます。
VB DataGridView と CellValidating
0 件のコメント:
コメントを投稿