Error handling in datagridview cell editing.

Hi,

I use datagridview cell to do editing.

There some fields required numeric input, how to handling wrong edit without showing error or get exception like :

If not isnumeric(cell.value) then cell.value= 0

Thank you.
LVL 1
emi_sastraAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

M3mph15Commented:
If Not IsNumeric(GridView1.Rows([rowindex]).Cells([cellindex]).Text) Then
                  GridView1.Rows([rowindex]).Cells([cellindex]).Text = 0
End If
0
emi_sastraAuthor Commented:
No, it is not work.
Where to put the checking?

Still get error:

Operation did not succeed because the program cannot commit or quit a cell value change.  

Thank you.
0
M3mph15Commented:
Try doing the checking in the RowUpdating event
0
Learn SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

Jorge PaulinoIT Pro/DeveloperCommented:
Try something like this:
    Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
        ' Checks if the column is the second one (zero based index)
        If e.ColumnIndex = 1 Then
 
            Dim result As Integer
            If Not Integer.TryParse(Me.DataGridView1(e.ColumnIndex, e.RowIndex).Value.ToString, result) Then
                Me.DataGridView1(e.ColumnIndex, e.RowIndex).Value = 0
            End If
 
        End If
    End Sub

Open in new window

0
emi_sastraAuthor Commented:
Hi M3mph15,

How to check it?

Thank you.
0
emi_sastraAuthor Commented:
Hi jpaulino,

How to check if the problem is on certain column?

Thank you.
0
emi_sastraAuthor Commented:
Hi jpaulino,

i use ProcessCmdKey.

 Case EnumGridViewColumn.NilaiTransaksi

                        If Not IsNumeric(dgvRow.Cells(.CurrentCell.ColumnIndex).Value) Then
                            dgvRow.Cells(.CurrentCell.ColumnIndex).Value = 0
                        End If

                        If dgvRow.Cells(.CurrentCell.ColumnIndex).Value < 0 Then
                            dgvRow.Cells(.CurrentCell.ColumnIndex).Value = 0
                        End If

                        If dgvRow.Cells("Keterangan").Value.ToString.Trim = "" Then
                            dgvRow.Cells("NilaiKurs").Value = CDbl(txtNilaiKurs.Text)
                        End If

                       'Exception at below code

                      .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex + 1)


Thank you.
     

 
Private Sub dgvTransaksi_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvTransaksi.CellEndEdit
        ' Checks if the column is the second one (zero based index)
        If e.ColumnIndex > 0 Then
 
            Dim result As Integer
            If Not Integer.TryParse(Me.dgvTransaksi(e.ColumnIndex, e.RowIndex).Value.ToString, result) Then
                If e.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or _
                    e.ColumnIndex = EnumGridViewColumn.NilaiKurs Then
                    Me.dgvTransaksi(e.ColumnIndex, e.RowIndex).Value = 0
                End If
            End If
 
        End If
    End Sub

Open in new window

0
Jorge PaulinoIT Pro/DeveloperCommented:
>> How to check if the problem is on certain column?

If e.ColumnIndex = 1 Then check if you have changed on the column 1
 
>> i use ProcessCmdKey.
For what ? Do you have problems with your snippet ?
0
emi_sastraAuthor Commented:
If e.ColumnIndex = 1 Then check if you have changed on the column 1

Why should I check column 1 when the problem happened on other column?

Please see the problem where the exception exist.

   'Exception at below code

   .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex + 1)

The code above is inside ProcessCmdKey procedure.

Thank you.
0
Jorge PaulinoIT Pro/DeveloperCommented:
>> Why should I check column 1 when the problem happened on other column?

Emi_sastra, ColumnIndex = 1 it's obviously and examples. You should change to the column where you want to validate.
You don't need to work on ProcessCmdKey
0
emi_sastraAuthor Commented:
You should change to the column where you want to validate.
Yes, that's why I change to :

