【问题标题】:DataGridView DateTime column string was not recognized as a valid DateTime DataErrorDataGridView DateTime 列字符串未被识别为有效的 DateTime DataError
【发布时间】:2017-09-15 15:57:52
【问题描述】:

我有一个DataGridView 和一个DataTable 作为它的DataSource。在DataTable 中,我有一列包含DataTypeDateTimeDataTable 使用 SqlDataAdapterSQL Server 成功填充。

我正在使用:

dgv.Columns(j).DefaultCellStyle.Format = "dd/MM/yyyy HHmm"

作为相关DataGridViewTextBoxColumn 的格式,数据加载正常,并以这种所需格式正确显示。

但是,每当我对此列中的一个单元格进行有效(或无效)编辑时,我总是会收到错误消息:

System.FormatException:字符串未被识别为有效的 DateTime。 在 System.DateTime.Parse(String s, IFormatProvider provider)... 请处理 DataError 事件。

DataGridViewTextBoxColumn 无法正确确定用户输入的值,仅仅指定默认单元格样式格式并不足以让我感到惊讶。所以,我的问题是:是否有其他一些事件/地方适合(并且有必要)指定某种CellValue = DateTime.TryParseExact(blah blah) 更正声明?我正在考虑在CellValidatingCellValidatedDataError 事件中这样做。我会做测试,但我真的觉得我在这里错过了一个更简单的解决方案。

谢谢!

【问题讨论】:

    标签: .net vb.net datetime datagridview


    【解决方案1】:

    由于您想要的格式是非标准的,您必须帮助提供解析和显示它的逻辑。一种方法是在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 格式化等其他内容一起使用。

    【讨论】:

    • 天才。 @Plutonix 是我的 DataGridView 英雄。为他人着想,请考虑在代码顶部的 Imports System.Globalization 第一行进行编辑。
    • 是的,我从完全合格的Globalization.DateTimeStyles.None ref 中截取了它以减少 HScroll。已添加
    猜你喜欢
    • 2011-09-12
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    相关资源
    最近更新 更多