如何将典型的 NumericUpDown 属性分配给自定义基于 NumericUpDown 的控件?

How to assign typical NumericUpDown properties to custom NumericUpDown based control?

我正在尝试创建一个 DataGridViewColumn 来继承典型 NumericUpDown 控件的所有属性。我在 Whosebug () and a MSDN article here (https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-host-controls-in-windows-forms-datagridview-cells?view=netframeworkdesktop-4.8&redirectedfrom=MSDN#code-snippet-1) 上找到了答案。

文章中的代码运行良好,但是...我无法为控件分配最大值和最小值(两者都停留在“默认”最小值 0 和最大值 100)。

我尝试从 SO 答案中添加代码(通过添加最小值和最大值字段)但这样做会将两者都锁定为 0 且无法更改。

问题简而言之:我如何添加必要的属性以允许这项工作。

自定义控件有问题:

Public Class NumericUpDownColumn
    Inherits DataGridViewColumn

    Public Sub New()
        MyBase.New(New NumericUpDownCell())
    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 Not (value Is Nothing) AndAlso Not value.GetType().IsAssignableFrom(GetType(NumericUpDownCell)) Then
                Throw New InvalidCastException("Must be an Integer")
            End If
            MyBase.CellTemplate = value
        End Set
    End Property
End Class


Public Class NumericUpDownCell
    Inherits DataGridViewTextBoxCell

    Public Sub New()
        ' Number Format
        Me.Style.Format = "0"
    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 NumericUpDownEditingControl = CType(DataGridView.EditingControl, NumericUpDownEditingControl)
        ctl.Value = CType(Me.Value, Decimal)
    End Sub

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

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

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


Class NumericUpDownEditingControl
    Inherits NumericUpDown
    Implements IDataGridViewEditingControl

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

    Public Sub New()
        Me.DecimalPlaces = 0
    End Sub

    Public Property EditingControlFormattedValue() As Object Implements IDataGridViewEditingControl.EditingControlFormattedValue
        Get
            Return Me.Value.ToString("#")
        End Get
        Set(ByVal value As Object)
            If TypeOf value Is Decimal Then
                Me.Value = Decimal.Parse(value.ToString)
            End If
        End Set
    End Property

    Public Function GetEditingControlFormattedValue(ByVal context As DataGridViewDataErrorContexts) As Object Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
        Return Me.Value.ToString("#")
    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 False
        End Select
    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

再仔细研究一下,我发现我可以像这样为最大和最小字段赋值:

        ' Set the value of the editing control to the current cell value.
        MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
        Dim ctl As NumericUpDownEditingControl = CType(DataGridView.EditingControl, NumericUpDownEditingControl)
        ctl.Value = CType(Me.Value, Decimal)
        ctl.Maximum = 180
        ctl.Minimum = -1
    End Sub

但我似乎无法通过构造函数上的 .Maximum.Minimum 的常用方法传递到该字段。任何 tips/advice?

这是一个简单的修复,而且很容易被忽视。

在您的 NumericUpDownCell class 中,您需要覆盖 Clone 方法以包含新的 MinimumMaximum 属性,例如:

首先,添加新属性 NumericUpDownCell class 然后覆盖克隆函数

Public Class NumericUpDownCell
    Inherits DataGridViewTextBoxCell
    ...
    Public Property Minimum() As Integer
    Public Property Maximum() As Integer
    ...

    Public Overrides Function Clone() As Object
        Dim retVal As NumericUpDownCell = CType(MyBase.Clone, NumericUpDownCell)

        retVal.Minimum = Me.Minimum
        retVal.Maximum = Me.Maximum

        Return retVal
    End Function
End Class

其次,在 NumericUpDownCell classes InitializeEditingControl 方法中,添加两行:

ctl.Minimum = Me.Minimum
ctl.Maximum = Me.Maximum

设置新列时,获取 CellTemplate 以设置新属性,按照:

Dim upDownColumn As New NumericUpDownColumn
Dim cellTemplate As NumericUpDownCell = CType(upDownColumn .CellTemplate, NumericUpDownCell)
cellTemplate.Minimum = 10
cellTemplate.Maximum = 15

或者,根据您对通过构造函数进行设置的偏好,按照

NumericUpdDownColumn class 添加一个新的构造函数
Public Sub New(minValue As Integer, maxValue As Integer)
    MyBase.New(New NumericUpDownCell())

    Dim template As NumericUpDownCell = CType(CellTemplate, NumericUpDownCell)
    template.Minimum = minValue
    template.Maximum = maxValue
End Sub

然后像这样使用它:

Dim upDownColumn As New NumericUpDownColumn(100, 150)
Dim cellTemplate As NumericUpDownCell = CType(upDownColumn.CellTemplate, NumericUpDownCell)

DataGridView1.Columns.Add(upDownColumn)