我有一个DataGridView
DataTable
作为DataSource
。在DataTable
中,我的列DataType
为DateTime
。使用DataTable
SQL Server
从SqlDataAdapter
成功填写了dgv.Columns(j).DefaultCellStyle.Format = "dd/MM/yyyy HHmm"
。
我正在使用:
DataGridViewTextBoxColumn
作为相关DataGridViewTextBoxColumn
的格式,数据加载正常,并以正确的格式显示。
但是,每当我对此列中的一个单元格进行有效(或无效)编辑时,我总是会收到错误:
System.FormatException:String未被识别为有效的DateTime。 在System.DateTime.Parse(String s,IFormatProvider provider)...请处理DataError事件。
我很惊讶,只是指定默认的单元格样式并不足以让CellValue = DateTime.TryParseExact(blah blah)
正确地确定用户输入的值。所以,我的问题是:是否有一些其他事件/地方适合(和必要)指定某种CellValidating
更正声明?我想在CellValidated
,DataError
或CreateWithInlinesView
事件中这样做。我正在进行测试,但感觉我在这里错过了一个更简单的解决方案。
谢谢!
答案 0 :(得分:2)
由于您需要的格式是非标准格式,因此您必须提供解析和显示格式的逻辑。一种方法是在CellFormatting
和CellParsing
事件中编写一些代码。
另一种方法是指定IFormatProvider
对象。 通常这些只是进行格式化,你仍然可能需要用于解析的代码,但是除了一些额外的代码行,FormatProvider
也可以这样做:
Imports System.Globalization
Public Class DGVOddDateFormatter
Implements IFormatProvider, ICustomFormatter
Private myFmt As String = "dd/MM/yyyy HHmm"
Private mydgv As DataGridView
Private myNDX As Int32 = -1
Public Sub New(ctl As DataGridView, fmt As String, colNdx As Int32)
mydgv = ctl
myFmt = fmt
myNDX = colNdx
AddHandler mydgv.CellParsing, AddressOf dgv_CellParsing
mydgv.Columns(colNdx).DefaultCellStyle.Format = fmt
End Sub
Private Sub dgv_CellParsing(sender As Object, e As DataGridViewCellParsingEventArgs)
If e.ColumnIndex = myNDX Then
Dim dt As DateTime
If DateTime.TryParseExact(e.Value.ToString(),
myFmt, Nothing,
DateTimeStyles.None, dt) Then
e.Value = dt
e.ParsingApplied = True
End If
End If
End Sub
Public Function Format(format1 As String,
arg As Object,
formatProvider As IFormatProvider) As String _
Implements ICustomFormatter.Format
Dim dt As DateTime
If TypeOf (arg) Is DateTime Then
dt = CType(arg, DateTime)
Return dt.ToString(myFmt)
Else
Return "" ' or other default value
End If
End Function
Public Function GetFormat(formatType As Type) As Object Implements IFormatProvider.GetFormat
If TypeOf formatType Is ICustomFormatter Then
Return Me
End If
Return Nothing
End Function
End Class
创建格式化程序时,它会挂钩CellParsing
事件,以提供补充逻辑,将内容转换回有效的DateTime
。
dgv1.DataSource = dtSample
dgv1.Columns(4).DefaultCellStyle.FormatProvider = New DGVOddDateFormatter(dgv1,
"dd/MM/yyyy HHmm", 4)
如果没有IFormatProvider
,您会在CellParsing
和CellFormatting
事件中使用相同的代码,但您必须在其他可能使用奇数的网格上复制它格式。由于格式化程序传递了要使用的格式,因此可以重复使用。
在这种情况下,DGV可以进行解析和格式化,因为它只需要它所具有的格式字符串。但在其他情况下,例如转换纪元类型日期(自某个任意日期以来的秒数),它将毫无头绪。因此,它们为您提供了创建和使用自己的IFormatProvider
的方法。这些可以与其他内容一起使用,例如Enum
转换,TimeSpan
格式化等。