Numeric TextBox - using Double.TryParse - c#

I know this is an age-old question with many an answer, but I haven't found any good, robust answers.
The requirement is a textbox that will always contain a string that Double.TryParse will return true on.
Most of the implementations I have seen do not guard against input such as: "10.45.8". This is a problem.
The preferable way of doing this is entirely with events, such as TextInput and KeyDown (for spaces). The problem with these is that it is quite complicated to get a string representing the new Text before it is changed (or the old Text after it is changed). The problem with TextChanged is that it doesn't provide a way to get the old Text.
If you could somehow get the new Text before it changes, that would be the most helpful, since you could test it against Double.TryParse. There may be a better solution though.
What is the best way to do this?
The best answer to this question is one that has several approaches and compares them.

Approach 1
Use a combination of the TextChanged and KeyDown events for a TextBox. On KeyDown you could save the current text in the textbox and then do your Double.TryParse in the TextChanged event. If the text entered is not valid, then you would revert to the old text value. This would look like:
private int oldIndex = 0;
private string oldText = String.Empty;
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
double val;
if (!Double.TryParse(textBox1.Text, out val))
{
textBox1.TextChanged -= textBox1_TextChanged;
textBox1.Text = oldText;
textBox1.CaretIndex = oldIndex;
textBox1.TextChanged += textBox1_TextChanged;
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
oldIndex = textBox1.CaretIndex;
oldText = textBox1.Text;
}
The CaratIndex is useful in not annoying your user to death with moving the cursor to the first position on failed validation. However, this method doesn't catch the SpaceBar key press. It will allow text to be entered like this "1234.56 ". Also, pasting text will not be properly validated. Beyond this, I don't like messing with the event handlers during text updating.
Approach 2
This approach should meet your needs.
Use the PreviewKeyDown and PreviewTextInput event handlers. By watching these events and handling accordingly, you don't need to worry about reverting to a previous text value in your text box. PreviewKeyDown can be used to watch for and ignore your SpaceBar key press and PreviewTextInput can be used to test your new textbox value before it is assigned.
private void textBox1_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
e.Handled = true;
}
}
private void textBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
//Create a string combining the text to be entered with what is already there.
//Being careful of new text positioning here, though it isn't truly necessary for validation of number format.
int cursorPos = textBox1.CaretIndex;
string nextText;
if (cursorPos > 0)
{
nextText = textBox1.Text.Substring(0, cursorPos) + e.Text + textBox1.Text.Substring(cursorPos);
}
else
{
nextText = textBox1.Text + e.Text;
}
double testVal;
if (!Double.TryParse(nextText, out testVal))
{
e.Handled = true;
}
}
This approach does a better job of catching invalid input before it gets into the textbox. However, setting the event to be Handled I suppose could get you into trouble depending on the rest of the destinations in the routing list for the message. A last piece that isn't handled here is the ability of the user to paste invalid input into the text box. This can be handled with the addition of this code, which is built off of Paste Event in a WPF TextBox.
private void OnPaste(object sender, DataObjectPastingEventArgs e)
{
double testVal;
bool ok = false;
var isText = e.SourceDataObject.GetDataPresent(System.Windows.DataFormats.Text, true);
if (isText)
{
var text = e.SourceDataObject.GetData(DataFormats.Text) as string;
if (Double.TryParse(text, out testVal))
{
ok = true;
}
}
if (!ok)
{
e.CancelCommand();
}
}
Add this handler with this code after the InitializeComponent call:
DataObject.AddPastingHandler(textBox1, new DataObjectPastingEventHandler(OnPaste));

