Validate on text change in TextBox - c#

I have implemented validation rules on a textBox in my WinForm and it works well. However it checks the validation only when I tab out of the field. I would like it to check as soon as anything is entered in the box and everytime the content changes. Also I'd like it to check validation as soon as the WinForm opens.
I remember doing this fairly recently by setting some events and whatnot, but I can't seem to remember how.

If you're using databinding, go to the Properties of the textbox. Open (DataBindings) at the top, click on the (Advanced) property, three dots will appear (...) Click on those. The advanced data binding screen appears. For each property of the TextBox that is bound, in your case Text, you can set when the databinding, and thus the validation, should "kick in" using the combobox Data Source Update mode. If you set it to OnPropertyChanged, it will re-evaluate as you type (the default is OnValidation which only updates as you tab).

TextChanged event
in the future you can find all of the events on the MSDN library, here's the TextBox class reference:
http://msdn.microsoft.com/en-us/library/system.windows.forms.textbox(VS.80).aspx

How will your data be valid if it isn't finished? i.e. a user types a number and you try and validate it as a date?

When binding your textbox to a bindingSource go to Advanced and select validation type
"On Property Changed". This will propagate your data to your entity on each key press.
Here is the screen shot

You should be checking on KeyPress or KeyDown events and not just your TextChanged event.
Here is a C# Example direct from the MSDN documentation:
// Boolean flag used to determine when a character other than a number is entered.
private bool nonNumberEntered = false;
// Handle the KeyDown event to determine the type of character entered into the control.
private void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
// Initialize the flag to false.
nonNumberEntered = false;
// Determine whether the keystroke is a number from the top of the keyboard.
if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
{
// Determine whether the keystroke is a number from the keypad.
if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
{
// Determine whether the keystroke is a backspace.
if(e.KeyCode != Keys.Back)
{
// A non-numerical keystroke was pressed.
// Set the flag to true and evaluate in KeyPress event.
nonNumberEntered = true;
}
}
}
//If shift key was pressed, it's not a number.
if (Control.ModifierKeys == Keys.Shift) {
nonNumberEntered = true;
}
}
// This event occurs after the KeyDown event and can be used to prevent
// characters from entering the control.
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
// Check for the flag being set in the KeyDown event.
if (nonNumberEntered == true)
{
// Stop the character from being entered into the control since it is non-numerical.
e.Handled = true;
}
}

Related

TextBox input validation, numbers only

Good day. I'm having a hard time with this. TextBox1 should only accept numbers and if the user input a text, a message box will pop-up saying that only numbers can be entered.
I don't know how to do this since the message box should pop-up without clicking any button.
The user will just really enter numbers and if they enter non numerical value the message box will appear instantly.
Is this even possible?
I've tried the KeyPress events but I can still input letters. Please help.
This is a very standard implementation, with a minor twist of including a dialog box. In general a dialog box is just going to annoy the user and take the focus away from the form, it breaks the flow of the user interaction so we try to avoid it, however you can adapt the standard example listed in the MS Docs - KeyEventHandler Delegate documentation:
// Boolean flag used to determine when a character other than a number is entered.
private bool nonNumberEntered = false;
// Handle the KeyDown event to determine the type of character entered into the control.
private void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
// Initialize the flag to false.
nonNumberEntered = false;
// Determine whether the keystroke is a number from the top of the keyboard.
if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
{
// Determine whether the keystroke is a number from the keypad.
if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
{
// Determine whether the keystroke is a backspace.
if(e.KeyCode != Keys.Back)
{
// A non-numerical keystroke was pressed.
// Set the flag to true and evaluate in KeyPress event.
nonNumberEntered = true;
}
}
}
//If shift key was pressed, it's not a number.
if (Control.ModifierKeys == Keys.Shift) {
nonNumberEntered = true;
}
}
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
// Check for the flag being set in the KeyDown event.
if (nonNumberEntered == true)
{
// Stop the character from being entered into the control since it is non-numerical.
e.Handled = true;
MessageBox.Show("Only numeric input is accepted");
}
}
Using the KeyEventArgs in this manner allows you access to the raw physical key that was pressed, and to separately prevent the textbox from accepting the key press.
This style of code is very useful when 3rd party controls (or your own code) has overriden the standard implementations. It is however possible to do it all in the KeyPress event handler:
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
// Check for the flag being set in the KeyDown event.
if (!Char.IsNumber(e.KeyChar) && e.KeyChar != '.')
{
// Stop the character from being entered into the control since it is non-numerical.
e.Handled = true;
MessageBox.Show("Only numeric input is accepted");
}
}
But that could still allow us to enter a value of "12.333...44..5" so a more complete example should extend one of the previous examples and compare against the current value in the textbox:
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
// Check for the flag being set in the KeyDown event.
bool isNumber = Char.IsNumber(e.KeyChar);
if (e.KeyChar == '.')
{
isNumber = !(sender as TextBox).Text.Contains(".");
}
if (!isNumber)
{
// Stop the character from being entered into the control since it is non-numerical.
e.Handled = true;
MessageBox.Show("Only numeric input is accepted");
}
}

