Mapping Datatable column to custom datagrid view column

Matt

Member
Joined
Apr 28, 2009
Messages
5
Programming Experience
5-10
I have a datatable that I am binding to a datagridview. I want to be able to add a column to the datatable that will bind to a custom datagridviewcolumn I have created called NumericUpDownColumn (which Inherits DataGridViewColumn).

I can actually add the column with no errors:
VB.NET:
f_dtLevels.Columns.Add(strName, GetType(NumericUpDownColumn))

But when I try and access a cell in the dataGridView I get a DataError event: 'System.Argument exception: Tyupe of value has a mismatch with column type Couldn't store <0> in Col1 Column. Expected type is NumericUpDownColumn.

By NumericUpDownColumn is belowfor reference.

VB.NET:
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 a CalendarCell")
            End If
            MyBase.CellTemplate = value
        End Set
    End Property

End Class



Public Class NumericUpDownCell
    Inherits DataGridViewTextBoxCell

    Public Sub New()
        ' Use the short date 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
        Me.Maximum = 9999
        Me.TextAlign = HorizontalAlignment.Right
    End Sub

    Public Property EditingControlFormattedValue() As Object Implements IDataGridViewEditingControl.EditingControlFormattedValue
        Get
            Return Me.Value.ToString("0")
        End Get

        Set(ByVal value As Object)
            If TypeOf value Is Decimal Then
                Me.Value = Decimal.Parse(value)
            End If
        End Set
    End Property

    Public Function GetEditingControlFormattedValue(ByVal context As DataGridViewDataErrorContexts) As Object Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
        Return Me.Value.ToString("0")
    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
        ' select the control contents
        Me.Select()
        Me.Select(0, Me.Value.ToString.Length)
    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
 
The column classes seems ok, but I don't recognize this:
f_dtLevels.Columns.Add(strName, GetType(NumericUpDownColumn))
DataGridViewColumnCollection only have these two Add methods: DataGridViewColumnCollection.Add Method (System.Windows.Forms)
Anyway, you don't need to code, you can add the column in Designer and set DataPropertyName corresponding to bound column name. If you have added data source to project you can simply select the bound column.
 
The column classes seems ok, but I don't recognize this:

DataGridViewColumnCollection only have these two Add methods: DataGridViewColumnCollection.Add Method (System.Windows.Forms)
Anyway, you don't need to code, you can add the column in Designer and set DataPropertyName corresponding to bound column name. If you have added data source to project you can simply select the bound column.

I am adding a column to the datatable which is bound to the datagridview. When the datagridview displays it I want it to be of the type NumericUpDownColumn, but I don't know what to add it as in the datatable so that it knows to convert it to this type as my NumericUpDownColumn Inherits a DataGridViewColumn (no mention of a datatable mapping)
 
Oh that, you have to set the correct data type for column, for example Integer. Then map that column to DGV column like I explained. The DataTable (or its column) has no knowledge of the DGV, it's the other way around.
If you're using auto-generated DGV columns you still have to add NumericUpDownColumn manually first and set the mapping name, the others will generate as before.
 
Back
Top