Its really annoying that TextBox does not provide PreviewTextChanged event and everybody should invent the wheel every time to emulate it. I solved exactly the same issue recently and even published my solution on github as WpfEx project (take a look at TextBoxBehavior.cs and TextBoxDoubleValidator.cs).
Adam S's answer is very good, but we should consider few other corner cases as well.
Selected text.
During coputing resulting text in our textBox_PreviewTextInput event handler we should consider that user can select some text in text box and new input will replace it. So we should use something like:
private static void PreviewTextInputForDouble(object sender,
TextCompositionEventArgs e)
{
// e.Text contains only new text and we should create full text manually
var textBox = (TextBox)sender;
string fullText;
// If text box contains selected text we should replace it with e.Text
if (textBox.SelectionLength > 0)
{
fullText = textBox.Text.Replace(textBox.SelectedText, e.Text);
}
else
{
// And only otherwise we should insert e.Text at caret position
fullText = textBox.Text.Insert(textBox.CaretIndex, e.Text);
}
// Now we should validate our fullText, but not with
// Double.TryParse. We should use more complicated validation logic.
bool isTextValid = TextBoxDoubleValidator.IsValid(fullText);
// Interrupting this event if fullText is invalid
e.Handled = !isTextValid;
}
And we should use the same logic when we'll handle OnPaste event.
Validating the text
We can't use simple Double.TryParse, because user can type '+.' to type '+.1' ('+.1' - is absolutely valid string for double), so our validation method should return true on '+.' or '-.' strings (I even created separate class called TextBoxDoubleValidator and the set of unit tests because this logic is so important).
Before dig into implementation lets take a look at set of unit tests that will cover all corner cases for validation method:
[TestCase("", Result = true)]
[TestCase(".", Result = true)]
[TestCase("-.", Result = true)]
[TestCase("-.1", Result = true)]
[TestCase("+", Result = true)]
[TestCase("-", Result = true)]
[TestCase(".0", Result = true)]
[TestCase("1.0", Result = true)]
[TestCase("+1.0", Result = true)]
[TestCase("-1.0", Result = true)]
[TestCase("001.0", Result = true)]
[TestCase(" ", Result = false)]
[TestCase("..", Result = false)]
[TestCase("..1", Result = false)]
[TestCase("1+0", Result = false)]
[TestCase("1.a", Result = false)]
[TestCase("1..1", Result = false)]
[TestCase("a11", Result = false)]
[SetCulture("en-US")]
public bool TestIsTextValid(string text)
{
bool isValid = TextBoxDoubleValidator.IsValid(text);
Console.WriteLine("'{0}' is {1}", text, isValid ? "valid" : "not valid");
return isValid;
}
Note, that I'm using SetCulture("en-US') attribute, because decimal separator "local-specific".
I think I cover all corner cases with those tests but with this tool in your hands you can easily "emulate" user imput and check (and reuse) whatever cases you want. And now lets take a look at TextBoxDoubleValidator.IsValid method:
/// <summary>
/// Helper class that validates text box input for double values.
/// </summary>
internal static class TextBoxDoubleValidator
{
private static readonly ThreadLocal<NumberFormatInfo> _numbersFormat = new ThreadLocal<NumberFormatInfo>(
() => Thread.CurrentThread.CurrentCulture.NumberFormat);
/// <summary>
/// Returns true if input <param name="text"/> is accepted by IsDouble text box.
/// </summary>
public static bool IsValid(string text)
{
// First corner case: null or empty string is a valid text in our case
if (text.IsNullOrEmpty())
return true;
// '.', '+', '-', '+.' or '-.' - are invalid doubles, but we should accept them
// because user can continue typeing correct value (like .1, +1, -0.12, +.1, -.2)
if (text == _numbersFormat.Value.NumberDecimalSeparator ||
text == _numbersFormat.Value.NegativeSign ||
text == _numbersFormat.Value.PositiveSign ||
text == _numbersFormat.Value.NegativeSign + _numbersFormat.Value.NumberDecimalSeparator ||
text == _numbersFormat.Value.PositiveSign + _numbersFormat.Value.NumberDecimalSeparator)
return true;
// Now, lets check, whether text is a valid double
bool isValidDouble = StringEx.IsDouble(text);
// If text is a valid double - we're done
if (isValidDouble)
return true;
// Text could be invalid, but we still could accept such input.
// For example, we should accepted "1.", because after that user will type 1.12
// But we should not accept "..1"
int separatorCount = CountOccurances(text, _numbersFormat.Value.NumberDecimalSeparator);
// If text is not double and we don't have separator in this text
// or if we have more than one separator in this text, than text is invalid
if (separatorCount != 1)
return false;
// Lets remove first separator from our input text
string textWithoutNumbersSeparator = RemoveFirstOccurrance(text, _numbersFormat.Value.NumberDecimalSeparator);
// Second corner case:
// '.' is also valid text, because .1 is a valid double value and user may try to type this value
if (textWithoutNumbersSeparator.IsNullOrEmpty())
return true;
// Now, textWithoutNumbersSeparator should be valid if text contains only one
// numberic separator
bool isModifiedTextValid = StringEx.IsDouble(textWithoutNumbersSeparator);
return isModifiedTextValid;
}
/// <summary>
/// Returns number of occurances of value in text
/// </summary>
private static int CountOccurances(string text, string value)
{
string[] subStrings = text.Split(new[] { value }, StringSplitOptions.None);
return subStrings.Length - 1;
}
/// <summary>
/// Removes first occurance of valud from text.
/// </summary>
private static string RemoveFirstOccurrance(string text, string value)
{
if (string.IsNullOrEmpty(text))
return String.Empty;
if (string.IsNullOrEmpty(value))
return text;
int idx = text.IndexOf(value, StringComparison.InvariantCulture);
if (idx == -1)
return text;
return text.Remove(idx, value.Length);
}
}