Suppress the display of the input into the TextBox

I have a winforms program containing a RichTextBox.
The user inputs the text into the RichTextBox.
I wish to receive the input through keyboard events and not through textBox1.Text property, validate the string and only display it in the RichTextBox later.
How can I prevent the RichTextBox from displaying the input text by the user, even though the user inputs the text into the RichTextBox?
The RichTextBox is selected and has focus.
I am sorry. I just wanted to simplify the issue and therefore I neglected to mention that it is not a TextBox but a RichTextBox. It turns out that it matters, as the proposed solution is based on the PassowrdChar property, which is not natively supported by RichTextBox. I do not wish to create an inherited class for a property which is not even being used as such, only to suppress displaying the user input at input time.
You can actually use the KeyDown event. By doing that, you have an ability to validate the user input.
Tutorial
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
//
// Detect the KeyEventArg's key enumerated constant.
//
if (e.KeyCode == Keys.Enter)
{
MessageBox.Show("You pressed enter! Good job!");
}
else if (e.KeyCode == Keys.Escape)
{
MessageBox.Show("You pressed escape! What's wrong?");
}
}
With that said, you have to store user input in string variable, validate it through the event and only then set variable value in textbox.
You can use this:
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
char c = e.KeyChar;
// ..
// handle the character as needed
// ..
e.Handled = true; // suppress the RTB from receiving it
}
Note that you may or may not want to treat mouse events like right mouseclicks to control inserting via the mouse..

Text length exceeding maximum allowed text

I am using textbox and here's my problem...
I already have a handler where program will not allow anymore inputs when defined Maximum text length is reached. Here's the code:
private void txtText_KeyPress(object sender, KeyPressEventArgs e)
{
if (txtText.Text.Length > MaxLengthAllowed - 1 && e.KeyChar != 8)
{
e.Handled = true;
Console.Beep(2000, 90);
return;
}
}
Now my problem is when I press and HOLD a key (for example the letter A), it exceeds the "MaxLengthAllowed" then beeps.
Is this a fault or something like a limitation of the textbox? Or am I missing something?
This code is working fine when you are not HOLDING a key. Hence, that's my problem.
Just set the MaxLength property of the textbox. It's as simple as
textboxVar.MaxLength = maxLengthAllowed;
Hope that helps.
You could always subscribe a PropertyChanged event, which you can rig to fire whenever the Text property of the textbox changes. Have a read of how to raise an event on Property Change
You could use the KeyUp event instead. That only fires once when you release the key. KeyPress will be fired multiple times for as long as you hold down the key.
The TextBox.Text is not updated when TextBox.KeyPress is fired. For example, if the Text before KeyPress is A, When user types B, the Text is still A (not AB) in the KeyPress event handler. So you have to define your MaxLengthAllowed to be 1 less than the desired value. The code should look like this:
private void txtText_KeyPress(object sender, KeyPressEventArgs e)
{
if ((txtText.Text.Length > MaxLengthAllowed - 1) && e.KeyChar != 8)
{
e.Handled = true;
Console.Beep(2000, 90);
}
}
I think you should use TextBox.MaxLength property instead, it also supports Beep, the Beep sound is even nicer than the Beep generated by Console.Beep().

