DataGridView中的VB.NET更新问题TimePicker:输入键不更新显示的值 [英] VB.NET Update Issue in DataGridView Cell for TimePicker: Enter Key Does not Update Displayed Value

查看:114
本文介绍了DataGridView中的VB.NET更新问题TimePicker:输入键不更新显示的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个好奇的问题,在VB.NET中重载DataGridView的单元格以使用DateTimePicker(允许用户选择日期和时间)。我采用了 Microsoft实施日历选择器并修改它是日历和时间选择器。当我输入新的日期并按ENTER键时,DataGridView单元格中显示的日期是旧的日期。



只有在该键再次按ENTER时,或点击该单元格,然后单击,显示新值。



如果单击单元格,输入新日期,此单元格将显示适当的日期时间值,然后点击进入另一个单元格。然后,显示的日期与我输入的日期相符。它正在使用我有问题的ENTER键。



我修改了Microsoft重载的代码如下:

 公共类TimeColumn 
继承DataGridViewColumn

Public Sub New()
MyBase.New(New TimeCell())
结束Sub

公共覆盖属性CellTemplate()作为DataGridViewCell
获取
返回MyBase.CellTemplate
结束获取
设置(ByVal值作为DataGridViewCell)
'确保用于模板的单元格是TimeCell。
If(value IsNot Nothing)AndAlso _
Not value.GetType()。IsAssignableFrom(GetType(TimeCell))_
然后
抛出新的InvalidCastException(必须是TimeCell )
End If
MyBase.CellTemplate = value
结束集
结束属性

结束类

公共类TimeCell
继承DataGridViewTextBoxCell

Public Sub New()
'使用短日期格式。
Me.Style.Format =MM / dd / yy h:mm tt
'm_isTime = True
End Sub
公开覆盖Sub InitializeEditingControl(ByVal rowIndex As Integer,_
ByVal initialFormattedValue As Object,_
ByVal dataGridViewCellStyle As DataGridViewCellStyle)

'将编辑控件的值设置为当前单元格值。
MyBase.InitializeEditingControl(rowIndex,initialFormattedValue,_
dataGridViewCellStyle)

Dim ctl As New TimeEditingControl
ctl = CType(DataGridView.EditingControl,TimeEditingControl)
ctl.CustomFormat =MM / dd / yyyy h:mm tt
Me.Value = ctl.Value

End Sub

公共覆盖ReadOnly属性EditType( )As Type
Get
'返回TimeCell使用的编辑轮廓的类型。
返回GetType(TimeEditingControl)
结束获取
结束属性

公共覆盖ReadOnly属性ValueType()作为类型
获取
'返回TimeCell包含的值的类型。
返回GetType(DateTime)
结束获取
结束属性

公共覆盖ReadOnly属性DefaultNewRowValue()As Object
获取
'使用当前日期和时间为默认值。
返回DateTime.Now
结束获取
结束属性

结束类

类TimeEditingControl
继承DateTimePicker
实现IDataGridViewEditingControl

私有dataGridViewControl作为DataGridView
私有值IsChanged As Boolean = False
Private rowIndexNum As Integer

Public Sub New()
Me .Format = DateTimePickerFormat.Custom
End Sub
公共属性EditingControlFormattedValue()As Object _
实现IDataGridViewEditingControl.EditingControlFormattedValue

获取
返回Me.Value。 ToShortDateString()
结束Get

Set(ByVal value As Object)
如果TypeOf的值为String然后
Me.Value = DateTime.Parse(CStr(value) )
结束如果
结束集

结束属性

公共函数GetEditingControlFormatted Value(ByVal context _
As DataGridViewDataErrorContexts)As Object _
实现IDataGridViewEditingControl.GetEditingControlFormattedValue

Dim result,tempDateTime As DateTime
tempDateTime = Me.Value

返回tempDateTime.ToString
结束函数


公共Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As _
DataGridViewCellStyle)_
实现IDataGridViewEditingControl.ApplyCellStyleToEditingControl

Me.Font = dataGridViewCellStyle.Font
Me.CalendarForeColor = dataGridViewCellStyle.ForeColor
Me.CalendarMonthBackground = dataGridViewCellStyle.BackColor

End Sub

公共属性EditingControlRowIndex()As Integer _
实现IDataGridViewEditingControl.EditingControlRowIndex