A comment rather than an answer, but...
I would beware of validating input on each keypress as it can have unintended consequences and annoy the end user.
For example, I remember being annoyed by a datepicker control which would not allow dates in the future, and was initialized to today's date. It performed validation after entering the day, month or year, so that it was impossible to enter a month/day later than the current date without first changing the year.
In the case of doubles, you could have a similar problem, for example your proposed validation would prevent the user from entering the perfectly valid values "-1", ".12", "1e+5":
- - invalid
-1 - valid
. - invalid
.1 - valid
1 - valid
1e - invalid
1e+ - invalid
1e+5 - valid
I would recommend validating as normal when the user leaves the textbox or explicitly validates by clicking a button.

Related

Ignore CR/LF characters embedded as part of barcode when scanned to a text box

I have a C# Winform app that reads supplier barcodes into a textbox and automatically goes to another textbox by handling Keydown event and looking for "ENTER" key press. The "ENTER" key character is automatically appended by the barcode scanner upon reading all characters of the barcode. However, I am having problems with barcodes that embed CR/LF characters which causes the Keydown event to erroneously detect it as completion of scanning and triggers transfer to the next textbox. Is it possible to ignore the CR/LF characters until all barcodes characters are already read? Or maybe just determine if all characters have been read so that this can be incorporated to the Keydown event handler to correctly determine when to trigger transfer to the other textboxes?
We use this below to capture UPS/USPS/FedEx barcodes. It is instantiated as a member variable on the Form, and then the Form.KeyPreview sends the char(s) to the KeyPress on it. It uses the hueristic that a human can't type those chars that fast, so it must be a scan. When it receives the correct length and a pattern matching one of the shipper's barcode format, it raises an event of a barcode scanned. You could probably adapt this to clean the spurious CRLF out of a scan as well.
using System;
using System.Diagnostics;
namespace YadaYada.LabelMaker.Library;
public class KeyReader
{
public delegate void ScannedEventHandler(string trackingNumber);
public static event ScannedEventHandler Scanned;
private static readonly object CurrentValueLock = new object();
private enum CurrentlyTrackingEnum
{
None = 0,
Ups = 1,
Usps = 2,
}
private static CurrentlyTrackingEnum _currentlyTracking;
private static DateTime _lastPress = DateTime.MinValue;
public static void KeyPress(char pressed)
{
lock (CurrentValueLock)
{
Debug.WriteLine($"Start:{CurrentValue}");
if (DateTime.Now.Subtract(_lastPress).Ticks > 1000000) CurrentValue = string.Empty;
_lastPress = DateTime.Now;
CurrentValue += pressed.ToString().ToUpperInvariant();
if (pressed == ']')
{
CurrentValue = string.Empty;
_currentlyTracking = CurrentlyTrackingEnum.Usps;
}
else if (CurrentValue == "1Z")
{
_currentlyTracking = CurrentlyTrackingEnum.Ups;
}
if (_currentlyTracking == CurrentlyTrackingEnum.Ups)
{
if (CurrentValue.Length == "1Z52895E0392843135".Length)
{
OnScanned(CurrentValue);
_currentlyTracking = CurrentlyTrackingEnum.None;
}
}
else if (_currentlyTracking == CurrentlyTrackingEnum.Usps)
{
if (CurrentValue.Length == "9400110298370442324568".Length)
{
OnScanned(CurrentValue);
_currentlyTracking = CurrentlyTrackingEnum.None;
}
}
Debug.WriteLine($"End:{CurrentValue}");
}
}
public static string CurrentValue { get; private set; } = String.Empty;
private static void OnScanned(string trackingnumber)
{
Scanned?.Invoke(trackingnumber);
CurrentValue = string.Empty;
}
}

How to compare KeyEventArgs to a character?

