强制datagridview单元承载一个numericupdown,恢复它在转义按下时更改

时间:2013-07-10 08:27:15

标签: vb.net winforms

我正在创建一个托管datagridviewcell控件的numeric updown。除了一件事,一切都很顺利。我无法在textboxcellcomboboxcell之类的转义按键上恢复更改。我的datagridviewcell是基于this示例创建的。所以任何人都知道如何在转义键按下时将numeric updown cell还原为先前的值?

NumericColumn类:

Imports System
Imports System.Windows.Forms

Public Class NumericColumn
    Inherits DataGridViewColumn

    ''' <summary>
    ''' Get, set numeric control min value
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property MinValue() As Decimal
        Get
            Return CType(MyBase.CellTemplate, NumericCell).MinValue
        End Get
        Set(ByVal value As Decimal)
            CType(MyBase.CellTemplate, NumericCell).MinValue = value
        End Set
    End Property

    ''' <summary>
    ''' Get, set numeric control max value
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property MaxValue() As Decimal
        Get
            Return CType(MyBase.CellTemplate, NumericCell).MaxValue
        End Get
        Set(ByVal value As Decimal)
            CType(MyBase.CellTemplate, NumericCell).MaxValue = value
        End Set
    End Property

    ''' <summary>
    ''' Get, set numeric control value
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property NumericControlValue() As Decimal
        Get
            Return CType(MyBase.CellTemplate, NumericCell).NumericControlValue
        End Get
        Set(ByVal value As Decimal)
            CType(MyBase.CellTemplate, NumericCell).NumericControlValue = value
        End Set
    End Property

    ''' <summary>
    ''' Indicate number of decimal places to display
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property DecimalPlaces() As Integer
        Get
            Return CType(MyBase.CellTemplate, NumericCell).DecimalPlaces
        End Get
        Set(ByVal value As Integer)
            CType(MyBase.CellTemplate, NumericCell).DecimalPlaces = value
        End Set
    End Property

    ''' <summary>
    ''' Detemine the value to increment or decrement each time button click
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Increment() As Integer
        Get
            Return CType(MyBase.CellTemplate, NumericCell).Increment
        End Get
        Set(ByVal value As Integer)
            CType(MyBase.CellTemplate, NumericCell).Increment = value
        End Set
    End Property

    Public Sub New()
        MyBase.New(New NumericCell())
    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 CalendarCell. 
            If (value IsNot Nothing) AndAlso _
                Not value.GetType().IsAssignableFrom(GetType(NumericCell)) _
                Then
                Throw New InvalidCastException("Must be a Numeric Cell")
            End If
            MyBase.CellTemplate = value

        End Set
    End Property

    ''' <summary>
    ''' Override clone method to clone new added properties
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function Clone() As Object
        Dim obj As NumericColumn = MyBase.Clone()
        obj.MaxValue = Me.MaxValue
        obj.MinValue = Me.MinValue
        obj.NumericControlValue = Me.NumericControlValue
        obj.DecimalPlaces = Me.DecimalPlaces
        obj.Increment = Me.Increment

        Return obj
    End Function
End Class

NumericCell类

Imports System
Imports System.Windows.Forms