获取
返回rowIndexNum
结束Get
Set(ByVal value As Integer)
rowIndexNum = value
结束集

结束属性



公共函数EditingControlWantsInputKey(ByVal key As Keys,_
ByVal dataGridViewWantsInputKey As Boolean)As Boolean _
实现IDataGridViewEditingControl.EditingControlWantsInputKey
Dim lDateTime As DateTime
'让DateTimePicker处理钥匙列出
选择键和Keys.KeyCode

案例Keys.Enter

Console.WriteLine(DateTime.Now.ToString&。& DateTime.Now。 Millisecond.ToString&:EditingControlWantsInputKey - Detected [ENTER] key。)
End选择
valueIsChanged = True
Console.WriteLine(EditingControlWantsInputKey(& Me.Value& ))
Dim lDataGridView1 As DataGridView
lDataGridView1 = Me.dataGridViewControl
lDataGridView1.BeginEdit(True)
lDataGridView1.BeginEdit(False)
返回True


结束函数

Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean)_
实现IDataGridViewEditingControl.PrepareEditingControlForEdit

'无需准备做完了。

End Sub

公共ReadOnly属性RepositionEditingControlOnValueChange()_
作为Boolean实现_
IDataGridViewEditingControl.RepositionEditingControlOnValueChange

获取
返回False
结束获取

结束属性

公共属性EditingControlDataGridView()作为DataGridView _
实现IDataGridViewEditingControl.EditingControlDataGridView

获取
返回dataGridViewControl

结束Get
Set(ByVal value As DataGridView)
dataGridViewControl = value
结束集

结束属性

公共属性EditingControlValueChanged()As Boolean _
实现IDataGridViewEditingControl.EditingControlValueChanged

获取
返回值IsChanged
结束获取
Set(ByVal值As Boolean)
valueIsChanged = value
结束集

结束属性

公共ReadOnly属性EditingControlCursor()As Cursor _
实现IDataGridViewEditingControl.EditingPanelCursor

获取
返回MyBase.Cursor
结束获取

结束属性

受保护的覆盖Sub OnValueChanged(ByVal eventargs As EventArgs)

'通知DataGridView单元格的内容已更改。
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnValueChanged(eventargs)

End Sub

结束类

我的发现到目前为止:


  1. 有趣的是,公共属性EditingControlValueChanged()作为布尔实现IDataGridViewEditingControl.EditingControlValueChanged 根本没有检测到ENTER键!您可以看到我为该事件输入了一些调试代码,看看它是否检测到按下ENTER键。


  2. 事件 Public Property EditingControlValueChanged()由于布尔实现IDataGridViewEditingControl.EditingControlValueChanged 不会检测到值更改(布尔值IsChanged设置为false),直到第二次按ENTER键,此时它被设置为true。


  3. 我也尝试更新DataGridView的CellEndEdit事件中的单元格值,但是没有起作用。


  4. p>我已经更新了我的Visual Studio Express 2013,以防它是Micosoft错误。


任何想法如何获得显示的值以匹配按ENTER键输入的内容?谢谢。

解决方案

我的初始评论绝对是错误的。在重现你的问题之后,我注意到有趣/令人沮丧的事情:在下面的一行的 EditingControlWantsInputKey 方法中放置一个断点,允许更新按预期发生(调试修复的问题):


 选择键And Keys.KeyCode 


这是非常烦人的,在我的沮丧中,我连续疯狂地测试了月份条目:1,2,3,...,12



这是当我注意到:10-12月更新正确。其实输入01正确更新。我随后的研究结果导致我进入了本文的评论部分,其中用户Dean Wiles在其评论中标题为使用Tab或Enter 丢失的更改提供这个Microsoft支持源,这表明:


提高了[DateTimePicker]的ValueChanged事件只有在
后,您才能输入以下任何一项:




  • 一年中的所有数字。

  • 一天的所有数字。

  • 一个月的所有数字。


这可以通过将以下vb.net版本的代码添加到您的 TimeEditingControl 类来解决:

 受保护的覆盖函数ProcessCmdKey(ByRef msg As Message,keyData As Keys)As Boolean 
选择案例keyData和Keys.KeyCode
案例Keys.Enter,Keys.Tab
Me.dataGridViewControl.Focus()
退出选择
结束选择