Private Sub dgvTransaksi_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvTransaksi.CellEndEdit
        ' Checks if the column is the second one (zero based index)
        If e.ColumnIndex > 0 Then
 
            Dim result As Integer
            If Not Integer.TryParse(Me.dgvTransaksi(e.ColumnIndex, e.RowIndex).Value.ToString, result) Then
                If e.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or _
                    e.ColumnIndex = EnumGridViewColumn.NilaiKurs Then
                    Me.dgvTransaksi(e.ColumnIndex, e.RowIndex).Value = 0
                End If
            End If
 
        End If
    End Sub

You don't need to work on ProcessCmdKey.

Do you remember that you taught me how to entry data at datagridview and use Enter to move to another column or row? You recommend using ProcessCmdKey. I use it now, please see the more complete code. If there is any alternative I am happy to learn it.

Thank you.


  Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
        If Not blnGridOnFocus Then Exit Function
 
        If keyData = Keys.Enter Then
 
            With Me.dgvTransaksi
 
                .EndEdit(True)
 
                Dim dgvRow As DataGridViewRow
                dgvRow = .Rows(.CurrentRow.Index)
 
                Select Case .CurrentCell.ColumnIndex
 
                   
                    Case EnumGridViewColumn.NilaiTransaksi
 
                        If Not IsNumeric(dgvRow.Cells(.CurrentCell.ColumnIndex).Value) Then
                            dgvRow.Cells(.CurrentCell.ColumnIndex).Value = 0
                        End If
 
                        If dgvRow.Cells(.CurrentCell.ColumnIndex).Value < 0 Then
                            dgvRow.Cells(.CurrentCell.ColumnIndex).Value = 0
                        End If
 
                        If dgvRow.Cells("Keterangan").Value.ToString.Trim = "" Then
                            dgvRow.Cells("NilaiKurs").Value = CDbl(txtNilaiKurs.Text)
                        End If
 
                        Me.Count_Total()
 
                        .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex + 1)
 
 
                    Case EnumGridViewColumn.Keterangan
 
                            If .Rows.Count > .CurrentRow.Index Then
 
                                If .CurrentCell.RowIndex + 1 = .RowCount Then ERV_Global.Add_New_Row(dtTDCASH)
 
                                If intMode = ERV_Global.MB_ADD Then
                                    .CurrentCell = .Rows(.CurrentCell.RowIndex + 1).Cells(EnumGridViewColumn.NamaRekanan)
                            Else
 
                                .CurrentCell = .Rows(.CurrentCell.RowIndex + 1).Cells(EnumGridViewColumn.NamaRekanan)
 
                                If .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex).Value.ToString.Trim <> "" Then
                                    .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(EnumGridViewColumn.JenisTrs)
                                End If
                            End If
 
                        End If
 
                    Case Else
                            SendKeys.Send("{TAB}")
                            .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex)
 
                End Select
 
                .BeginEdit(True)
                blnGridOnFocus = True
 
            End With
 
            Return True
        Else
            Return MyBase.ProcessCmdKey(msg, keyData)
        End If
 
    End Function

Open in new window

0
Jorge PaulinoIT Pro/DeveloperCommented:
>> Yes, that's why I change to :

This will validate ALL column starting in the first second one. Is this what you want ?
 
>> You recommend using ProcessCmdKey
That's two different thinks!
The first it's to capture the enter key on the datagridview to do something (in that case to change the behavior). This is perform some validation AFTER the user changes the data. This way you can use the build in events of the datagridview (CellEndEdit) to handle your validation. You cannot detect from the ProcessCmdKey if the user have changed a value in the cell.
0
emi_sastraAuthor Commented:
This will validate ALL column starting in the first second one. Is this what you want ?
No, so how to change it?

The first it's to capture the enter key on the datagridview to do something (in that case to change the behavior). This is perform some validation AFTER the user changes the data. This way you can use the build in events of the datagridview (CellEndEdit) to handle your validation. You cannot detect from the ProcessCmdKey if the user have changed a value in the cell.

