How to assign typical NumericUpDown properties to custom NumericUpDown based control? - vb.net

I'm trying to make a DataGridViewColumn that inherits all of the properties of a typical NumericUpDown control. I found an answer here on StackOverflow (https://stackoverflow.com/a/55788490/692250) and a MSDN article here (https://learn.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).
The code from the article works well, but... I cannot assign a Maximum nor Minimum value to the control (both are stuck at the "default" Minimum of 0 and Maximum of 100).
I tried to add in code from the SO answer (by adding in a Min and Max field) but doing so locks both in to 0 and unable to change.
The question in short: how do I add the necessary properties to allow to this work.
The custom control is question:
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
Focusing on it a bit more, I found that I can assign values to the Maximum and Minimum fields as so:
' 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
But I cannot seem to pass to this field via the usual means of .Maximum or .Minimum on the constructor. Any tips/advice?

This is an easy fix and very easy to overlook.
In your NumericUpDownCell class you need to override the Clone method to include the new Minimum and Maximum properties, for example:
First, add the new properties the NumericUpDownCell class and then override the Clone function
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
Second, inside the NumericUpDownCell classes InitializeEditingControl method, add the two lines:
ctl.Minimum = Me.Minimum
ctl.Maximum = Me.Maximum
When you setup the new column, get the CellTemplate to set the new properties, as per:
Dim upDownColumn As New NumericUpDownColumn
Dim cellTemplate As NumericUpDownCell = CType(upDownColumn .CellTemplate, NumericUpDownCell)
cellTemplate.Minimum = 10
cellTemplate.Maximum = 15
Or, following you preference to setup via the constructor, add a new constructor to the NumericUpdDownColumn class as per
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
and then use it like:
Dim upDownColumn As New NumericUpDownColumn(100, 150)
Dim cellTemplate As NumericUpDownCell = CType(upDownColumn.CellTemplate, NumericUpDownCell)
DataGridView1.Columns.Add(upDownColumn)

Related

DataGridView ComboBox column that will accept any text - Dropdown populated by Column