返回MyBase.ProcessCmdKey(msg,keyData)
结束函数


I am having a curious issue with overloading a cell of the DataGridView in VB.NET to use a DateTimePicker (allows user to select both a date and a time). I took the Microsoft implementation of a Calendar picker and modified it be both a Calendar and Time picker. When I enter a new date and press the ENTER key, the displayed date in the DataGridView cell is the old date.

It's only when press ENTER again on that key, or click on that cell and click away that the new value is displayed.

This cell does display the proper date-time value if I click on the cell, enter a new date, and click away onto another cell. Then, the displayed date matches what I inputted. It's using the ENTER key that I am having issues with.

I modified the Microsoft overloaded code as follows:

Public Class TimeColumn
    Inherits DataGridViewColumn

    Public Sub New()
        MyBase.New(New TimeCell())
    End Sub

    Public Overrides Property CellTemplate() As DataGridViewCell
        Get
            Return MyBase.CellTemplate
        End Get
        Set(ByVal value As DataGridViewCell)
            ' Ensure that the cell used for the template is a TimeCell.
            If (value IsNot Nothing) AndAlso _
                Not value.GetType().IsAssignableFrom(GetType(TimeCell)) _
                Then
                Throw New InvalidCastException("Must be a TimeCell")
            End If
            MyBase.CellTemplate = value
        End Set
    End Property

End Class

Public Class TimeCell
    Inherits DataGridViewTextBoxCell

    Public Sub New()
        ' Use the short date format.            
        Me.Style.Format = "MM/dd/yy  h:mm tt"
        'm_isTime = True
    End Sub
    Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
        ByVal initialFormattedValue As Object, _
        ByVal dataGridViewCellStyle As DataGridViewCellStyle)

        ' Set the value of the editing control to the current cell value.
        MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, _
            dataGridViewCellStyle)

        Dim ctl As New TimeEditingControl
        ctl = CType(DataGridView.EditingControl, TimeEditingControl)
        ctl.CustomFormat = "MM/dd/yyyy h:mm tt"
        Me.Value = ctl.Value

    End Sub

    Public Overrides ReadOnly Property EditType() As Type
        Get
            ' Return the type of the editing contol that TimeCell uses.
            Return GetType(TimeEditingControl)
        End Get
    End Property

    Public Overrides ReadOnly Property ValueType() As Type
        Get
            ' Return the type of the value that TimeCell contains.            
            Return GetType(DateTime)
        End Get
    End Property

    Public Overrides ReadOnly Property DefaultNewRowValue() As Object
        Get
            ' Use the current date and time as the default value.
            Return DateTime.Now
        End Get
    End Property

End Class