Yes, I have trapped it in CellEndEdit event, but after that it back to inside ProcessCmdKey.
Operation did not succeed because the program cannot commit or quit a cell value change.  
Exception happened inside ProcessCmdKey under code  :
 .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex + 1)

Thank you.
0
Jorge PaulinoIT Pro/DeveloperCommented:


>> No, so how to change it?

You need to use the columns you want to validate, like:
If e.ColumnIndex = 2 Or e.ColumnIndex = 4 Then
    ' your code
End If

This will validate the columns 3 and 5

Try this way and then let me know if the error in the ProcessCmdKey still occurs

 
0
emi_sastraAuthor Commented:
I change to :

If e.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or _
                  e.ColumnIndex = EnumGridViewColumn.NilaiKurs Then

            Dim result As Integer
            If Not Integer.TryParse(Me.dgvTransaksi(e.ColumnIndex, e.RowIndex).Value.ToString, result) Then
                Me.dgvTransaksi(e.ColumnIndex, e.RowIndex).Value = 0
            End If
        End If

The error still happens.

Thank you.

0
Jorge PaulinoIT Pro/DeveloperCommented:
>> The error still happens.
What errors ?

0
emi_sastraAuthor Commented:
Operation did not succeed because the program cannot commit or quit a cell value change.  
Exception happened inside ProcessCmdKey under code  :
 .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex + 1)

Thank you.
0
Priest04Commented:
Try this
If e.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or _
                  e.ColumnIndex = EnumGridViewColumn.NilaiKurs Then
 
            Dim result As Integer
            If Not Integer.TryParse(e.FormattedValue, result) Then
                e.Cancel = True
                SendKeys.Send("{ESC}")
                Me.dgvTransaksi(e.ColumnIndex, e.RowIndex).Value = 0
            End If
        End If

Open in new window

0
emi_sastraAuthor Commented:
Hi Priest04,

Still get the same error.

Thank you.
0
Priest04Commented:
You cannot have the same error, O have tried the example on a grid with an int column and it is working. If yo do, there is ome insfo that you are not telling us.. Place a new datagridview,and try the example.

0
emi_sastraAuthor Commented:
Do you use below ProcessCmdKey in you code?

Thank you.
Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
        If Not blnGridOnFocus Then Exit Function
 
        If keyData = Keys.Enter Then
 
            With Me.dgvTransaksi
 
                .EndEdit(True)
 
                Dim dgvRow As DataGridViewRow
                dgvRow = .Rows(.CurrentRow.Index)
 
                Select Case .CurrentCell.ColumnIndex
 
                   
                    Case EnumGridViewColumn.NilaiTransaksi
 
                        If Not IsNumeric(dgvRow.Cells(.CurrentCell.ColumnIndex).Value) Then
                            dgvRow.Cells(.CurrentCell.ColumnIndex).Value = 0
                        End If
 
                        If dgvRow.Cells(.CurrentCell.ColumnIndex).Value < 0 Then
                            dgvRow.Cells(.CurrentCell.ColumnIndex).Value = 0
                        End If
 
                        If dgvRow.Cells("Keterangan").Value.ToString.Trim = "" Then
                            dgvRow.Cells("NilaiKurs").Value = CDbl(txtNilaiKurs.Text)
                        End If
 
                        Me.Count_Total()
 
                        .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex + 1)
 
 
                    Case EnumGridViewColumn.Keterangan
 
                            If .Rows.Count > .CurrentRow.Index Then
 
                                If .CurrentCell.RowIndex + 1 = .RowCount Then ERV_Global.Add_New_Row(dtTDCASH)
 
                                If intMode = ERV_Global.MB_ADD Then
                                    .CurrentCell = .Rows(.CurrentCell.RowIndex + 1).Cells(EnumGridViewColumn.NamaRekanan)
                            Else
 
                                .CurrentCell = .Rows(.CurrentCell.RowIndex + 1).Cells(EnumGridViewColumn.NamaRekanan)
 
                                If .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex).Value.ToString.Trim <> "" Then
                                    .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(EnumGridViewColumn.JenisTrs)
                                End If
                            End If
 
                        End If
 
                    Case Else
                            SendKeys.Send("{TAB}")
                            .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex)
 
                End Select
 
                .BeginEdit(True)
                blnGridOnFocus = True
 
            End With
 
            Return True
        Else
            Return MyBase.ProcessCmdKey(msg, keyData)
        End If
 
    End Function