Public Class NumericCell
    Inherits DataGridViewTextBoxCell

    ''' <summary>
    ''' Min value for numeric control
    ''' </summary>
    ''' <remarks></remarks>
    Private min As Decimal = 0.0

    ''' <summary>
    ''' Max value for numeric control
    ''' </summary>
    ''' <remarks></remarks>
    Private max As Decimal = 100.0

    ''' <summary>
    ''' Value for numeric control
    ''' </summary>
    ''' <remarks></remarks>
    Private controlValue As Decimal = 0.0

    ''' <summary>
    ''' Decimal places for numeric control
    ''' </summary>
    ''' <remarks></remarks>
    Private places As Integer = 0

    ''' <summary>
    ''' Detemine the value to increment or decrement each time button click
    ''' </summary>
    ''' <remarks></remarks>
    Private incrementStep As Integer = 1

    ''' <summary>
    ''' Get, set numeric control min value
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property MinValue() As Decimal
        Get
            Return Me.min
        End Get
        Set(ByVal value As Decimal)
            Me.min = value
        End Set
    End Property

    ''' <summary>
    ''' Get, set numeric control max value
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property MaxValue() As Decimal
        Get
            Return Me.max
        End Get
        Set(ByVal value As Decimal)
            Me.max = value
        End Set
    End Property

    ''' <summary>
    ''' Get, set numeric control value
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property NumericControlValue() As Decimal
        Get
            Return Me.controlValue
        End Get
        Set(ByVal value As Decimal)
            Me.controlValue = value
        End Set
    End Property

    ''' <summary>
    ''' Indicate number of decimal places to display
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property DecimalPlaces() As Integer
        Get
            Return Me.places
        End Get
        Set(ByVal value As Integer)
            Me.places = value
        End Set
    End Property

    ''' <summary>
    ''' Detemine the value to increment or decrement each time button click
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Increment() As Integer
        Get
            Return Me.incrementStep
        End Get
        Set(ByVal value As Integer)
            Me.incrementStep = value
        End Set
    End Property

    Public Sub New()

    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 NumericEditingControl = CType(DataGridView.EditingControl, NumericEditingControl)
        RemoveHandler ctl.Enter, AddressOf Me.OnNumericEnter
        AddHandler ctl.Enter, AddressOf Me.OnNumericEnter

        'config property for control
        ctl.Minimum = Me.min
        ctl.Maximum = Me.max
        ctl.DecimalPlaces = Me.DecimalPlaces
        ctl.Increment = Me.incrementStep
        ctl.TextAlign = HorizontalAlignment.Right
        ctl.ThousandsSeparator = True

        ' Use the default row value when Value property is null. 
        If (Me.Value Is Nothing) Then
            ctl.Value = Me.controlValue
        Else
            ctl.Value = CType(Me.Value, Decimal)
        End If


    End Sub

    ''' <summary>
    ''' Handle on enter event of numeric
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub OnNumericEnter(ByVal sender As Object, ByVal e As EventArgs)
        Dim control As NumericEditingControl = CType(sender, NumericEditingControl)
        Dim strValue As String = control.Value.ToString("N2")
        control.Select(0, strValue.Length)
    End Sub

    Public Overrides ReadOnly Property EditType() As Type
        Get
            ' Return the type of the editing control that CalendarCell uses. 
            Return GetType(NumericEditingControl)
        End Get
    End Property

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

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

    ''' <summary>
    ''' Override clone method to clone new added properties
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function Clone() As Object
        Dim obj As NumericCell = MyBase.Clone()
        obj.MaxValue = Me.MaxValue
        obj.MinValue = Me.MinValue
        obj.NumericControlValue = Me.NumericControlValue
        obj.DecimalPlaces = Me.DecimalPlaces
        obj.Increment = Me.Increment

        Return obj
    End Function
End Class

NumericEditingControl类:

Imports System
Imports System.Windows.Forms

Public Class NumericEditingControl
    Inherits NumericUpDown
    Implements IDataGridViewEditingControl

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

    Public Sub New()
        'Me.Format = DateTimePickerFormat.Short
    End Sub

    Public Property EditingControlFormattedValue() As Object _
        Implements IDataGridViewEditingControl.EditingControlFormattedValue

        Get
            Return Me.Value.ToString("N2")
        End Get

        Set(ByVal value As Object)
            Try
                ' This will throw an exception of the string is  
                ' null, empty, or not in the format of a date. 
                Me.Value = Decimal.Parse(value)
            Catch
                ' In the case of an exception, just use the default 
                ' value so we're not left with a null value. 
                Me.Value = 0.0
            End Try
        End Set

    End Property

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

        Return Me.Value.ToString("N2")

    End Function

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

        Me.Font = dataGridViewCellStyle.Font
        Me.ForeColor = dataGridViewCellStyle.ForeColor
        Me.BackColor = 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

        ' Let the DateTimePicker handle the keys listed. 
        'Select Case key And Keys.KeyCode
        '    Case Keys.Left, Keys.Up, Keys.Down, Keys.Right, _
        '        Keys.Home, Keys.End, Keys.PageDown, Keys.PageUp

        '        Return True

        '    Case Else
        '        Return Not dataGridViewWantsInputKey
        'End Select
        If key.KeyCode = Keys.Escape Then

        End If
        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

1 个答案:

答案 0 :(得分:1)

负责处理此行为的部分是EditingControlWantsInputKey。通过查看original code,很明显必须将此部分默认设置为false(=返回先前存储的值),但在您的代码中将其设置为true。这个想法只是为(“特殊”)键设置为true,这不应该引起值的删除;也就是说,你不需要在这里提到scape,只需要任何其他键(触发此函数),你不想激发回到前一个值的行为。

因此,解决方案:

Public Function EditingControlWantsInputKey(ByVal key As Keys, _
    ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
    Implements IDataGridViewEditingControl.EditingControlWantsInputKey

    Return False

End Function
相关问题