Class TimeEditingControl
    Inherits DateTimePicker
    Implements IDataGridViewEditingControl

    Private dataGridViewControl As DataGridView
    Private valueIsChanged As Boolean = False
    Private rowIndexNum As Integer

    Public Sub New()
        Me.Format = DateTimePickerFormat.Custom
    End Sub
    Public Property EditingControlFormattedValue() As Object _
        Implements IDataGridViewEditingControl.EditingControlFormattedValue

        Get
            Return Me.Value.ToShortDateString()
        End Get

        Set(ByVal value As Object)
            If TypeOf value Is String Then
                Me.Value = DateTime.Parse(CStr(value))
            End If
        End Set

    End Property

    Public Function GetEditingControlFormattedValue(ByVal context _
        As DataGridViewDataErrorContexts) As Object _
        Implements IDataGridViewEditingControl.GetEditingControlFormattedValue

        Dim result, tempDateTime As DateTime
        tempDateTime = Me.Value      

        Return tempDateTime.ToString            
    End Function


    Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As  _
        DataGridViewCellStyle) _
        Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl

        Me.Font = dataGridViewCellStyle.Font
        Me.CalendarForeColor = dataGridViewCellStyle.ForeColor
        Me.CalendarMonthBackground = dataGridViewCellStyle.BackColor

    End Sub

    Public Property EditingControlRowIndex() As Integer _
        Implements IDataGridViewEditingControl.EditingControlRowIndex

        Get
            Return rowIndexNum
        End Get
        Set(ByVal value As Integer)
            rowIndexNum = value
        End Set

    End Property



    Public Function EditingControlWantsInputKey(ByVal key As Keys, _
        ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
        Implements IDataGridViewEditingControl.EditingControlWantsInputKey
        Dim lDateTime As DateTime
        ' Let the DateTimePicker handle the keys listed.
        Select key And Keys.KeyCode

            Case Keys.Enter

                Console.WriteLine(DateTime.Now.ToString & "." & DateTime.Now.Millisecond.ToString & ": EditingControlWantsInputKey--Detected [ENTER] key.")
        End Select
        valueIsChanged = True
        Console.WriteLine("EditingControlWantsInputKey (" & Me.Value & ")")
        Dim lDataGridView1 As DataGridView
        lDataGridView1 = Me.dataGridViewControl
        lDataGridView1.BeginEdit(True)
        lDataGridView1.BeginEdit(False)
        Return True


    End Function

    Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _
        Implements IDataGridViewEditingControl.PrepareEditingControlForEdit

        ' No preparation needs to be done.

    End Sub

    Public ReadOnly Property RepositionEditingControlOnValueChange() _
        As Boolean Implements _
        IDataGridViewEditingControl.RepositionEditingControlOnValueChange

        Get
            Return False
        End Get

    End Property

    Public Property EditingControlDataGridView() As DataGridView _
        Implements IDataGridViewEditingControl.EditingControlDataGridView

        Get
            Return dataGridViewControl

        End Get
        Set(ByVal value As DataGridView)
            dataGridViewControl = value
        End Set

    End Property

    Public Property EditingControlValueChanged() As Boolean _
        Implements IDataGridViewEditingControl.EditingControlValueChanged

        Get
            Return valueIsChanged
        End Get
        Set(ByVal value As Boolean)
            valueIsChanged = value
        End Set

    End Property

    Public ReadOnly Property EditingControlCursor() As Cursor _
        Implements IDataGridViewEditingControl.EditingPanelCursor

        Get
            Return MyBase.Cursor
        End Get

    End Property

    Protected Overrides Sub OnValueChanged(ByVal eventargs As EventArgs)

        ' Notify the DataGridView that the contents of the cell have changed.
        valueIsChanged = True
        Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
        MyBase.OnValueChanged(eventargs)

    End Sub

End Class

My findings so far:

  1. What's curious is that Public Property EditingControlValueChanged() As Boolean Implements IDataGridViewEditingControl.EditingControlValueChanged does not detect the ENTER key at all! You can see I entered some debugging code for that event to see if it detects the ENTER key being pressed.

  2. The event Public Property EditingControlValueChanged() As Boolean Implements IDataGridViewEditingControl.EditingControlValueChanged does not detect the value change (the boolean valueIsChanged is set to false) until the second time the ENTER key is pressed, at which point it is set to true.

  3. I tried also updating the cell value in the CellEndEdit event for the DataGridView, but that didn't work.

  4. I already updated my Visual Studio Express 2013 in case it was a Micosoft bug.

Any ideas how to get the displayed value to match what was entered upon hitting the ENTER key? Thanks.

解决方案

My initial comment was definitely wrong. After reproducing your problem, I noticed something funny/frustrating: placing a breakpoint within the EditingControlWantsInputKey method on the following line, allowed the updates to occur as expected (a debugging fix of the problem):

Select key And Keys.KeyCode

That was beyond annoying and in my frustration, I frantically tested month entries in succession: 1, 2, 3, ..., 12

That's when I noticed: months 10-12 updated correctly. In fact, entering 01 updated correctly. My subsequent research led me to the comments section of this article, where user Dean Wiles in his comment titled Changes lost using Tab or Enter provides this Microsoft support source which indicates that:

The ValueChanged event of the [DateTimePicker] is raised only after you type any one of the following:

  • All the digits of a year.
  • All the digits of a day.
  • All the digits of a month.

And this can be addressed by adding the following vb.net version of his code to your TimeEditingControl class:

Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
    Select Case keyData And Keys.KeyCode
        Case Keys.Enter, Keys.Tab
            Me.dataGridViewControl.Focus()
            Exit Select
    End Select

    Return MyBase.ProcessCmdKey(msg, keyData)
End Function

这篇关于DataGridView中的VB.NET更新问题TimePicker:输入键不更新显示的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