..This is a reworking of a previously deleted question, I'm rewording to try to be more clear..
VB.NET 2010 Winform with a Datagridview.
User is able to type into an editable cell.
As they type, the "current" value of the cell should be used to search through an array of radiobuttons and select the button that matches the typed value.
Issue is that the user could type a value, but then type a DEL or BACKSPACE to alter the value. And the DEL/BACKSPACE of course doesn't have to be done at end of value, could be anywhere. Also a cells value isn't "finalized" until after this event is complete.
My original code looked like this...
Private Sub txtdgvDiaryEdit_Keypress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
'Test for numeric value or backspace
If IsNumeric(e.KeyChar.ToString()) _
Or e.KeyChar = ChrW(Keys.Back) Then
e.Handled = False 'if numeric
'******************************************************
If IsNumeric(e.KeyChar.ToString()) Then
If DirectCast(sender, TextBox).Text.Length = 0 Then
Call SelectRadioButtonForValue(e.KeyChar.ToString)
Else
Dim strvar As String
strvar = DirectCast(sender, TextBox).Text.ToString + e.KeyChar.ToString
Call SelectRadioButtonForValue(strvar.ToString)
End If
Else ...
But this doesn't pick up the value of the cell AFTER the DEL/BACKSPACE.
AND I can't use any kind of CELL VALUE CHANGES Because those don't fire till i'm actually LEAVING the cell.
I need to be able to pick up the actual cell value AFTER the Keypress had been processed but remain in EDIT MODE.
Thoughts?
Related
I'm struggling find a specific answer to this question, therefore asking it myself...
I have a DataGridView with columns which has the following formatting applied to it:
DGV.Columns(3).DefaultCellStyle.Format = "C2"
On the form there is a text box in which the user enters a number and that value is then entered in one of the cells in DGV:
For Each dr As DataGridViewRow In DGV.Rows
dr.Cells("ColumnHeader").Value = TextBox.Text
Next
Before the above code is executed, this event occurs on the TextBox to format its value:
Private Sub TextBox_Leave(sender As Object, e As EventArgs) Handles TextBox.Leave
TextBox.Text = FormatCurrency(TextBox.Text)
End Sub
The text within the TextBox is displaying correctly as a currency, but when the code to put that into a cell in the DGV executes it fails saying the value is in incorrect format.
Is DGV.Columns(3).DefaultCellStyle.Format = "C2" different format to FormatCurrency(TextBox.Text)?
That is all wrong. "C2" is a numeric format string, so it will only work on numbers. A String containing digit characters is not a number and a String containing currency text definitely isn't. You need to get the String from the TextBox, concert that to a number (probably Decimal for currency values) and then load that number into the grid. The grid converts that number, along with all the data, into text to display and will use your format string to do so:
dr.Cells("ColumnHeader").Value = CDec(TextBox.Text)
You would, presumably, already have validated the user input by this stage, so there's no possibility of CDec throwing an exception.
If the intent is to display the data formatted as currency in both the grid and the TextBox then you should get rid of your Leave event handler and handle the Validating and Validated events instead. The first will validate the input to ensure that it is numeric and the second will do the formatting:
Private Sub TextBox1_Validating(sender As Object, e As CancelEventArgs) Handles TextBox1.Validating
If Not Decimal.TryParse(TextBox1.Text, NumberStyles.Currency, Nothing, Nothing) Then
'Don't let the control lose focus when it contains invalid data.
e.Cancel = True
End If
End Sub
Private Sub TextBox1_Validated(sender As Object, e As EventArgs) Handles TextBox1.Validated
TextBox1.Text = Decimal.Parse(TextBox1.Text, NumberStyles.Currency).ToString("C2")
End Sub
That code will allow the user to enter the currency symbol or not, but it will ensure that the format is currency with two decimal places once it loses focus. You would then need to allow for the formatting when copying to the grid:
dr.Cells("ColumnHeader").Value = Decimal.Parse(TextBox1.Text, NumberStyles.Currency)
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.
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.
New poster here and a VB hack of sorts.
I have a windows form that contains a picture box and three textboxes.
The three textboxes (Red, Green, Blue) are used to enter a numeric value from 000 to 255 representing a color code.
The PictureBox will display the resulting color from the three TextBox values.
My validation routine ValidDecCode makes sure the values entered are within the allowable limits (000-255).
If a user enters a ‘2’ in the first position all is well. If a user then enters a ‘6’ in the second position it will not pass my validation test.
After entering the KeyDown event I save the sender.selectionstart and the sender.text values. After entering the ‘6’ the selectionstart will be a 1 and text contains data that has been validated, ‘2’.
Once the ‘6’ fails my validation test I display a MessageBox, reload my saved sender data, text and selectionstart. This returns the form back to its state prior to entering the ‘6’. The TextBox will show a ‘2’ and the cursor is placed after the ‘2’.
What I find strange is that if I comment out the MessageBox.Show() line the TextBox will show ‘26’ after failing validation. If I comment out the reload of my sender data and not the MessageBox.Show() line, the TextBox will show ‘26’.
I would like to know why commenting out the MessageBox.Show() line does not return the form to its state prior to entering invalid data and what can I do about it. What is it about calling the MessageBox that makes it work?
Private Sub RedBox_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) _
Handles RedBox.KeyDown, GreenBox.KeyDown, BlueBox.KeyDown
Dim InChr As String
Dim InPos As Integer = sender.selectionstart
Dim InText As String = sender.text
If IsNumeric(Chr(e.KeyCode)) Then
InChr = Chr(e.KeyValue)
If Not ValidDecCode(InText + InChr, InPos) Then
MessageBox.Show("Invalid value")
sender.text = InText
sender.selectionstart = InPos
End If
Else
MessageBox.Show("Invalid value")
sender.Text = InText
sender.selectionstart = InPos
Exit Sub
End If
End Sub
How can I select a single cell from selected row in datagridView and after selecting that I want to put simple search functionality (like we have in our windows folders-typing any characters and search should work)?
I do not really understand your question. If you want to select one cell, you can use the celldoubleclick event for exemple. And the to get the selected cell, use e.rowindex and e.columnindex which will give you the row and the column where the cell is located.
You can try this as a possible solution.
Dim nwData as CustomersDataSet = CustomersDataSet.GetCustomers()
m_CustomersGrid.DataSource = m_CustomersBindingSource
m_CustomersBindingSource.DataSource = nwData.Customers
Then you can sort using the BindingSource.
CustomersBindingSource.Sort = "ContactName ASC"
And you can find using the BindingSource.
Dim index as integer = _
CustomersBindingSource.Find("CompanyName", CompanyNameTextBox.Text)
If index <-1 then 'it was found; move to that position
CustomersBindingSource.Position = index
End If
You could then populate:
CustomersBindingSource.Find("CompanyName", CompanyNameTextBox.Text)
with the keys pressed in the cell by capturing them by utilizing:
Private Sub DataGridView1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView1.KeyUp
Dim dgv As DataGridView = TryCast(sender, DataGridView)
If dgv IsNot Nothing Then
'You will need some logic here to determine how long to wait between keyups
'Perhaps a timer that ticks every500 milliseconds and reset on keyup.
e.KeyData
End If
End Sub
I found the original Biding Source Logic at : This Location