vb.netでdataridcontrolをdatatableを使用し、
BindingSourceしています。
datagridviewで数値型等のエラーが発生した際に「既定のエラーダイアログ」が表示されるので、DataErrorで処理を行おうと思っています。
数値欄に文字を入力した場合のエラーはdataErrorで拾いたいのですが
主キーの重複エラーとNULLエラーはdataerrorで拾いたくないのですが
こんな使い分けはできるのでしょうか。
エラー発生時に、入力された文字列を見て、自前で判断する必要があるかと。
dataerror起動時にエラーとしない項目はshaincodeだけ
なのですが、(それ以外の項目はすべてdataerrorで検出してOK)
その場合は具体的にどうすればいいのでしょうか。
今はこのようなコードを書いています。
'DataErrorイベントハンドラ
Private Sub DataGridView1_DataError(ByVal sender As Object, _
ByVal e As DataGridViewDataErrorEventArgs) _
Handles DataGridView1.DataError
If Not (e.Exception Is Nothing) Then
MessageBox.Show(Me, _
String.Format("({0}, {1}) のセルでエラーが発生しました。" + _
vbCrLf + vbCrLf + "説明: {2}", _
e.ColumnIndex, e.RowIndex, e.Exception.Message), _
"エラーが発生しました", _
MessageBoxButtons.OK, _
MessageBoxIcon.Error)
End If
End Sub
回答して頂きありがとうございました。
詳細としては、
新しく行を追加した際に、入力後「確定」ボタンを
押すことでDBにデータを追加しにいく仕様になっています。
カーソルが新規行にいる場合は大丈夫なのですが、
他の行にあたった瞬間にdataerrorが走り、数値入力フィールドで
あれば新規行は消えないのですが、主キーのチェックが
入った場合は、エラーメッセージが表示された後、新規行自体
が消えてしまうんです。
どうにかならないでしょうか。
たとえば、こんな感じ。
Private Sub DataGridView1_DataError(……
e.ThrowException = False
End Sub
Private Sub DataGridView1_CellValidating(……
If e.ColumnIndex = 社員コード列 Then
Dim value As Decimal
If Not Decimal.TryParse(e.FormattedValue.ToString(), value) _
OrElse value < 0D OrElse value > 99999D Then
MessageBox.Show("0 から 99999 までの範囲の数値を入力してください。", _
"入力エラー", MessageBoxButtons.OK, MessageBoxIcon.Warning)
End If
End If
End Sub
あるいは、目的のセルを数値型にせず、何でも入力可能な(String型)に
しておいて、MessageBox ではなくセルまたは行の ErrorText プロパティを
使って、エラーアイコンによる通知を使うという手もあるかと。
あぁ、重複エラーを処理したいということでしたか。
であれば、これでどうでしょう。
Public Class Form1
Private table As New DataTable
Private Const ShainCDColumn As Integer = 0
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
table = New DataTable
table.Columns.Add("ShainCD", GetType(Integer))
table.Columns.Add("ShainSei", GetType(String))
table.PrimaryKey = New DataColumn() {table.Columns("ShainCD")}
table.Rows.Add(1000, "田中")
table.Rows.Add(2000, "中山")
table.Rows.Add(3000, "山岡")
table.Rows.Add(4000, "岡田")
table.AcceptChanges()
DataGridView1.EditMode = DataGridViewEditMode.EditOnEnter
DataGridView1.DataSource = table
End Sub
'既存行の主キーを変更できなくする
Private Sub DataGridView1_CellEnter(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles DataGridView1.CellEnter
If e.ColumnIndex = ShainCDColumn Then
Dim dgvRow As DataGridViewRow = DataGridView1.Rows(e.RowIndex)
Dim dgvRowView As DataRowView = Nothing
Try
dgvRowView = DirectCast(dgvRow.DataBoundItem, DataRowView)
Catch
End Try
If dgvRowView Is Nothing Then
Return '新規行
End If
If dgvRowView Is Nothing Then Return
Dim row As DataRow = dgvRowView.Row
Dim isNewRow As Boolean = (row.RowState = DataRowState.Detached OrElse row.RowState = DataRowState.Added)
DataGridView1(ShainCDColumn, e.RowIndex).ReadOnly = Not isNewRow
End If
End Sub
Private Sub DataGridView1_DataError(ByVal sender As Object, ByVal e As DataGridViewDataErrorEventArgs) Handles DataGridView1.DataError
e.ThrowException = False
End Sub
Private Sub DataGridView1_RowValidating(ByVal sender As Object, ByVal e As DataGridViewCellCancelEventArgs) Handles DataGridView1.RowValidating
Dim dgvRow As DataGridViewRow = DataGridView1.Rows(e.RowIndex)
Dim dgvRowView As DataRowView = Nothing
Try
dgvRowView = DirectCast(dgvRow.DataBoundItem, DataRowView)
Catch ex As Exception
e.Cancel = True
End Try
If dgvRowView Is Nothing Then
Return '新規行
End If
Dim row As DataRow = dgvRowView.Row
Dim isNewRow As Boolean = (row.RowState = DataRowState.Detached OrElse row.RowState = DataRowState.Added)
If isNewRow Then
Dim newValue As Object = DataGridView1(ShainCDColumn, e.RowIndex).Value
For Each dataRow As DataRow In table.Rows
If Integer.Equals(dataRow("ShainCD"), newValue) Then
If dataRow IsNot row Then
MessageBox.Show(String.Format( _
"社員コード{0}は、既に'{1}'として登録済みです。", _
newValue, dataRow("ShainSei")), _
"入力エラー", MessageBoxButtons.OK, MessageBoxIcon.Error)
e.Cancel = True
Return
End If
End If
Next
End If
End Sub
End Class
解決しました。
本当にありがとうございました
ツイート | ![]() |