https://stackoverflow.com/a/59545459/20359642
Hi, on the article above, I grabbed the code snippet from Sidupac. This class works but it has a different drop down list for each row. I want each row to be populated with the same list. I am not very good at classes, can someone please help? My goal is to be able to add a column to a DataGridView that will act as a combobox but also accepts manual text input as well.
Public Class DataGridViewDropDownComboBoxColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New DataGridViewDropDownComboBoxCell)
End Sub
Public Property DropDownStyle As ComboBoxStyle
Public Property DataSource As Object
Public Property ValueMember As Object
Public Property DisplayMember As Object
Public Overrides Property CellTemplate As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set
' Ensure that the cell used for the template is a DataGridViewDropDownComboBoxCell.
If ((Not (Value) Is Nothing) AndAlso Not Value.GetType.IsAssignableFrom(GetType(DataGridViewDropDownComboBoxCell))) Then
Throw New InvalidCastException("Must be a DropDownCell")
End If
MyBase.CellTemplate = Value
End Set
End Property
End Class
Public Class DataGridViewDropDownComboBoxCell
Inherits DataGridViewTextBoxCell
Public Sub New()
MyBase.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 DataGridViewDropDownComboBoxEditingControl = CType(DataGridView.EditingControl, DataGridViewDropDownComboBoxEditingControl)
' Use the default row value when Value property is null.
If (Me.Value Is Nothing) Or IsDBNull(Me.Value) Then
ctl.Text = CType(Me.DefaultNewRowValue, String)
Else
ctl.Text = CType(Me.Value, String)
End If
'ctl.BringToFront()
'ctl.Focus()
'ctl.DroppedDown = True
End Sub
Public Overrides ReadOnly Property EditType As Type
Get
' Return the type of the editing control that DataGridViewDropDownComboBoxCell uses.
Return GetType(DataGridViewDropDownComboBoxEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType As Type
Get
' Return the type of the value that DataGridViewDropDownComboBoxCell 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 ""
End Get
End Property
End Class
Class DataGridViewDropDownComboBoxEditingControl
Inherits ComboBox
Implements IDataGridViewEditingControl
Private dataGridView As DataGridView
Private valueChanged As Boolean = False
Private rowIndex As Integer
Public Sub New()
MyBase.New
End Sub
Public Shadows Property DropDownStyle() As ComboBoxStyle
Get
Return MyBase.DropDownStyle
End Get
Set(ByVal value As ComboBoxStyle)
If value = ComboBoxStyle.Simple Then
'Throw New NotSupportedException("ComboBoxStyle.Simple not supported")
value = ComboBoxStyle.DropDown
End If
MyBase.DropDownStyle = value
End Set
End Property
' Implements the IDataGridViewEditingControl.EditingControlFormattedValue
' property.
Public Property EditingControlFormattedValue As Object Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Text
End Get
Set
If (TypeOf Value Is String) Then
Me.Text = CStr(Value)
End If
End Set
End Property
' Implements the
' IDataGridViewEditingControl.GetEditingControlFormattedValue method.
Public Function GetEditingControlFormattedValue(ByVal context As DataGridViewDataErrorContexts) As Object Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.EditingControlFormattedValue
End Function
' Implements the
' IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As DataGridViewCellStyle) Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
Me.ForeColor = dataGridViewCellStyle.ForeColor
Me.BackColor = dataGridViewCellStyle.BackColor
End Sub
' Implements the IDataGridViewEditingControl.EditingControlRowIndex
' property.
Public Property EditingControlRowIndex As Integer Implements IDataGridViewEditingControl.EditingControlRowIndex
Get
Return Me.rowIndex
End Get
Set
Me.rowIndex = Value
End Set
End Property
' Implements the IDataGridViewEditingControl.EditingControlWantsInputKey
' method.
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, Keys.F4
Return True
Case Else
Return Not dataGridViewWantsInputKey
End Select
End Function
' Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit
' method.
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
Dim col As DataGridViewDropDownComboBoxColumn = CType(dataGridView.Columns(dataGridView.CurrentCell.ColumnIndex), DataGridViewDropDownComboBoxColumn)
If (col Is Nothing) Then
Throw New InvalidCastException("Must be in a DropDownComboBoxColumn")
End If
DropDownStyle = col.DropDownStyle
Items.Clear()
If IsDBNull(dataGridView.CurrentCell.Value) Then
Text = ""
Else
Text = CType(dataGridView.CurrentCell.Value, String)
End If
Items.Add(Text)
Dim dt As DataTable = New DataTable
Dim ct As Integer = 0, cx As Integer = 0
Try
dt = DirectCast(col.DataSource, DataTable)
If Not col.DisplayMember Is Nothing Then
For Each c As DataColumn In dt.Columns
If c.ColumnName Is col.DisplayMember Then
cx = ct
End If
ct += 1
Next
End If
For Each r As DataRow In dt.Rows
If Not col.DisplayMember Is Nothing Then
If Not Items.Contains(r(cx)) Then Items.Add(r(cx))
Else
If dt.Columns.Count = 1 Then
If Not Items.Contains(r(0)) Then Items.Add(r(0))
Else
If Not Items.Contains(r(dt.Columns.Count - 1)) Then Items.Add(r(dt.Columns.Count - 1))
End If
End If
Next
Catch ex As Exception
End Try
'DropDownStyle = col.DropDownStyle
'ValueMember = col.ValueMember
'DisplayMember = col.DisplayMember
'DataSource = col.DataSource
' (If you don't explicitly set the Text then the current value is
' always replaced with one from the drop-down list when edit begins.)
'If IsDBNull(dataGridView.CurrentCell.Value) Then
' Text = ""
'Else
' Text = CType(dataGridView.CurrentCell.Value, String)
'End If
End Sub
' Implements the IDataGridViewEditingControl
' .RepositionEditingControlOnValueChange property.
Public ReadOnly Property RepositionEditingControlOnValueChange As Boolean Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
' Implements the IDataGridViewEditingControl
' .EditingControlDataGridView property.
Public Property EditingControlDataGridView As DataGridView Implements IDataGridViewEditingControl.EditingControlDataGridView
Get
Return Me.dataGridView
End Get
Set
Me.dataGridView = Value
End Set
End Property
' Implements the IDataGridViewEditingControl
' .EditingControlValueChanged property.
Public Property EditingControlValueChanged As Boolean Implements IDataGridViewEditingControl.EditingControlValueChanged
Get
Return Me.valueChanged
End Get
Set
Me.valueChanged = Value
End Set
End Property
' Implements the IDataGridViewEditingControl
' .EditingPanelCursor property.
Public ReadOnly Property EditingPanelCursor As Cursor Implements IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property
Protected Overrides Sub OnTextChanged(ByVal eventargs As EventArgs)
' Notify the DataGridView that the contents of the cell
' have changed.
Me.valueChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnTextChanged(eventargs)
End Sub
Protected Overrides Sub OnSelectedIndexChanged(ByVal e As EventArgs)
' Notify the DataGridView that the contents of the cell
' have changed.
Me.valueChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnSelectedIndexChanged(e)
End Sub
End Class
I've tried messing around with the class myself but I just cant seem to figure it out.
I actually figured it out. The DataSource was not populating the dropdowns because I was not giving it a DataTable to reference. I was giving it a string array. I just need to alter the class a bit to handle different types of inputs for the DataSource.
For example, I changed the code inside of the try statement in the PrepareEditingControlForEdit procedure to the code below:
If TypeOf col.DataSource Is String Then
Items.Add(col.DataSource)
ElseIf TypeOf col.DataSource Is String() Then
For Each obj As Object In DirectCast(col.DataSource, String())
Items.Add(obj)
Next
ElseIf TypeOf col.DataSource Is List(Of String) Then
For Each obj As String In DirectCast(col.DataSource, List(Of String))
Items.Add(obj)
Next
ElseIf TypeOf col.DataSource Is List(Of Object) Then
For Each obj As String In DirectCast(col.DataSource, List(Of Object))
Items.Add(obj)
Next
ElseIf TypeOf col.DataSource Is DataTable Then
dt = DirectCast(col.DataSource, DataTable)
If Not col.DisplayMember Is Nothing Then
For Each c As DataColumn In dt.Columns
If c.ColumnName Is col.DisplayMember Then
cx = ct
End If
ct += 1
Next
End If
For Each r As DataRow In dt.Rows
If Not col.DisplayMember Is Nothing Then
If Not Items.Contains(r(cx)) Then Items.Add(r(cx))
Else
If dt.Columns.Count = 1 Then
If Not Items.Contains(r(0)) Then Items.Add(r(0))
Else
If Not Items.Contains(r(dt.Columns.Count - 1)) Then Items.Add(r(dt.Columns.Count - 1))
End If
End If
Next
End If

How to hide expand button in a propertygrid in Windows Forms

I have written my on editor for a property in a propertyGrid. Everything works as expected, but for best user experience i want to hide the expand button on the propertygrid for this property. Can someone tell me how to do that?
I am using a custom typeconverter
Public Class PropertyLanguageSetupEditor
Inherits UITypeEditor
Public Overrides Function GetEditStyle(context As ITypeDescriptorContext) As UITypeEditorEditStyle
Return UITypeEditorEditStyle.Modal
End Function
Public Overrides Function EditValue(context As ITypeDescriptorContext, provider As IServiceProvider, value As Object) As Object
Try
Dim svc As IWindowsFormsEditorService = CType(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
Dim settings As LanguageSettings = value
Dim oldSettings As LanguageSettings = CType(value, LanguageSettings).Clone
If Not svc Is Nothing And Not settings Is Nothing Then
Dim form As New PropertyLanguageSetupWindow(settings)
If svc.ShowDialog(form) = DialogResult.OK Then
value = form.Data
Else
value = oldSettings
End If
End If
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
Return MyBase.EditValue(context, provider, value)
End Function
End Class
And this is de property which uses the typeConverter
<DisplayName("Properties Translation Settings"), Editor(GetType(PropertyLanguageSetupEditor), GetType(System.Drawing.Design.UITypeEditor)), TypeConverter(GetType(BrowsableTypeConverter)),
Description("Settings for the output text"), BrowsableTypeConverter.BrowsableLabelStyleAttribute(BrowsableTypeConverter.LabelStyle.lsEllipsis),
Category("10 - DXF Export"), Browsable(True)>
Public Property TranslationSettings As LanguageSettings = New LanguageSettings
My BrowsAbleTypeConverter
Public Class BrowsableTypeConverter
Inherits ExpandableObjectConverter
Public Enum LabelStyle
lsNormal
lsTypeName
lsEllipsis
lsText
End Enum
Public Class BrowsableLabelStyleAttribute
Inherits System.Attribute
Private eLabelStyle As LabelStyle = LabelStyle.lsEllipsis
Public Sub New(ByVal LabelStyle As LabelStyle)
eLabelStyle = LabelStyle
End Sub
Public Property LabelStyle() As LabelStyle
Get
Return eLabelStyle
End Get
Set(ByVal value As LabelStyle)
eLabelStyle = value
End Set
End Property
End Class
Public Class BrowsableLabelTextAttribute
Inherits System.Attribute
Private strText As String = ""
Public Sub New(ByVal value As String)
strText = value
End Sub
Public Property Text() As String
Get
Return strText
End Get
Set(ByVal value As String)
strText = value
End Set
End Property
End Class
Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
Return True
End Function
Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
Dim Style As BrowsableLabelStyleAttribute = context.PropertyDescriptor.Attributes(GetType(BrowsableLabelStyleAttribute))
If Not Style Is Nothing Then
Select Case Style.LabelStyle
Case LabelStyle.lsNormal
Return MyBase.ConvertTo(context, culture, value, destinationType)
Case LabelStyle.lsTypeName
Return "(" & value.GetType.Name & ")"
Case LabelStyle.lsEllipsis
Return "(...)"
Case LabelStyle.lsText
Dim text As BrowsableLabelTextAttribute = context.PropertyDescriptor.Attributes(GetType(BrowsableLabelTextAttribute))
If text IsNot Nothing Then
Return text.Text
End If
End Select
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
Your TypeConverter derives from ExpandableObjectConverter, which means subproperties will be visible because of its GetPropertiesSupported method returning true.
In your TypeConverter, you simply need to override GetPropertiesSupported and return false.

DataGridView DateTimePicker Column - add Long Format support (Date and the Time)

I'm trying to make gridview Datetimepicker column and i succeeded,
but i have a little problem that when the user edit the date in the gridview
the date appear in short "11/9/16" but what i want is the date and the time together"11/9/16 2:34:45 AM"
This is the code I use:
CalendarColumn:
Imports System
Imports System.Windows.Forms
Public Class CalendarColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New CalendarCell())
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(CalendarCell)) _
Then
Throw New InvalidCastException("Must be a CalendarCell")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
CalendarCell:
Public Class CalendarCell
Inherits DataGridViewTextBoxCell
Public Sub New()
' Use the short date format.
'Me.Style.Format = "d"
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 CalendarEditingControl = _
CType(DataGridView.EditingControl, CalendarEditingControl)
' Use the default row value when Value property is null.
If (Me.Value Is Nothing) Then
ctl.Value = CType(Me.DefaultNewRowValue, DateTime)
Else
ctl.Value = CType(Me.Value, DateTime)
End If
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing control that CalendarCell uses.
Return GetType(CalendarEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that CalendarCell 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
CalendarEditingControl:
Class CalendarEditingControl
Inherits DateTimePicker
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
Me.Format = DateTimePickerFormat.Long
'Me.CustomFormat = "'Today is:' hh:mm:ss dddd MMMM dd, yyyy"
End Sub
Public Property EditingControlFormattedValue() As Object _
Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Value.ToShortDateString()
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 = DateTime.Parse(CStr(value))
Catch
' In the case of an exception, just use the default
' value so we're not left with a null value.
Me.Value = DateTime.Now
End Try
End Set
End Property
Public Function GetEditingControlFormattedValue(ByVal context _
As DataGridViewDataErrorContexts) As Object _
Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Value.ToShortDateString()
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
And this code for add column :
Dim col As New CalendarColumn() With {.HeaderText = "Date time"}
DataGridView1.Columns.Insert(5, col)
source Code
How can I make it long with the time.
To show a date and time in custom format, you should assign format to Format property of DefaultCellStyle. The CustomFormat property of DateTimePicker is useful for editing format but for displaying data in cell you should use column.DefaultCellStyle.Format.
For example to show date and time like 2016/09/15 10:31:04 PM you should use yyyy/MM/dd h:mm:ss tt as format.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt = New DataTable()
dt.Columns.Add("Date", GetType(DateTime))
dt.Rows.Add(DateTime.Now)
dt.Rows.Add(DateTime.Now)
Dim column = New DataGridViewTextBoxColumn()
column.DefaultCellStyle.Format = "yyyy/MM/dd h:mm:ss tt"
column.DataPropertyName = "Date"
Me.DataGridView1.Columns.Add(column)
Me.DataGridView1.DataSource = dt
End Sub
For more information about custom date formats see:
Custom Date and Time Format Strings
DataGridView DateTimePicker Column
Here is the full source code of date time picker column with some fixes. The source has been taken from MSDN and I just made some small changes and a small fix. The changes has been made to support Time and long format. Also the fix has been done to prevent exception when the cell value is DBNull.Value:
Imports System
Imports System.Windows.Forms
Public Class CalendarColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New CalendarCell())
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(CalendarCell)) _
Then
Throw New InvalidCastException("Must be a CalendarCell")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
Public Class CalendarCell
Inherits DataGridViewTextBoxCell
Public Sub New()
' Use the short date format.
Me.Style.Format = "yyyy/MM/dd h:mm:ss tt"
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 CalendarEditingControl = _
CType(DataGridView.EditingControl, CalendarEditingControl)
' Use the default row value when Value property is null.
If (Me.Value Is Nothing OrElse IsDBNull(Me.Value)) Then
ctl.Value = CType(Me.DefaultNewRowValue, DateTime)
Else
ctl.Value = CType(Me.Value, DateTime)
End If
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing control that CalendarCell uses.
Return GetType(CalendarEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that CalendarCell 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 CalendarEditingControl
Inherits DateTimePicker
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
Me.Format = DateTimePickerFormat.Custom
Me.CustomFormat = "yyyy/MM/dd h:mm:ss tt"
End Sub
Public Property EditingControlFormattedValue() As Object _
Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Value.ToString("yyyy/MM/dd h:mm:ss tt")
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 = DateTime.Parse(CStr(value))
Catch
' In the case of an exception, just use the default
' value so we're not left with a null value.
Me.Value = DateTime.Now
End Try
End Set
End Property
Public Function GetEditingControlFormattedValue(ByVal context _
As DataGridViewDataErrorContexts) As Object _
Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Value.ToString("yyyy/MM/dd h:mm:ss tt")
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
' 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
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
And here is the test code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt = New DataTable()
dt.Columns.Add("Date", GetType(DateTime))
dt.Rows.Add(DateTime.Now)
dt.Rows.Add(DateTime.Now)
Dim column = New CalendarColumn()
column.DataPropertyName = "Date"
Me.DataGridView1.Columns.Add(column)
Me.DataGridView1.DataSource = dt
End Sub

DateTimePicker in Datagrid - clear It's value?

I have used code from MSDN site that adds DateTimePicker in Datagrid. I have shorten It a bit, so now DateTimepicker doesn't show It's default value and enters in column only when user selects value from It. Now I want to add code for clearing DTP with Delete or Backspace key. I know DTP can't have null value, but I've managed to do It with other DTP's (which are not inside Datagridview) like this:
Private Sub DataGridView1_KeyDown(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyDown
If e.KeyCode = Keys.Delete Or e.KeyCode = Keys.Back Then
DTPtest.format = DTPtest.custom
DTPtest.Format = DateTimePickerFormat.Custom
DTPtest.CustomFormat = " "
End If
End Sub
Code for hosting DateTimePicker in Datagrid is above my knowledge, and I don't know where I should create something similar that will work same. ANY HELP MUCH APPRECIATED !!!
Here is my code for hosting DaTeTimePicker (from MSDN as mentioned):
Public Class CalendarColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New CalendarCell())
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(CalendarCell)) _
Then
Throw New InvalidCastException("Must be a CalendarCell")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
Public Class CalendarCell
Inherits DataGridViewTextBoxCell
Public Sub New()
' Use the short date format.
Me.Style.Format = "d"
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 CalendarEditingControl =
CType(DataGridView.EditingControl, CalendarEditingControl)
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing control that CalendarCell uses.
Return GetType(CalendarEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that CalendarCell contains.
Return GetType(DateTime)
End Get
End Property
End Class
Class CalendarEditingControl
Inherits DateTimePicker
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.ToShortDateString()
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 = DateTime.Parse(CStr(value))
Catch
' In the case of an exception, just use the default
' value so we're not left with a null value.
Me.Value = DateTime.Now
End Try
End Set
End Property
Public Function GetEditingControlFormattedValue(ByVal context _
As DataGridViewDataErrorContexts) As Object _
Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Value.ToShortDateString()
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
' 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
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
Solved, pretty simple actually:
Private Sub DataGridView1_KeyDown(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyDown
If e.KeyCode = Keys.Delete Or e.KeyCode = Keys.Back Then
DataGridView1.CurrentCell.Value = Nothing
End If
End Sub
Only thing that It's not same is that you have to go out of cell, and then return into It for delete.

custom datagridview column Control will not accept a period (.)

I cannot get a control I found online to accept a period(.). I need to be able to enter numeric values with decimal places. I wanted to use the numericupdown control in a datagridview cell so I can use the up-down arrows for adjusting values.
This control implments the NumericUpDown control as the editing control on a datagridview column. I found it online (don't remember where), and ti was based on a similar custom datagridview column based in a calendar control.
I made a few modifications to it so I could set the maximum, minimum, decimalplaces and imcrement properties.
However, even when decimal places is set to 2 and increment is .1, when I'm typing a value the control will not accept a period.
Below is the code, which includes the classes for the column, cell, and editing control. Please help. I have no clue what the problem is.
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
Private _Maximum As Decimal = 100
Private _Minimum As Decimal = 0
Private _Increment As Decimal = 0.1
Private _DecimalPlaces As Integer = 2
Public Property DecimalPlaces() As Integer
Get
Return _DecimalPlaces
End Get
Set(ByVal value As Integer)
If _DecimalPlaces = value Then
Return
End If
_DecimalPlaces = value
End Set
End Property
Public Property Maximum() As Decimal
Get
Return _Maximum
End Get
Set(ByVal value As Decimal)
_Maximum = value
End Set
End Property
_
Public Property Minimum() As Decimal
Get
Return _Minimum
End Get
Set(ByVal value As Decimal)
_Minimum = value
End Set
End Property
_
Public Property Increment() As Decimal
Get
Return _Increment
End Get
Set(ByVal value As Decimal)
_Increment = value
End Set
End Property
End Class
Public Class NumericUpDownCell
Inherits DataGridViewTextBoxCell
Public Sub New()
' Use the short date format.
Me.Style.Format = "N2"
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)
RemoveHandler ctl.Enter, AddressOf Me.OnNumericEnter
AddHandler ctl.Enter, AddressOf Me.OnNumericEnter
ctl.Maximum = CType(Me.DataGridView.Columns(Me.ColumnIndex), NumericUpDownColumn).Maximum
ctl.Minimum = CType(Me.DataGridView.Columns(Me.ColumnIndex), NumericUpDownColumn).Minimum
ctl.Increment = CType(Me.DataGridView.Columns(Me.ColumnIndex), NumericUpDownColumn).Increment
ctl.DecimalPlaces = CType(Me.DataGridView.Columns(Me.ColumnIndex), NumericUpDownColumn).DecimalPlaces
ctl.ThousandsSeparator = True
ctl.Value = CType(Me.Value, Decimal)
End Sub
'''
''' Handle on enter event of numeric
'''
'''
'''
'''
Private Sub OnNumericEnter(ByVal sender As Object, ByVal e As EventArgs)
Dim control As NumericUpDownEditingControl = CType(sender, NumericUpDownEditingControl)
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 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()
End Sub
Public Property EditingControlFormattedValue() As Object _
Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Value.ToString("N2")
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("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
Case Keys.Up, Keys.Down
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
I used an old programmers trick to solve this. I just downloaded the sample code from the post Plutonix referenced and just added the DLL it came with to my project. This work fine and saved me a lot of trouble I wasn't looking for.