Validating DataGridView Cells - vb.net

I have a datagridview on my form currently. The idea that I'm trying to do is to catch a possible double entry issue when a user edits a cell in the datagridview. I'm supposed to check the field for a duplicate value (which CheckContestantList already does by looping through each row and a possible match). On a match, the previous value is supposed to be restored and a messagebox should pop up and warn the user while resetting that field to edit mode.
However, when a user presses the Enter key... the current row indicator moves down by one... and throws everything off. I've already done a bit of reading on the matter but I can't seem to keep the current cell active even if someone presses Enter.
How do I allow for the Enter key to still confirm the enter press but not move down by one row?
Private Sub dgvContestantPool_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles dgvContestantPool.CellEndEdit
' On the editing of the field, check to see if the value already exists.
If CheckContestantList(dgvContestantPool.CurrentCell.Value) = True Then
' Reset the value to the original value...
dgvContestantPool.ClearSelection()
dgvContestantPool.CurrentCell = dgvContestantPool.Rows(intCurrentRow).Cells("ContestantName")
dgvContestantPool.Rows(intCurrentRow).Selected = True
dgvContestantPool.CurrentCell.Value = strOldValue
dgvContestantPool.BeginEdit(True)
' Alert the user to try again...
MessageBox.Show("Entered value already exists in the list, try again or delete the entry.", "INVALID DATA - Already Exists", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
' Go ahead and let the edit persists.
End If
End Sub
Private Sub dgvContestantPool_CellBeginEdit(sender As Object, e As DataGridViewCellCancelEventArgs) Handles dgvContestantPool.CellBeginEdit
strOldValue = dgvContestantPool.CurrentCell.Value
intCurrentRow = dgvContestantPool.CurrentRow.Index
End Sub

You are using the wrong datagridview event, if you're gonna validate an input, you can use the _CellValidating event.
Here's an example:
Private Sub dgvContestantPool_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) Handles dgvContestantPool.CellValidating
If CheckContestantList(dgvContestantPool.Rows(e.RowIndex).Cells(e.ColumnIndex).EditedFormattedValue) = True Then
'Your code goes here
End If
...
Now, for example the cell value is invalid, you can call the
e.Cancel = True in the cell_validating event so that the user cannot go to other cells unless the cell value is valid or press the ESC key. This will exit the cell and return to its previous/original value.

Related

How do I get the textbox to enable after a certain amount of text is inputted?

So my next question(i know i know ive had a lot of questions already but im learning and my teachers suck)
but I am trying to get the textbox to go to readonly after a certain amount of text has been entered. I know how to make it a read only textbox but only after Ive had one set of data entered. i need it to be readonly after 7 days of data has been entered
I've tried inputtextbox.enabled = false
'Validating if user input is a number or not
Dim output As Integer
If Not Integer.TryParse(InputTextbox.Text, output) Then
MessageBox.Show("ERROR! Data must be a number")
InputTextbox.Text = String.Empty
Else
UnitsTextbox.AppendText(Environment.NewLine & InputTextbox.Text)
InputTextbox.Text = String.Empty
End If
InputTextbox.Enabled = False
I'm expecting it to disable after the user has entered 7 days worth of data but it only disables after one day of data is entered
Since the entries to UnitsTextbox are all done in code, this TextBox can be set to read only at design time.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim output As Integer
If Not Integer.TryParse(InputTextbox.Text, output) Then
MessageBox.Show("ERROR! Data must be a number")
Else
UnitsTextbox.AppendText(Environment.NewLine & InputTextbox.Text)
End If
'Moved this line outside of the If because it happens either way
InputTextbox.Text = String.Empty
If UnitsTextbox.Lines.Length >= 7 Then
Button2.Enabled = False
End If
End Sub
Here's some simple psuedocode
Private Sub InvalidateTextbox(sender As TextBox, e As KeyEventArgs) Handles TextBox1.KeyUp, TextBox2.KeyUp
'FOR ANY TEXTBOX YOU WANT TO CONTROL WITH THIS SUB, ADD AN ADDITIONAL HANDLE.
If Strings.Len(sender.Text) > 7 Then
'^SIMPLE CONDITIONAL, CHECKING IF THE LENGTH IS MORE THAN SEVEN CHARACTERS, MODIFY THIS TO SUIT YOUR NEEDS.
sender.Enabled = False
'^IF THE CONDITIONAL IS TRUE, DEACTIVATE THE CONTROL, IF THAT IS WHAT YOU ARE LOOKING FOR.
sender.ReadOnly = true
'^IF YOU WANT READONLY,NOT ENABLED/DISABLED.
End If
End Sub
This code will execute every time a key is pressed while the text boxes are active. What is after "Handles" defines what events will trigger the sub.
sender becomes the textbox object that triggered the sub. e holds all the event arguments for the keyboard, so you can evaluate things like which key was pressed and other neat things.
There was some confusion on if you wanted enabled/disabled or readonly, both options included.

Datagridview Check Box Error Default