Open in new window

0
Priest04Commented:
emi_sastra, the conversation is not going anywhere. I am giving you one code, you are returning yours.... And you cannot have it both ways. First of all, ProcessCmdKey is not a place where you would put your business logic. For that purpose events like CellValidating, CellEndEdit and similar are used.

I don't see any reason why you would handle this in the ProcessCmdKey event. Do you? If you do, I would like to know why?

The code I gave you to handle non numeric values is doing what you wanted to - it sets value to 0 when non numeric value is used.
0
emi_sastraAuthor Commented:
emi_sastra, the conversation is not going anywhere. I am giving you one code, you are returning yours.... And you cannot have it both ways. First of all, ProcessCmdKey is not a place where you would put your business logic. For that purpose events like CellValidating, CellEndEdit and similar are used.

I am not going any where, but the fact is I am using it. I just want to know whether the way I do cause the problem or not?

I don't see any reason why you would handle this in the ProcessCmdKey event. Do you? If you do, I would like to know why?
I have try any other event to move from one cell to next cell using Enter, but I can not get solution from EE, and later jpaulino taught me to do that and so far I am happy with it except this problem.

The code I gave you to handle non numeric values is doing what you wanted to - it sets value to 0 when non numeric value is used.

Please see the run sequence:

After I enter not numeric key to the cell  and Press Enter to the cell then It goes to :

1. ProcessCmdKey
2. CellLeave
3. CellValidating
4. CellValueChange
5. CellEnter
5. ProcessCmdKey at .CurrentCell = .Rows(.CurrentCell.RowIndex).Cells(.CurrentCell.ColumnIndex + 1) where the exception occurs.

The code you provide has 2 problem:

