Text length exceeding maximum allowed text - c#

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().

Related

How to make TextBox to receive only number key values using KeyDown Event in C#?

This code in my form updates the textBox1.Text twice whenever number keys are pressed.
private void textBox1_KeyDown( object sender, KeyEventArgs e ) {
//MessageBox.Show();
if( char.IsNumber((char)e.KeyCode) ) {
textBox1.Text += (char)e.KeyCode;
}
}
Explain why if you can?
Modify the code or provide me a better solution for this.
Input ( in textbox1 ):
54321
Output:
1234554321
When you press a key, a character is already appended to your TextBox. Then you run the following code and, if the key represents a number, you append it again:
if (char.IsNumber((char)e.KeyCode)) {
textBox1.Text += (char)e.KeyCode;
}
If you want to suppress any key that's not a number, you could use this instead:
e.SuppressKeyPress = !char.IsNumber((char)e.KeyCode);
From the syntax I assume you are using WinForms for the following answer.
The key pressed event is not suppressed, so it still works like a normal key pressed event and adds the character to the text of the box. Additionally you add the character to the text yourself once again.
Try to suppress the key pressed event in case a key is pressed, you do not want to allow.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (!char.IsNumber((char)e.KeyCode))
{
e.SuppressKeyPress = true;
}
}
You can try like this:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = !(e.KeyValue >= 48 && e.KeyValue <= 57);
}
Check New keyboard APIs: KeyEventArgs.SuppressKeyPress
The problem is that "Handled" doesn't take care of pending WM_CHAR
messages already built up in the message queue - so setting Handled =
true does not prevent a KeyPress from occurring.
In order not to break anyone who has currently got e.Handled =
true, we needed to add a new property called SuppressKeyChar. If we
went the other way, if "handling" a keydown suddenly started to
actually work, we might break folks who accidentally had this set to
true.
Try this code to accept numbers only
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar))
e.Handled = true;
}

Preventing user from entering zero but allowing other numbers that contain zero

I have a TextBox control. I have set my KeyPress event of the TextBox so that the user is only allowed to enter digits:
private void txtbxRecurEveryXWeeks_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
But in addition to that I do not want the user to set the value of the TexBot to zero "0". But they still should be allowed to enter "10" or "3400" as the value. How can I achieve that?
It's probably best to ignore the keypress event and handle the lost focus event and check and ensure the value isn't 0 when the user is done typing.
EDIT: It was pointed out that the user could type "000" and lose focus which would cause this to fail. You can check and confirm the textbox has a value and parse it as an int to confirm it isn't 0.
private void txtbxRecurEveryXWeeks_LostFocus(object sender, EventArgs e)
{
int value;
if(!string.IsNullOrWhitespace(txtbxRecurEveryXWeeks.Text)
&& int.TryParse(txtbxRecurEveryXWeeks.Text, out value)
&& value > 0)
{
//Do something like clear the textbox value
}
}
In the assumption that you use winforms, consider using the NumericUpDown control to enter numbers. It has the Minimum property, which you could set to 1 to avoid zero input.
Use NumericUpDown with minimum value = 1 and hidden up and down buttons.
numericUpDown1.Minimum = 1;
numericUpDown1.Controls[0].Hide();

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.

Validate on text change in TextBox

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;
}
}

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