Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > Datagridview restrict to numeric input
 

Datagridview restrict to numeric input

VS2005 CTP July
Am I the only developer on the planet that needs to restrict a Datagridview column to numeric input with Minimum, Maximum and decimal places? I have searched high and low.  Does anyone have working code that lets you use a NumericUpDown control as a cell in a DataGridView control?

This is such a BASIC function for a grid control that I just can't believe that Microsoft does not have it as part of the datagridview control columns.

I have tried converting the CalendarCell class in MSDN Magazine/ April 2005 Cutting Edge but I cant get the column to allow input of the decimal point and the NumericUpDown control will only display when you click on it. It will not display in all cells of the column at one time.



 


Imports System
Imports System.Windows.Forms

#Region "NumericUpDownColumn Class"
Public Class NumericUpDownColumn
    Inherits DataGridViewColumn

    Public Sub New()
        MyBase.New(New NumericUpDownCell())
    End Sub 'New

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

End Class
#End Region

#Region "NumericUpDownCell Class"
Public Class NumericUpDownCell
    Inherits DataGridViewTextBoxCell


    Public Sub New()
    End Sub


    Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As DataGridViewCellStyle)
        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 NumericUpDownCell uses.
            Return GetType(NumericUpDownEditingControl)
        End Get
    End Property

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

    Public Overrides ReadOnly Property DefaultNewRowValue() As Object
        Get

            Return 0D
        End Get
    End Property
End Class
#End Region