1. I have to add event below, otherwise will cause error.
       Private Sub dgvTransaksi_DataError(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles dgvTransaksi.DataError
        e.Cancel = True
        e.ThrowException = False

    End Sub

2. SendKeys.Send("{ESC}") cause hanging, I have to press Ctrl Alt Del to make it process the next line which is   Me.dgvTransaksi(e.ColumnIndex, e.RowIndex).Value = 0.

Thank you.



Private Sub dgvTransaksi_CellValueChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles _
                dgvTransaksi.CellValueChanged
 
        If Not blnAllowGridValidation Then Exit Sub
 
        With dgvTransaksi
 
            If e.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or _
               e.ColumnIndex = EnumGridViewColumn.NilaiKurs Then
 
                Dim dgvRow As DataGridViewRow = .Rows(.CurrentRow.Index)
 
                If Not IsNumeric(dgvRow.Cells(e.ColumnIndex).Value) Then
                    dgvRow.Cells(e.ColumnIndex).Value = 0
                End If
 
                Count_Total()
            End If
 
        End With
 
    End Sub
 
 Private Sub dgvTransaksi_CellLeave(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvTransaksi.CellLeave
        blnGridOnFocus = False
 
        If intMode = ERV_Global.MB_VIEW Then Exit Sub
 
        With dgvTransaksi
 
            If e.ColumnIndex = 1 Then
                .Rows(e.RowIndex).Cells(e.ColumnIndex).Style.BackColor = .Rows(e.RowIndex).Cells(2).Style.BackColor
            Else
                .Rows(e.RowIndex).Cells(e.ColumnIndex).Style.BackColor = .Rows(e.RowIndex).Cells(1).Style.BackColor
            End If
 
        End With
    End Sub
 
 Private Sub dgvTransaksi_CellEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvTransaksi.CellEnter
        If intMode = ERV_Global.MB_VIEW Then Exit Sub
 
        If Not blnAllowGridValidation Then Exit Sub
 
        blnGridOnFocus = True
 
        With dgvTransaksi
            .Rows(e.RowIndex).Cells(e.ColumnIndex).Style.BackColor = ERV_Global.Get_LostFocus_Color()
        End With
    End Sub

Open in new window

0
Priest04Commented:
> I don't see any reason why you would handle this in the ProcessCmdKey event. Do you? If you do, I would like to know why?
>>I have try any other event to move from one cell to next cell using Enter, but I can not get solution from EE, and later jpaulino taught me to do that and so far I am happy with it except this problem.

THe problem is, if you use ProcessCmdKey for purpose of moving to the next cell, you shouldnt be now using it for everything else. This is not what it is meant for.

I, for example, also use ProcessCmdKey event to override the default behavior of Enter key when you are in edit mode (it moves to the next cell bellow), where I implement logic which leaves the focus to the cell which is edited. Now, I have some property which is called CellEditEnterBehavior, whicih has two values, Defualt and None, so I can easily choose weather I will use default implementation or my custom implementation. I choose not to move to the next cell in the same row, because in many cases I have to skip some column, and I can with ease move to any cell I want in the CellEndEdit cell, just by setting column index.

I am explaining all this, because if it is done this way, you can reuse this custom datagridview in ANY project. You dont need to have one for projectA, and one for ProjectB, etc, so you will have some duplicate code for each project. And what if in some point you see that there is some wrong code logic that you have implemented, and you need to rewrite the code? You would be rewriting in many applications, which could lead to a nighmare.

So, the point is to create something that can be reused any time. This is whay ProcessCmdKey should be used for. And this is where you should have implemented the cell focus behavior, but, in this case, ONLY that. You should not place any custom validation code in it.

Back to the problem. Altough I havent tested thoroughly SendKeys with CellValidating, I did experience what you were saying only if a breakpoint is set. Therefore it should be ok in the release code. Anyway, it is not the best solution, I agree, but its better that doing this in ProcessCmdKey event.

Remove the cell value valdation from CellValueChanged, and from ProcessCmdKey. We will use EditingControlShowing event to prevent user to type anything but numeric values. If you need to use decimal values, then you should also allow dot (.), but before you do, check if there is one already (dont allow two dots).


    Dim textBoxHandlerAdded As Boolean
 
    Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
 
        If Not TypeOf e.Control Is TextBox Then Exit Sub
 
        If Not handlerAdded Then
            AddHandler CType(e.Control, TextBox).KeyPress, AddressOf ValidateInput
            handlerAdded = True
        End If
    End Sub
 
    Private Sub ValidateInput(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
        Select Case Asc(e.KeyChar)
            Case 8, 48 To 57
            Case Else
                e.KeyChar = Nothing
        End Select
    End Sub

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
emi_sastraAuthor Commented:
Hi Priest04,

I am sorry, just back again.

It works, but need additional code to check certain cells is in editing and decimal symbol.

Thank you.
0
Priest04Commented:
>>It works, but need additional code to check certain cells is in editing

Do you mean you want to check that cell in certain column is editing? Here is improved version that handles this and decimal point.

Private Sub ValidateInput(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
    If  e.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or e.ColumnIndex = EnumGridViewColumn.NilaiKurs Then
        Select Case Asc(e.KeyChar)
            Case 8, 48 To 57 ' delete key and numeric keys
                ' do nothing
            Case 46 ' decimal point
                ' ckeck if there is another one
                If TextBox1.Text.IndexOf(e.KeyChar) <> -1 Then
                    e.KeyChar = Nothing
                End If
            Case Else
                e.KeyChar = Nothing
        End Select
    end if
End Sub
0
emi_sastraAuthor Commented:
There is one problem, when I click one of the cells then the handler still active.

  If  e.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or e.ColumnIndex = EnumGridViewColumn.NilaiKurs Then

The above code has limitation, we have to check the column, how about checking if it is numeric column type?

Thank you.
0
Priest04Commented:
Pardon, my mistake. It should have been

If dgvTransaksi.CurrentCell.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or dgvTransaksi.CurrentCell.ColumnIndex = EnumGridViewColumn.NilaiKurs Then

0
emi_sastraAuthor Commented:
Still have problem.

 If Not handlerAdded Then
            AddHandler CType(e.Control, TextBox).KeyPress, AddressOf ValidateInput
            handlerAdded = True
        End If

This handler always active at any cell? Its mean when the current is not EnumGridViewColumn.NilaiTransaksi and EnumGridViewColumn.NilaiKurs  then non numeric input will be reject.

Could we just check the cell type? if it is numeric than we do the addhandler.

Thank you.
0
Priest04Commented:
When you add handler for any cell any any column, you have added it for all. I do not understand your questions. What is the problem if handler is active? There is not such thing as numeric cell type,  there are types like Int16, Int32, Int64, UInt16, UInt32, UInt64, float, double, etc, so you would need to check for every type that can accept numeric values, or if you use only one or two types, then you can check only them.

To check the type of the cell

If dgvTransaksi.CurrentCell.ValueType Is GetType(Double) Then

End If

But I dont see why dont you check the column index? Its much easier, and much more cleaner.

Private Sub ValidateInput(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
    ' this will be fired on ANY cell edit
    If  e.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or e.ColumnIndex = EnumGridViewColumn.NilaiKurs Then
        ' but this code will be executed only for NilaiTransaksi and NilaiKurs columns
        Select Case Asc(e.KeyChar)
0
emi_sastraAuthor Commented:
When you add handler for any cell any any column, you have added it for all.
That's the problem.

When the column is not NilaiTransaksi and NilaiKurs then it will not accept numeric key, right? It will return nothing.

 Private Sub ValidateInput(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
        Select Case Asc(e.KeyChar)
            Case 8, 48 To 57
            Case Else
                e.KeyChar = Nothing
        End Select
    End Sub


Thank you.
0
Priest04Commented:
emi_sastra, seems to me I am posting here code for nothing, since you are not looking at it?

Looak at the post dated 11.30.2008 at 12:33PM CET
0
emi_sastraAuthor Commented:
Do you mean below code?

Private Sub ValidateInput(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
    If  e.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or e.ColumnIndex = EnumGridViewColumn.NilaiKurs Then
        Select Case Asc(e.KeyChar)
            Case 8, 48 To 57 ' delete key and numeric keys
                ' do nothing
            Case 46 ' decimal point
                ' ckeck if there is another one
                If TextBox1.Text.IndexOf(e.KeyChar) <> -1 Then
                    e.KeyChar = Nothing
                End If
            Case Else
                e.KeyChar = Nothing
        End Select
    end if
End Sub

If you mean this, this is not the problem.

Your forgot to remove handler when it is not needed, am I right?

 Private Sub dgvTransaksi_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles dgvTransaksi.EditingControlShowing

        If Not TypeOf e.Control Is TextBox Then Exit Sub

        Dim dgv As DataGridView = sender

        With dgv

            If .Columns(.CurrentCell.ColumnIndex).ValueType.ToString = GetType(Decimal).ToString Then

                If Not blnHandlerAdded Then
                    AddHandler CType(e.Control, TextBox).KeyPress, AddressOf ERV_Global.ValidateNumericInput
                    blnHandlerAdded = True
                End If

            Else

               'This is where you forgot
                RemoveHandler CType(e.Control, TextBox).KeyPress, AddressOf ERV_Global.ValidateNumericInput
                blnHandlerAdded = False
            End If

        End With

    End Sub

Thank you.


0
Priest04Commented:
No, I didnt. As I sad, it doesnt make any difference. This way you are only adding/removing hanlders, anytime you change column (from decimal type to non-decimal).

As I said, quite unnecessary.
0
emi_sastraAuthor Commented:
Please see the scenario.

Let's say we have 3 colums.

1. ItemCode
2. ItemName
3. ItemQty

Let's say we have move to ItemQty column and the handler is active, which mean we can not input anything excep number and decimalk symbol.

Now, we click ItemCode cell which should could accept number and non number key. Since the handler still active then we can not input non number key, am I right? Therefore when the current cell is not number field then we should deactivate the handler, am I right?

Thank you.
0
Priest04Commented:
If you used this code

Private Sub ValidateInput(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
        Select Case Asc(e.KeyChar)
            Case 8, 48 To 57
            Case Else
                e.KeyChar = Nothing
        End Select
    End Sub


Then you are incorrect. However, this is why you should add column index validation, so it will validate only 2nd and 3rd column. In your example, if column index for ItemCode  is 0, so it will not validate it.

Private Sub ValidateInput(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
    If  dgvTransaksi.CurrectCell.ColumnIndex = 1 or dgvTransaksi.CurrectCell.ColumnIndex = 2 Then
        Select Case Asc(e.KeyChar)
            Case 8, 48 To 57 ' delete key and numeric keys
                ' do nothing
            Case 46 ' decimal point
                ' ckeck if there is another one
                If TextBox1.Text.IndexOf(e.KeyChar) <> -1 Then
                    e.KeyChar = Nothing
                End If
            Case Else
                e.KeyChar = Nothing
        End Select
    end if
End Sub

What I used in my code are enum values, which I saw you were using in your example, so NilaiTransaksi should have value 1 and NilaiKurs should have value 2. If this enums should not be applied in this example, then you should replace it with the accoring ones, I cannot know the structure of your project.

If  dgvTransaksi.CurrectCell.ColumnIndex = EnumGridViewColumn.NilaiTransaksi Or dgvTransaksi.CurrectCell.ColumnIndex = EnumGridViewColumn.NilaiKurs Then

0
Priest04Commented:
pardon I made a typing mistake. I wrote

>>Then you are incorrect. However, this is why you should add column index validation,

should have been

Then you are correct. However, this is why you should add column index validation,
0
emi_sastraAuthor Commented:
Ok.

If  dgvTransaksi.CurrectCell.ColumnIndex = 1 or dgvTransaksi.CurrectCell.ColumnIndex = 2 Then

If we use the above code then it will be the code at any form. I want to make it public so we don't have to take care the column number.

Thus my code like below:

 Public Shared Sub ValidateNumericInput(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
        Select Case Asc(e.KeyChar)
            Case 8, 48 To 57
            Case Asc(Get_Decimal_Char())
                'If TextBox1.Text.IndexOf(e.KeyChar) <> -1 Then
                '    e.KeyChar = Nothing
                'End If
            Case Else
                e.KeyChar = Nothing
        End Select
    End Sub

Then I should removehandler if I use the above code.

How to make the remarks line working?

Thank you.
0
Priest04Commented:
If you want to make it public, then the only way is to add/remove handlers.

What do you mean by "make the remark working"? I thought that all issues are solved
0
Priest04Commented:
Aha, got it. :)


If ((sender)TextBox).Text.IndexOf(e.KeyChar) <> -1 Then
    e.KeyChar = Nothing
End If

Open in new window

0
Priest04Commented:
well, its a c# mixed code, I am currently coding in c#. VB.NET casting is done with CType, if I remember well


If CType(sender, TextBox).Text.IndexOf(e.KeyChar) <> -1 Then
    e.KeyChar = Nothing
End If

Open in new window

0
emi_sastraAuthor Commented:
Hi  Priest04,

It works. Just for your info, below code will handle decimal for any regional setting.

Public Shared Function Get_Decimal_Char() As String
        Dim curNilai As Decimal
        curNilai = 1.5

        Get_Decimal_Char = Format(curNilai, "#.0")
        Get_Decimal_Char = Mid(Get_Decimal_Char, 2, 1)
    End Function

Thank you very much for your help.
0
Priest04Commented:
You are welcome. There is a built in method that will return decimal sign from the number, I think in CurrentUICulture class, if my memory server me well.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.