I have a Datagridview in which a user will input data for shifts they have worked. I have a Checkbox to tick whether they require an on call payment for the shift. It's unchecked Value is "N" and when checked the value is "Y". This works well.
However when the user leaves the check box at it's default state from load, when i come to send it to the database i get an exception. How can I get the default value to always be "N" even if the user hasn't altered the box?
Error Message: Object Reference Not set to an instance of an object.
You need declare the checkbox in the datagrid item_databound
Private Sub dataGrid_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dataGrid.ItemDataBound
If (e.Item.ItemType = ListItemType.Item) Or (e.Item.ItemType = ListItemType.AlternatingItem) Then
dim checkbox as checkbox = e.item.findControl("yourCheckboxID")
end if
end sub

Datagridview won't change checkbox of first row (vb.net)

I have a datagridview (here called cameraTable). One column of the datagridview is purely checkboxes. I have a button that when clicked will check all the boxes in the column, aka select all. Here's the code:
Private Sub btnSelectAll_Click(sender As Object, e As EventArgs) Handles btnSelectAll.Click
For Each row As DataGridViewRow In cameraTable.Rows
DirectCast(row.Cells("CheckBox"), DataGridViewCheckBoxCell).Value = _
True
Next
End Sub
The problem I'm having is that the initial box (i.e. row zero) never changes to checked. I tried these:
DirectCast(cameraTable(0, 0), DataGridViewCheckBoxCell).Value = True ' doesn't work
cameraTable.Rows(0).Cells(0).Value = True ' doesn't work
Neither change the box to checked, but the other rows within the column change without a problem. I even did a msgbox that prints out the value, and turns out to be "True". So the value of the checkbox has changed, but the check box in the datagridview is still unchecked. Any ideas?
Thanks for all the help!
-K
The datagrid will not get INotifyPropertyChanged events (or will not process them) for the row/cell that is currently selected. If you have other columns that can be edited, move the focused column to it.
If all else fails, reload the grid after seting the values by setting the datasource = nothing and then back to what it was.
Steve is right. What I did was when the check box is clicked, I set the focus to another cell on that row (my dgv is set to FullRowSelect):
Private Sub dgv_CellContentClick(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgv.CellContentClick
If e.ColumnIndex = iCBColIDX Then
dgv.CurrentCell = dgv.Rows(e.RowIndex).Cells("sts")
End If
End Sub
Make your checkbox column width=20 instead of 18.
No, I don't know why, but it helps.
Thanks this man.
PS. It isn't a joke, it's a bug.

How to Supply Default Value back to DataGridViewCell After Error Message

My current code will show a messagebox that tells the user that only numeric input will be accepted if they input any non-integer into the field. However I can't seem to find out how I might supply a default value back to the datagridviewcell.
Private Sub DataGridViewCOTS_DataError(ByVal sender As Object, ByVal e As DataGridViewDataErrorEventArgs) Handles DataGridViewCOTS.DataError
If StrComp(e.Exception.Message, "Input string was not in a correct format.") = 0 Then
'If e.ColumnIndex = 2 Then
MessageBox.Show("Please Enter a numeric Value")
'DataGridViewCOTS.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = 3
End If
End Sub
From this thread http://social.msdn.microsoft.com/Forums/windows/en-US/ca2b3a41-e598-4a84-ac75-57064febd5e5/change-cell-value-in-datagridviewdataerror
The DataError event occurs when an external data-parsing or validation
operation throws an exception, or when an attempt to commit data to a
data source fails.
Based on it, you can't fix the value here since the
value will not be committed. After you changed the correct/default
value to the DataGridView Cell, you must commit it. So, set the
e.Cancel = false would be OK.
So, just set e.Cancel = false after you change value and it should work.
Hope this helps

One column in a vb.net Datagridview should not allow paste of non-integers

I have a datagridview and one of the columns is a Quantity column that should only allow integers. No negative symbols or decimal points. I have prevented the user from typing in any characters but they can paste them in. I could stop this in validation but I would ideally like to not even show characters that are pasted in. How would I detect and remove pasted in letters and in what event?
Ideally I would also like for only the paste to not work, so if the field already had a 2 in it and they pasted "test" then the 2 would remain, although that isn't as important.
Here's one approach:
'Set a flag to show when the form has finished initialising
Dim initialising As Boolean = True
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Form is initialised so set boolean to false
initialising = False
End Sub
Private Sub DataGridView1_CellValueChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
'Only process once the form is initialised as values don't exist yet!
If Not initialising Then
If Not IsNothing(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value) Then
'If the clipboard contains text
If Clipboard.ContainsText Then
' Check to see if the value of the cell matches whats in the clipboard
If CStr(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value) = Clipboard.GetText Then
'You know its been pasted
If Not IsNumeric(CStr(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value)) Then
'This value should be rejected
Else
'This value is allowed
End If
End If
End If
End If
End If
End Sub
See my commentated code for an explanation.
I'm not sure you will want to do it on this event as it doesn't fire the event until the user leaves the cell. Hopefully however my approach of checking the value against what is in the clipboard might help you to identify if its a pasted value.
You'd have to implement a validating method and call it in some of the DataGridView's events (I'm thinking KeyDown/Keypress and MouseClick).
I think it's bad practice, because you'll be struggling to find more ways in which the user can trick your application; most apps nowadays let the user input whatever they want, but keep the user from completing her task until she has sanitized her input. Most also give clear on-screen instructions on how to do so.
Something like this
Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
End Sub