I have a TextEdit.PreviewKeyDown method where I want to check if an input character is equal to a special character of my choosing.
For an instance I want to check if the user's input character is '#'. I'd use:
if(e.Key == Key.D3 && (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
The problem is I don't know what the special character will be at the time and I can't possibly program all the cases, so I wanted something like:
string strSpecChar = GetSpecialCharacter();
if(strSpecChar = e.Key) {do_sth();}
Which doesn't work at all, because if I press, for example '3', the e.Key value will be equal to 'D3', so if my strSpecChar value is '3' I can't get to the do_sth()
I have browsed through the System.Windows.Input.KeyEventArgs docs and I've found nothing and I've also read some discouraging posts on other forums.
Is there any way I would be able to compare the PreviewKeyDown e and string strSpecChar?
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
string strNewLigneSign = String.Empty;
if (InsertTextDialogHelper != null)
strNewLigneSign = InsertTextDialogHelper.GetNewLineSign();
if (e.Key.Equals(strNewLigneSign))
{
if (!String.IsNullOrEmpty(strNewLigneSign))
{
int strCaretPosition = TextBox.CaretIndex;
e.Handled = true;
string strNewText = "\r\n";
CurrentDialogData.TextValue = CurrentDialogData.TextValue.Insert(strCaretPosition, strNewText);
TextBox.CaretIndex = strCaretPosition + strNewText.Length;
}
}
}
EDIT:
As per #mm8's suggestion I tried to implement it in the TextEdit.PreviewTextInput property as follows:
XAML
<dxe:TextEdit Name="TextBox"
PreviewTextInput="TextBox_PreviewTextInput" \">
</dxe:TextEdit>
C#
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
string strNewLigneSign = String.Empty;
if(InsertTextDialogHelper != null)
strNewLigneSign = InsertTextDialogHelper.GetNewLineSign();
if(!String.IsNullOrEmpty(strNewLigneSign))
{
if(e.Text.Contains(strNewLigneSign))
{
int strCaretPosition = TextBox.CaretIndex;
e.Handled = true;
string strNewText = Unhashify(e.Text);
CurrentDialogData.TextValue = CurrentDialogData.TextValue.Insert(strCaretPosition, strNewText);
TextBox.CaretIndex = strCaretPosition + strNewText.Length;
}
}
}
However when I run the app and set the breakpoints anywhere inside that method it seems never to go inside it.
The exact same solution worked for me back when I used it in wpf's TextBox, but as soon as I switched to devexpress, the TextBox_PreviewTextInput method is never called.
A key is a key and not a character. It's eventually mapped to a character depending on the input device.
You may want to consider handling PreviewTextInput and check the value of Text[0] of the TextCompositionEventArgs instead of handling PreviewKeyDown.

Using Linq to loop through all controls only get the first control

I have a form with 5 text boxes and a button, I want to check all these text boxes for empty or null user input.
Using this simple method:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (verifyUI() == true)
MessageBox.Show("user input for all textboxes was correct!");
else
MessageBox.Show("user input for all textboxes was missing!");
}
private bool verifyUI()
{
bool userInputOk = false;
foreach (Control cTxt in Controls.OfType<TextBox>())
{
if (string.IsNullOrWhiteSpace(cTxt.Text) || cTxt.Text == "")
{
userInputOk = false;
}
else
{
userInputOk = true;
}
}
return userInputOk;
}
}
When I enter a value in text box 1 , the method is checking only the first text box and returning true, and ignoring all other text boxes.
I am sure something is wrong in the logic of the method which I am using.
It seems you want to know if any input is wrong (or all the input is correct):
private bool verifyUI() {
return !Controls
.OfType<TextBox>()
.Any(cTxt => string.IsNullOrWhiteSpace(cTxt.Text));
}
or (equivalent All() implementation)
private bool verifyUI() {
return Controls
.OfType<TextBox>()
.All(cTxt => !string.IsNullOrWhiteSpace(cTxt.Text));
}
In your current code you constantly re-write userInputOk and so return the last value
The easiest way would be to use the All method:
private bool verifyUI()
{
return Controls.OfType<TextBox>().All(tb => !string.IsNullOrWhiteSpace(tb.Text));
}
You could also invert the logic and use the Any method as well. I prefer All in this case simply because it conveys the intention better and makes the logic more clear for the next person.
I think just for checking whether any textbox is not filled. following code is enough.
private bool verifyUI()
{
bool alluserInputsOk = true;
foreach (Control cTxt in Controls.OfType<TextBox>())
{
if (string.IsNullOrWhiteSpace(cTxt.Text))
{
userInputOk = false;
break;
}
}
return userInputOk;
}
or You can use .any() method with your list
Your code is actually only checking whether the last control in the list is blank or not, since that's where your iteration ends.
Your code checks only the last textbox it finds. Try this All() statement instead:
bool userInputOk = Controls.OfType<TextBox>()
.All(tb => !string.IsNullOrWhiteSpace(tb.Text));
Note that string.IsNullOrWhiteSpace() is true for string.Empty, too. So you don't need that extra check for string.Empty.
Actually, it's probably looping though all controls, but only returning the result of the last one, since you set the value of userInputOk back to true if the control has valid text. So the end result is the result for the last control. Now it's possible that textBox1 is the last control in the collection, depending on how they were added. You can either just remove the else block, which will flag userInputOk only if a control has an invalid value, or use Linq:
bool userInputOk =
!Controls.OfType<TextBox>()
.Any(cTxt => string.IsNullOrWhiteSpace(cTxt.Text))

