I am creating a program that has a lot of user inputs. Most of the user inputs are going to be in TextBoxes that need to be only numeric entries.
Currently, I am just using a TextChanged method for getting values, which then make other buttons/checkboxes show/hide based on the entry.
I am wanting to create a method or implement some kind of utilization that checks when is being inputted into the boxes, to either prevent people from making incorrect inputs, to fix changes that they had made, or to create a messagebox that will tell them that their input is invalid.
I have two ways I am currently working with but they don't work with each other.
I have a parse method, that converts the input text into a Double but the problem I am running into, if they utilize the backspace button then re-enter their numbers, it will not recognize the input (which is needed to open/close other textboxes/checkboxes). This does work with the TextChanged method.
I have a regex set that utilizes the PreviewTextInput and KeyDown methods. This works pretty well with not allowing certain inputs but it doesn't work with the textchanged method (or at least I don't understand how to point to it).
I am in need of some guidance on how to create a viable method for checking inputs into textboxes that doesn't require my users to press a button for each entry (aka checking real-time).
I think this is what you are looking for.
Binding.Validation
For an Int it is as easy as just binding to an Int.
If you need to be able to increase/decrease the value via button use NumericUpDown or one of its subclass.
If you just need a textbox, you have to handle PreviewKeyDown() event. You need to manually check for valid/invalid keys pressed. When an invalid key is pressed, you set e.Handled = true; to prevent the key down event from tunneling down.
I really couldn't understand completely, but according to me you are trying to prevent a textbox to take invalid input and at the same time you want to use TextChanged method, so you can do like this:
<TextBox Name="txtAddNumber" TextChanged="txtAddLable_TextChanged" PreviewTextInput="txtAddNumber_PreviewTextInput" />
And txtAddNumber_PreviewTextInput method:
private void txtAddNumber_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
char c = Convert.ToChar(e.Text);
if (!Char.IsLetter(c))
e.Handled = false;
else
e.Handled = true;
base.OnPreviewTextInput(e);
}
And if you want to handle some error message kind of thing on the base of input you can do like this:
private void txtAddNumber_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
char c = Convert.ToChar(e.Text);
if (!Char.IsLetter(c))
{
// Put your Logic here according to requirement
e.Handled = false;
}
else
{
// Put your Logic here according to requirement
e.Handled = true;
}
base.OnPreviewTextInput(e);
}
And
e.Handled = false means input is numeric and e.Handled = true means input is non-numeric.
And your txtAddLable_TextChanged method will bw like:
private void txtAddLable_TextChanged(object sender, TextChangedEventArgs e)
{
// Logics here...
}
Related
I've added a KeyPress event handler to my DataGridView. If user presses "=" in a Cell, this event fires. But the = key must be first char.
How can I detect whether the pressed key is the first char?
I used the code shown here for this. I've made a string variable, named meter. It keeps the last pressed key, so I can understand from the length of meter if it's the first char or not.
It is worked actually, but when user deletes the key then it gives the wrong result.
Is there anyone give me some advice? Maybe different solution?
// this keeps pressed key and makes string.
string meter = string.Empty;
void Control_KeyPress(object sender, KeyPressEventArgs e)
{
// if the first pressed "=" key. Then meter="=". So meter length=1
meter = meter +e.KeyChar.ToString();
if (meter.Length == 1)
{
//if user keypress "="
if (e.KeyChar == '=')
{
//do things
}
}
}
I find a solution. I explain how to solve for other users If they face the similar problem.
First of all thanx to #Jimi. He gave me the idea.
I added "cellTb" object that represents the cell textbox using "EditingControlShowing" event.So it allows me to detect text is "=" or not. Here is the codes.
DataGridViewCell currentCell;
TextBox cellTb; // this represents cell textbox
private void dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
e.Control.KeyUp += new KeyEventHandler(Control_KeyUp);
currentCell = this.dgv.CurrentCell;
cellTb = (TextBox)e.Control;
}
void Control_KeyUp(object sender, KeyEventArgs e) //
{
if (cellTb.Text == "=") // this is my check operations.
{
if (e.KeyCode == Keys.D0) //if user keyup "="
{
//do things
}
}
}
Edit: Explanation
#Harald Coppoolse.Actually it is my fault not telling exactly what I'm trying to do. I want to try something similar excel aplication. If the user press “=”, then he/she can selects columns then when press Enter the result will shown. But the problem is after the user pressed “=” then selecting another cell make cursor leaves the main cell. I asked question about that before. There is a link below. But what i asked is some diffucult to make possible. #JohnG.( commenter) advice me to use textbox control.
Handle select click event datagridview
Its seems sense. So i decided to used textbox. I added picture for easy understanding how i perform it.
For now it seems succeeded but i do not know which problems will be occur in the future.
I want to touch on the points you draw attention.
“What would happen if the operator keeps the equal sign down for a
while,”
I tried now it returns string like that“=====”. This is user problem.
“what if the operator selects several rows and presses the equal sign?
And what about copy-paste to paste the equal sign, or drag and drop?”
Actually i never think about this situations. But i ll try if conditions.
In a conclusion i ll change my codes according to your directions.
Thank you very much and your time.
I'm not sure if it is wise to react on KeyPress. What would happen if the operator keeps the equal sign down for a while, so that a KeyPress appears rapidly after each other, or what if the operator selects several rows and presses the equal sign?
And what about copy-paste to paste the equal sign, or drag and drop?
I think what you want is this:
Whenever the operator is editing DataGridViewTextBoxCell X of the DataGridView, and during editing the contents of the EditingControl of the cell X contains only the equal sign, I want to call procedure MyProcedure(DataGridViewCell cell)
(TODO: invent proper name for MyProcedure)
So you don't want this when the operator has finished editing the cell, you want this during cell editing.
For this you need access to the DataGridViewTextBoxEditingControl Class
This object is only available while the DataGridViewTextBoxCell class is in edit mode. You get access to the object just before the operator starts editing via event DataGridView.EditingControlShowing
Using visual studio designer:
this.dataGridView1.EditingControlShowing += this.OnEditingControlShowing);
In the event handler you subscribe to the TextChanged event of the editing control that is about to be shown
private void OnEditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
e.Control.TextChanged += ShownEditingControl_TextChanged;
}
Now whenever the operator types something in the Cell's editing control, you get notified:
private void ShownEditingControl_TextChanged(object sender, EventArgs e)
{
DataGridViewTextBoxEditingControl shownEditingControl =
(DataGridViewTextBoxEditingControl)sender;
// Do what you want to do:
Debug.WriteLine(shownEditingControl.Text);
}
You can do what you want to do if the text contains only the equal sign, or if the text has several characters with the equal sign as first character.
if (shownEditingControl.Text == "="
{
// do what you want to do if the operator edited only the equal sign
// for example:
DataGridView dgv = shownEditingControl.EditingControlDataGridView;
DataGridViewCell cell = dgv.CurrentCell;
MyProcedure(cell);
}
I want to write something in a TextBox, then I want to press Enter and convert the input into a string.
How do you do this in WinForms?
For starters, input into a TextBox is already a string and is stored in the Text property. So that part is easy.
Triggering off of the "Enter" key is another story however. The easiest way is with the PreviewKeyDown event. Assign something like the following handler to your text box's PreviewKeyDown event (either in code-behind or through the designer):
void HandleKeyPress(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
string input = (sender as TextBox)?.Text;
//Your logic
e.IsInputKey = true; //Don't do standard "Enter" things
}
}
The reason you use PreviewKeyDown is that the later events (KeyDown, KeyPress, KeyUp) won't trigger on "Enter" because its not a "InputKey". The linked documentation explains is in fuller detail.
Notes:
If you want the standard handling of "Enter" to continue, then don't set IsInputKey to true.
The first line of the if statement says "Cast the control that raised this event to TextBox and get it's Text property." You could instead use the TextBox's name, or a number of other things.
The ?. is in case the cast fails due to the control not actually being a TextBox (input will be null in that case). This is only valid syntax in C# 6.
The text in the textbox would already be a string. You can grab the text value of the textbox by simply grabbing the .Text property.
See https://msdn.microsoft.com/en-us/library/a19tt6sk(v=vs.110).aspx for more info.
I have a TextBox. After leaving the textBox the first character should be a capital Letter.
Three Events work as same. They are Leave,Validating and Validated.
if (txtLocl.Text.Length > 0)
txtLocl.Text = txtLocl.Text.Substring(0, 1).ToUpper() + txtLocl.Text.Substring(1);
Which event of these 3 events should I use?
You can subscribe to the Control.Leave event which will be fired when the control loses focus. Originally, I thought using Control.LostFocus would be the most appropriate event to use but it is not available via the designer meaning you would need to manually subscribe to the event which is a bit ugly and unconventional in my opinion.
private void inputTextBox_Leave(object sender, EventArgs e)
{
if (inputTextBox.Text != string.Empty)
{
string input = inputTextBox.Text;
inputTextBox.Text = input.First().ToString(CultureInfo.InvariantCulture).ToUpper() +
string.Join(string.Empty, input.Skip(1));
}
}
You sound like you're interested in Control.Validating. The advantage of using Control.Validating is that you can utilize the event handler's given argument; CancelEventArgs and set the Cancel property to true. What this will do is stop the control from losing focus and forcing the user to enter a valid value. I don't think this is appropriate for your application as you are not really validating anything but formatting the input.
private void inputTextBox_Validating(object sender, CancelEventArgs e)
{
if (inputTextBox.Text == string.Empty)
{
statusLabel.Text = "The given input is not valid.";
e.Cancel = true;
}
}
Bear in mind that when the form closes, all controls subsequently lose focus and the Control.Validating event is fired which could stop the Form closing until all fields pass their relative validation checks. If you find yourself needing to avoid this behavior a quick search will prevail.
There are many other events also available.
As said by MSDN, When you change the focus by using the keyboard (TAB, SHIFT+TAB, and so on), by calling the Select or SelectNextControl methods, or by setting the ContainerControl.ActiveControl property to the current form, focus events occur in the following order:
1) Enter
2) GotFocus
3) Leave
4) Validating
5) Validated
6) LostFocus
When you change the focus by using the mouse or by calling the Focus method, focus events occur in the following order:
1) Enter
2) GotFocus
3) LostFocus
4) Leave
5) Validating
6) Validated
If the CausesValidation property is set to false, the Validating and Validated events are suppressed.
textBox1_Leave is appropriate for you.
Check the events and description about textboxes over here>>
http://msdn.microsoft.com/en-us/library/system.windows.forms.textbox_events.aspx
Hope its helpful.
You might want to subscribe to LostKeyboardFocus event (in WPF) or Leave event (in WF).
I'd suggest using the Leave because I assume you aren't validating the value, but formatting it. Validating and Validated should contain code for validation and the aftermath of validation respectively, IMO.
I have a NumericUpDown in my application but it is dangerous. When the value is changed the entire document is erased. Because of this, I'd like to give the user a warning (even if he accidentally hits OK he can undo it.)
The problem is that it seems that the only event I could handle would be the ValueChanged event and I'd end up with code like this.
private bool ignoreValueChanged = false;
private void numFoobar_ValueChanged(object sender, EventArgs e)
{
if (ignoreValueChanged)
{
ignoreValueChanged = false;
return;
}
if (MessageBox.Show("This will erase the entire document. Are you sure?", "Confirmation", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
ignoreValueChanged = true;
numFoobar.Value = oldValue; // The ValueChanged event gets called again =/
return;
}
// More code
}
There has got to be a better way. I was hoping Validating would help but it is only called when closing the form it seems.
Oh well you could remove the event subscribed to the numericUpdown control before resetting its value, after resetting it then again subscribe it back. This way, the event is not called when you reset the value.
But i am also thinking about how to check if the event is already subscribed or not. But above said method shall give you half the solution.
Here i tried this a bit and it seems to work but i cant seem to figure out how to check if already that same event is subscribed or not.
void NumericUpDown1ValueChanged(object sender, EventArgs e)
{
if(numericUpDown1.Value > 10)
{numericUpDown1.ValueChanged -= new System.EventHandler(this.NumericUpDown1ValueChanged);
numericUpDown1.Text = "5";
}
else numericUpDown1.ValueChanged += NumericUpDown1ValueChanged;//Here i need to first check if already it is subscribed or not before such that i dont want to subscribe double time
}
Did some Googling, and here's something that might work:
private void numFoobar_ValueChanged(object sender, EventArgs e)
{
this.ValidateChildren();
}
private void numFoobar_Validating(object sender, CancelEventArgs e)
{
if (MessageBox.Show("This will erase the entire document. Are you sure?", "Confirmation", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
e.Cancel = true;
}
}
Note that you'll need to reset the value as canceling the validation doesn't change the value. But this is the only way I was able to get the Validating event to fire.
ContainerControl.ValidateChildren Method
There are couple of issues to work out with this, however:
When exiting the program, it will fire the Validating event again; probably need to handle it in one of the closing events for the form or application.
I played with resetting the value in the ValueChanged event, but that trigged the Validating event again.
I'll keep playing with it for a bit and see if I can come up with a more solid solution for you.
This is really a usability issue. I guess what you are trying to do is to ignore the valueChanged event when the value has changed to the current persistent value. One option is to compare with the current value the document is based on.
Been googling a bit. First, I came up with this:
typeof(NumericUpDown).GetField("currentValue", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(numericUpDown1, 5m);
Which works but it is reflection and it seems a little over the top so I decided against it. Then I found this:
C# winforms numericupdown control
And based my solution on the second answer, which isn't so bad to be honest.
I can't seem to find a way to catch the input of a magnetic card reader. When it swipes, the input gets into active text editor, like say a notepad.
Unfortunately, the focus on textbox field won't do the trick, because I'm required to make it a label instead of a textbox. Thus, I need a way to catch the input from the USB device to a variable or label instead.
Does anyone knows of a .NET class I could use to do this or any better ideas?
If it's a winforms app you could do
private void Form1_Load(object sender, EventArgs e)
{
KeyPreview = true;
KeyPress += Form1_KeyPress;
}
private bool inputToLabel = true;
void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (inputToLabel)
{
label1.Text = label1.Text + e.KeyChar;
e.Handled = true;
}
else
{
e.Handled = false;
}
}
and as long as the window has focus, the keypress characters will go to the label's text.
I don't think there will be anyway for you to prevent the user from manual input. I suspect the card reader that you have emulates a keyboard. So, to be able to read from the reader, you must receive keyboard input, and keyboard input means the user can type anything they like.
A possible solution is to change your card reader to one that uses an API to read from cards.
If getting a better card reader isn't an option, I think the best method to do this is to have a button. When the button is clicked, open a new form that contains the code #Bala R provided. But in addition, close the form within 1 second from the first key input. This will prevent users from tampering the input manually, but will provide sufficient time for the reader to complete.