DataGridView DateTime列字符串未被识别为有效的DateTime DataError

时间:2017-09-15 15:57:53

标签: .net vb.net datetime datagridview

我有一个DataGridView DataTable作为DataSource。在DataTable中,我的列DataTypeDateTime。使用DataTable SQL ServerSqlDataAdapter成功填写了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更正声明?我想在CellValidatedDataErrorCreateWithInlinesView事件中这样做。我正在进行测试,但感觉我在这里错过了一个更简单的解决方案。

谢谢!

1 个答案:

答案 0 :(得分:2)

由于您需要的格式是非标准格式,因此您必须提供解析和显示格式的逻辑。一种方法是在CellFormattingCellParsing事件中编写一些代码。

另一种方法是指定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,您会在CellParsingCellFormatting事件中使用相同的代码,但您必须在其他可能使用奇数的网格上复制它格式。由于格式化程序传递了要使用的格式,因此可以重复使用。

在这种情况下,DGV可以进行解析和格式化,因为它只需要它所具有的格式字符串。但在其他情况下,例如转换纪元类型日期(自某个任意日期以来的秒数),它将毫无头绪。因此,它们为您提供了创建和使用自己的IFormatProvider的方法。这些可以与其他内容一起使用,例如Enum转换,TimeSpan格式化等。