Position cursor on textbox that has error

I have a simple form that takes 9 decimal numbers from 9 textboxes and I put some validation so that the users can only enter decimal numbers and nothing else.
Now the challenge I'm having is how to set the cursor in the textbox that had no decimal number after showing the error message in the try-catch statement?
Here's my code:
private void btn_Aceptar_Click(object sender, EventArgs e)
{
POI GPI = new POI();
POI VIM = new POI();
POI ST = new POI();
try
{
GPI.POI_x = Convert.ToDecimal(txt_GPIx.Text);
GPI.POI_y = Convert.ToDecimal(txt_GPIy.Text);
GPI.POI_z = Convert.ToDecimal(txt_GPIz.Text);
VIM.POI_x = Convert.ToDecimal(txt_VIMx.Text);
VIM.POI_y = Convert.ToDecimal(txt_VIMy.Text);
VIM.POI_z = Convert.ToDecimal(txt_VIMz.Text);
ST.POI_x = Convert.ToDecimal(txt_STx.Text);
ST.POI_y = Convert.ToDecimal(txt_STy.Text);
ST.POI_z = Convert.ToDecimal(txt_STz.Text);
}
catch (Exception)
{
MessageBox.Show("Ingrese solamente nĂºmeros en las variables GPI/VIM/ST", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
//Set the cursor in the first textbox that had no decimals..
return;
}
Comisurales Comisurales = new Comisurales();
Comisurales.calculo_coord_comisurales(PC, AC, IHP, GPI, VIM, ST);
}
Let me add that I also have a function to ensure the user is only limited to enter decimals but I wasn't able to figure how to avoid the "." only or this for example: "1."
As an addition to my question, here's what gets validated every time the user press a key in the textbox:
private void ValidarDecimal(object sender, KeyPressEventArgs e)
{
// permitir 0-9, backspace, y decimal
if (((e.KeyChar < 48 || e.KeyChar > 57) && e.KeyChar != 8 && e.KeyChar != 46))
{
e.Handled = true;
return;
}
// chequear solamente un decimal
if (e.KeyChar == 46)
{
if ((sender as TextBox).Text.IndexOf(e.KeyChar) != -1)
e.Handled = true;
}
}
I guess I have 2 ways to resolve my issue. Number one would be find a way to ensure the user never ever enters something weird in the textbox (which I've done partially) and number 2 would be to use the try-catch with the current limitations I mentioned above and then point the user to the textbox that has issues, both are acceptable.
The Decimal class has a TryParse method that could be used to avoid all this logic driven by catching exceptions (a very expensive approach in terms of performance)
decimal value;
if(decimal.TryParse(txt_GPIx.Text, out value))
GPI.POI_x = value;
else
{
MessageBox.Show("Invalid decimal value");
txt_GPIx.Focus();
}
Of course this code needs to be repeated for every control in your list, but you could write a generic function like this one
private decimal GetValueAndValidate(Textbox txt, out bool isOK)
{
isOK = true;
decimal value = 0m;
if(!decimal.TryParse(txt.Text, out value))
{
MessageBox.Show("Invalid decimal value");
txt.Focus();
isOK = false;
}
return value;
}
and then use the following approach in your code inside the button click
bool isOK = true;
if(isOK) GPI.POI_x = GetValueAndValidate(txt_GPIx, out isOK);
if(isOK) GPI.POI_y = GetValueAndValidate(txt_GPIy, out isOK);
.... and so on for the other fields ....
For the second part of your question, finding a way to completely control the input logic is not easy. What happens for example if your user PASTE an invalid text in your textbox? There are very edge case situations that takes a lot of effort to code correctly. It is a lot more easy to leave freedom of typing to your user and apply a strict logic when you get that input.

c# How to validate when pasting into textbox

I have written a little program. It works almost as I want, I just have one problem. I am trying to copy all functions I have found in the other program.
I have a TextBox, when the user can write a phone number. Firstly, he is only allowed to use digits and "+"and "-", so I use:
private void textBoxPhoneNumber_KeyPress(object sender, KeyPressEventArgs e)
{
if ((char.IsDigit(e.KeyChar) == false) && (e.KeyChar != '+') && (e.KeyChar != '-') && (e.KeyChar != '\b')) e.Handled = true;
}
Then I want the phone number to be in certain format (+12-34-1234567), so I use:
private bool IsPhoneNumberCorrect(string name)
{
return Regex.IsMatch(name, #"^+\+[0-9]{2}-[0-9]{2}-[0-9]{7}$", RegexOptions.None);
}
and finally this (with TextChange):
private void phoneNumberValidity(object sender, EventArgs e)
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
checkIfOk();
textBoxPhoneNumber.Focus();
}
I use counter4 as a part of method (checkIfOk) that enables button. There is also an "X" icon that changes into "tick" when the number is given in proper format.
It works perfectly for me (just like in the program I am copying) - when the user writes something in the TextBox, he can only use digits and "+" and "-" and when the format is ok the icon changes and when other textboxes are also ok, the Ok buton enables.
Now, finally, the problem:
I am able to paste something from the Clipboard. In the original program, when I paste something with letters, digits and other signs, only digits and "+" and "-" remains. My program accepts everything in such situation.
I've been looking for something that might be helpful, but all I have found was very complicated. Is there a way to do it?
I tried to do something like this. It causes that when pasting only digits and "+" and "-" remains as it should, but the user can't write anything.
I am still a beginner. Maybe I am making a simple mistake?
private void phoneNumberValidity(object sender, EventArgs e)
{
Regex regex = new Regex("[^0-9-+]");
if (regex.IsMatch(Clipboard.GetText()))
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
string output = regex.Replace(Clipboard.GetText(), "");
textBoxPhoneNumber.Text = output;
checkIfOk();
textBoxPhoneNumber.Focus();
}
}
I am trying to do something like this:
private void phoneNumberValidity(object sender, EventArgs e)
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
checkIfOk();
textBoxPhoneNumber.Focus();
Regex regex = new Regex("[^0-9-+]");
if (textBoxPhoneNumber.Text.Contains("a"))
{
if (regex.IsMatch(Clipboard.GetText()))
{
string output = regex.Replace(Clipboard.GetText(), "");
textBoxPhoneNumber.Text = output;
}
}
}
I know that it's not exactly what I want, but maybe someone can give some clues...
Generally i thought, that I'd like to check if the text in tb contains some unwanted elements, but I don't know how to check it. As you can see, it checks only one unwanted element.
First of all, please use TRY-Catch for the Convert.ToInt32 !
Second: Use TextChanged event, and validate the input with the actual content of the TextBox
To validate, you can do something similar:
string output = ""
string clipboardText = GetClipboardText()
for each chara in clipboardText's characters
if chara.isNumeric or chara=='+' or chara == '-'
output += chara
end foreach
Of course its just a simple soultion, but you can confgure it as you want.
Or if you want more complex way, you can play with the regex... Start with number or + - BUT not contains alphabetical char. Based on your request.
This is what I made, and it works :) I will only add try-catch block as Krekkon has suggested.
private void phoneNumberValidity(object sender, EventArgs e)
{
counter4 = Convert.ToInt32(IsPhoneNumberCorrect(textBoxPhoneNumber.Text));
pictureBoxPhoneNumber.Image = imageList1.Images[counter4];
if (Regex.IsMatch(textBoxPhoneNumber.Text, "[^0-9-+]"))
{
Regex regex = new Regex("[^0-9-+]");
string output = regex.Replace(Clipboard.GetText(), "");
textBoxPhoneNumber.Text = output;
}
checkIfOk();
textBoxPhoneNumber.Focus();
}
Maybe it will help someone in the future.
Maybe you should try like this: leave the first version of phoneNumberValidity method as it is and then check if the tb Text has some unwanted elements, get rid of them.

Categories

Resources