How to prevent zeros from being input before non-zero digits?

In C#, WinForms how would you stop the following inputs:
0000000000001234556
0000.123456
00000123456.123456
If you want 1234556 instead of 000000001234556
Then you can convert it in Int,Double or any other Datatype as you want
2nd option is use the keypress event
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (e.KeyCode == ascii of 0)
{
e.Handled = false;
}
}
You can override the KeyPress event and define a state that, if input is == '0' then ignore, else, wait for a non-zero input. Then change the state to accept 0s.
Since you do not show code, I will not either
You could add an event handler to the KeyDown or KeyPress events. Inside the event handler check if the KeyEventArgs KeyCode is 0 and if the length of your TextBox.Text property is 0. If so set the KeyEventArgs Handled property to false.

Preventing double events in DataGridView

I have a problem that I am not sure how to solve. I have a DataGridView (EditMode = EditProgrammatically). This grid has one checkbox column and one or more textbox columns. The functionality is as following (or should be at least):
When you click on a checkbox, the checkbox should be toggled
When a row (or many rows) are selected, and you press space, the checkboxes should be toggled.
I have these two event handlers:
private void grid_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex == useColumn.Index)
{
if (ModifierKeys != Keys.Shift && ModifierKeys != Keys.Control)
{
ToggleRows(grid.SelectedRows);
}
}
}
private void RowSelectorForm_KeyDown(object sender, KeyEventArgs e)
{
if (grid.Focused && e.KeyCode == Keys.Space)
{
ToggleRows(grid.SelectedRows);
e.Handled = true; // Not sure if this is needed or even does anything
e.SuppressKeyPress = true; // Or this for that matter...
}
}
This almost works. The problem is when you press space and a checkbox cell is active. When a textbox cell is active, it works like it should. The problem is that when you press space and a checkbox cell is active, both events gets fired. Which means it first selects and then deselects (or the reverse). So the checkboxes end up being like they was. How can I prevent this?
I have thought about using a flag, but not sure where I can put it, since I can't really know if it was a double event or if it was just the user using space and then clicking with the mouse. So that can't really be used I think. Is there a different event I should use? Is there a way to see if the cell was clicked by mouse or by space? Is there a way to disable the automatic checkbox toggling when space is pressed? What can I do?
Note: Reason for RowSelectorForm_KeyDown and not just grid_KeyDown was that I was trying to use KeyPreview and then suppress the keypress if it was space and the grid was focused. But that SuppressKeyPress doesn't really seem to do anything at all =/ Maybe I've just misunderstood it...
Well, I didn't want to do it, but I have now fixed it with a timer... but if anyone knows how to do it properly, please let me know!!
Current solution:
private DateTime lastClick = DateTime.MinValue;
and in both events:
if (DateTime.Now - lastClick > TimeSpan.FromMilliseconds(400))
{
lastClick = DateTime.Now;
ToggleRows(grid.SelectedRows);
}
It has been a time since I worked with C#, but I assume that you can disconnect the grid_CellClick event handler before calling ToggleGrid in RowSelectorForm_KeyDown.
After the call, you can reconnect the event handler.
Also, there might be some way to supress the event from being fired in the first place. In some API's certain methods are specially provided that don't trigger any events.
The frustrating problems are:
.Handled doesn't prevent the check box from changing
.SuppressKeyPress doesn't prevent the checkbox from changing
If you DoubleClick on the checkbox, the first click fires the Click() event (toggling the checkbox) and the second click fires the DoubleClick() event (toggling the checkbox yet again).
However, the KeyDown event fires before any of the grid events. Perhaps setting a flag to indicate the spacebar was pressed or if the row was already selected, reset the value of the checkbox.
I used the following and it seemed to work well:
private Keys _ClickSource = 0;
private void dgv_CellClick(object sender, System.Windows.Forms.DataGridViewCellEventArgs e)
{
if (_ClickSource == 0 || _ClickSource != Keys.Space)
{
dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = ! (System.Convert.ToBoolean(dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value));
}
_ClickSource = null;
}
private void dgv_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
_ClickSource = e.KeyCode;
}

Categories