#Region "NumericUpDownEditingControl 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 Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle) Implements System.Windows.Forms.IDataGridViewEditingControl.ApplyCellStyleToEditingControl
        Me.Font = dataGridViewCellStyle.Font
    End Sub

    Public Property EditingControlDataGridView() As System.Windows.Forms.DataGridView Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlDataGridView
        Get
            Return Me.dataGridViewControl
        End Get
        Set(ByVal value As System.Windows.Forms.DataGridView)
            Me.dataGridViewControl = value
        End Set
    End Property

    Public Property EditingControlFormattedValue() As Object Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlFormattedValue
        Get
            Return Me.Value.ToString
        End Get
        Set(ByVal value As Object)
            If TypeOf value Is [String] Then
                Me.Value = CType(value, Decimal)
            End If
        End Set
    End Property

    Public Property EditingControlRowIndex() As Integer Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlRowIndex
        Get
            Return rowIndexNum
        End Get
        Set(ByVal value As Integer)
            rowIndexNum = value
        End Set
    End Property

    Public Property EditingControlValueChanged() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlValueChanged
        Get
            Return valueIsChanged
        End Get
        Set(ByVal value As Boolean)
            valueIsChanged = value
        End Set
    End Property

    Public Function EditingControlWantsInputKey(ByVal key As System.Windows.Forms.Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlWantsInputKey
        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 ReadOnly Property EditingPanelCursor() As System.Windows.Forms.Cursor Implements System.Windows.Forms.IDataGridViewEditingControl.EditingPanelCursor
        Get
            Return MyBase.Cursor
        End Get
    End Property

    Public Function GetEditingControlFormattedValue(ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object Implements System.Windows.Forms.IDataGridViewEditingControl.GetEditingControlFormattedValue
        Return Me.Value.ToString
    End Function

    Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements System.Windows.Forms.IDataGridViewEditingControl.PrepareEditingControlForEdit

    End Sub

    Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.RepositionEditingControlOnValueChange
        Get
            Return False
        End Get
    End Property
End Class

#End Region






DrMicrochip  Monday, August 29, 2005 8:44 PM
Unfortunately the DataGridView does not support masked input out of the box. You may want to create a custom DataGridViewTextBoxCell which uses the MaskedTextox control as its editing control (instead of the regular TextBox control). You would have to create a DataGridViewMaskedTextBoxCell & a DataGridViewMaskedTextBoxEditingControl class (and optionally a DataGridViewMaskedTextBoxColumn class).

If you want your custom cell to look different than a regular textbox cell when it's not edited, you'll have to custom paint it.

-Regis
DataGridView Developer
Microsoft
this post is provided "as-is"
Regis Brid  Monday, August 29, 2005 10:47 PM
Hi, I have experienced identical problems using the code example in the White Paper on DGV custom columns. I notice that if you use this code in the C# IDE it works just fine. This looks like it might be a bug with the VB.net version of the DGV. I just wondered if you had made any progress?

Thanks for your time.

Regards

Steve
Southport
UK
Steve_Ainsdale  Wednesday, September 27, 2006 3:05 PM
Unfortunately the DataGridView does not support masked input out of the box. You may want to create a custom DataGridViewTextBoxCell which uses the MaskedTextox control as its editing control (instead of the regular TextBox control). You would have to create a DataGridViewMaskedTextBoxCell & a DataGridViewMaskedTextBoxEditingControl class (and optionally a DataGridViewMaskedTextBoxColumn class).

If you want your custom cell to look different than a regular textbox cell when it's not edited, you'll have to custom paint it.

-Regis
DataGridView Developer
Microsoft
this post is provided "as-is"
Regis Brid  Monday, August 29, 2005 10:47 PM
You completely ignored the fact that I am trying to use the NumericUpDown in a cell. Are you saying that the NUD control cannot be used in a cell??

It is also interesting that a "Link Column" is more important from Microsofts' point of view than a numeric input column. I would venture a guess that more developers would use a grid control for numeric input than clicking on links. I guess editing the unit cost on a line item of an order is no longer important.
DrMicrochip  Tuesday, August 30, 2005 12:42 AM
I agree that a numericupdown control would be very useful with the DGV.  This may be a little (or a lot) hoaky, but what if you created two small Button cells to the right of your text cell and had one increment up and the other decrement the value in the textbox.  You would need to have the EndEdit event make sure it's numeric, however.
Adam Plocher  Tuesday, August 30, 2005 6:55 PM
Hi, I have experienced identical problems using the code example in the White Paper on DGV custom columns. I notice that if you use this code in the C# IDE it works just fine. This looks like it might be a bug with the VB.net version of the DGV. I just wondered if you had made any progress?

Thanks for your time.

Regards

Steve
Southport
UK
Steve_Ainsdale  Wednesday, September 27, 2006 3:05 PM
Add this to ur code

Protected Overloads Overrides Sub OnValueChanged(ByVal e As EventArgs)
' Notify the DataGridView that the contents of the cell
' have changed.
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnValueChanged(e)

End Sub
amostafa84  Sunday, December 21, 2008 2:36 PM
Hi dudes.

I "stole" the code posted in this page and I've adapted it to create a DataGridViewMaskedTextBox Column and Cell.

There are only one restriction: you must "mask" the cell when the row is created. You cannot add a column mask, for example (I think it can be adapted to automatically add the masks but I haven't figured it out yet).

Thanks very much to DrMicrochip and amostafa84 who posted the code that helped me to do this.

This is the code when a user adds the row:

        private void dataGridView1_UserAddedRow(Object sender, DataGridViewRowEventArgs e)
        {
            DataGridViewMaskedTextBoxCell dmtxt = (DataGridViewMaskedTextBoxCell)dataGridView1[0, e.Row.Index];

            dmtxt.CellMask = "00.00";
        }

And this is the class code:

    public class DataGridViewMaskedTextBoxCell : DataGridViewTextBoxCell
    {        
        public DataGridViewMaskedTextBoxCell()
            : base()
        {            
        }

        private String Mask;

        public String CellMask
        {
            get { return Mask; }
            set {

                Mask = value;

                DataGridViewMaskedTextBoxEditingControl dgvmtbex = (DataGridViewMaskedTextBoxEditingControl)DataGridView.EditingControl;

                if (value != null)
                    dgvmtbex.Mask = value;
                else
                    dgvmtbex.Mask = String.Empty;
                }
        }

        public override void InitializeEditingControl(Int32 rowIndex, Object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
        {
            base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);

            DataGridViewMaskedTextBoxEditingControl dgvmtbex = (DataGridViewMaskedTextBoxEditingControl)DataGridView.EditingControl;
            
            if (Mask != null)
                dgvmtbex.Mask = Mask;

            dgvmtbex.Text = this.Value.ToString();            
        }

        public override Type EditType
        {
            get
            {
                return typeof(DataGridViewMaskedTextBoxEditingControl);
            }
        }

        public override Type ValueType
        {
            get
            {
                return typeof(String);
            }
        }

        public override object DefaultNewRowValue
        {
            get
            {
                return String.Empty;
            }
        }             
    }

    public class DataGridViewMaskedTextBoxEditingControl : MaskedTextBox, IDataGridViewEditingControl
    {

        private DataGridView dataGridViewControl = null;
        private Boolean valueIsChanged = false;
        private Int32 rowIndexNum;

        #region IDataGridViewEditingControl Members

        public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
        {
            this.Font = dataGridViewCellStyle.Font;
        }

        public DataGridView EditingControlDataGridView
        {
            get
            {
                return this.dataGridViewControl;
            }
            set
            {
                this.dataGridViewControl = value;
            }
        }

        public object EditingControlFormattedValue
        {
            get
            {
                return this.Text;
            }
            set
            {
                this.Text = value.ToString();
            }
        }

        public int EditingControlRowIndex
        {
            get
            {
                return rowIndexNum;
            }
            set
            {
                rowIndexNum = value;
            }
        }

        public bool EditingControlValueChanged
        {
            get
            {
                return valueIsChanged;
            }
            set
            {
                valueIsChanged = value;
            }
        }

        public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
        {
            return true;
        }

        public Cursor EditingPanelCursor
        {
            get { return base.Cursor; }
        }

        public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
        {
            return this.Text;
        }

        public void PrepareEditingControlForEdit(bool selectAll)
        {
            //do nothing
        }

        public bool RepositionEditingControlOnValueChange
        {
            get { return false; }
        }

        protected override void OnTextChanged(EventArgs e)
        {
            valueIsChanged = true;

            this.EditingControlDataGridView.NotifyCurrentCellDirty(true);

            base.OnTextChanged(e);
        }

        #endregion        
    }

Ing Rosell
fabrosell  Thursday, September 24, 2009 2:55 PM

You can use google to search for other answers

Custom Search

More Threads

• cannot create a datagridview from datasource
• examples
• How to build Gridview Master/detail
• How to cancel the process untill the validations conditions are met when click the button? --VB.net or VS 2005
• DataGridView ComboBox list appears in wrong place on UI
• DataGridView Edit Problem..
• Dealing with dataGridView
• Adding first item to combobox's datasource messes up display member
• Display blank cell in DataGrid when binding to non-nullable property
• ADO.NET Strongly DataType Problem