private void inputBox_KeyPress(object sender, KeyPressEventArgs e)
{
stringScan();
var regex1 = new Regex(#"[^+^\-^\b^\r\n]");
var regex2 = new Regex(#"[^0-9^+^\-^/^*^#^\b^\r\n]");
if (ListBox.Items.Count == 0 && string.IsNullOrWhiteSpace(inputBox.Text))
{
if (regex1.IsMatch(e.KeyChar.ToString()))
{
e.Handled = true;
toolTip1.Show("Plus or minus first then followed by numbers.", inputBox, 1500);
}
}
else
{
if (regex2.IsMatch(e.KeyChar.ToString()))
{
e.Handled = true;
}
}
}
public void stringScan()
{
char last_char = inputBox.ToString()[inputBox.ToString().Length - 1];
Console.WriteLine(last_char);
}
How can i get the last letter/number of a string?. Its really hard to explain so I'll show some screenshots.
the output should show "0" not "1".
It always show the "previews last" and not the latest one that i typed in the textbox.
Remember, when the event inputBox_KeyPress is raised, the typed key isn't added yet. Also, don't use regex for this. It will be overcomplicated.
Try the TextChanged event.
Text box key change will be executed every time u change the content of the text box
So for every value u enter u will be calling the string scan
This can be limited if u know what length the text is going to be
What about you try this:
public void stringScan()
{
String last_char = inputBox.ToString();
Console.WriteLine(last_char[last_char.Length-1]);
}
If you want last typed char I suggest:
private void inputBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
Console.WriteLine(e.Text);
}
If you want last char in textbox I suggest TextChanged event as already told by Jeroen van Langen:
private void inputBox_TextChanged(object sender, TextChangedEventArgs e)
{
string inputString = ((TextBox)sender).Text;
char lastChar = inputString.Last();
Console.WriteLine(lastChar);
}
Hope code samples help you
Edit:
Now I get that you probably want to get integer from textbox, if that's the matter, Get integer from Textbox could help you, code sample:
private void inputBox_TextChanged(object sender, TextChangedEventArgs e)
{
string inputString = ((TextBox)sender).Text;
int valueFromTextBox;
if (int.TryParse(inputString, out valueFromTextBox))
{
//parsing successful
}
else
{
//parsing failed.
}
}
Related
I have implemented some code in my Windows Form C# program, and the problem is that I want to have the following code in TextChangeEvent instead of the Validating event, but the .Focus() and .Select() methods don't work.
What is the solution for this?
private void jTextBox5_TextChangeEvent(object sender, EventArgs e)
{
if (jTextBox5.TextValue != "John")
{
jTextBox5.Focus();
}
}
You could try:
private void jTextBox5_TextChangeEvent(object sender, EventArgs e)
{
if (jTextBox5.Text.ToUpper().Trim() != "JOHN")
{
((Textbox)sender).Focus();
}
If you're trying to enforce that the user can only type the word "John" into the textbox, and you want to validate this on each key press, then you can do something like the following code, which examines the current text, one character at a time, and compares each character to it's counterpart in the word "John".
If a character doesn't match, then we set the text to only the substring of characters that do match, so they can continue typing:
private void jTextBox5_TextChanged(object sender, EventArgs e)
{
var requiredText = "John";
// Don't allow user to type (or paste) extra characters after correct word
if (jTextBox5.Text.StartsWith(requiredText))
{
jTextBox5.Text = requiredText;
}
else
{
// Compare each character to our text, and trim the text to only the correct entries
for (var i = 0; i < jTextBox5.TextLength; i++)
{
if (jTextBox5.Text[i] != requiredText[i])
{
jTextBox5.Text = jTextBox5.Text.Substring(0, i);
break;
}
}
}
// Set the selection to the end of the text so they can keep typing
jTextBox5.SelectionStart = jTextBox5.TextLength;
}
I have several text boxes and would like to format them all the same way with these rules:
// limits to number, control keys, and decimal
// goes to the next text box when enter
private void tb_text1_KeyPress_1(object sender, KeyPressEventArgs e)
{
string newString = Regex.Replace(tb_text1.Text, "[^.0-9]", "");
tb_text1.MaxLength = 6;
e.Handled = (!char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar) && e.KeyChar != '.');
if (e.KeyChar == (char)(Keys.Enter))
{
this.GetNextControl(ActiveControl, true).Focus();
}
}
// removes restricted chars
private void tb_text1_Enter(object sender, EventArgs e)
{
tb_text1.Text = Regex.Replace(tb_text1.Text, "[^.0-9]", "");
}
// applies format at exit
private void tb_text1_Leave(object sender, EventArgs e)
{
tb_text1.Text = string.Format("{0,-6} [Ohm]", decimal.Parse(tb_text1.Text));
}
What is the best way? create a new text box class based on the text box?
Thanks.
Replace in methods your "tb_text1" variable to the "((TextBox)sender)", and now You can use Your code for any textbox.
It is very easy to do it with javascript . Please try that. I have done it i'm not able to find piece of that code right now . It is worth the effort because it will be very fast and will be running on client side.
I'm struggling with copying only letters from clipboard to textbox. I've tried to filter the clipboard and replacing it with only letters with regex, but I want to clipboard stay untouched.
I've tried:
private void Schowek()
{
string schoweczek;
if (Clipboard.ContainsText())
{
schoweczek = Clipboard.GetText();
var schoweczek2 = Regex.Replace(schoweczek, #"[\d-]", string.Empty);
Clipboard.SetText(schoweczek2);
}
}
and
private void textBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
Schowek();
}
}
but I think it's not the most efficient way to do that.
UPDATE:
I've come up with sth like this, tho it's not working:
private void textBox1_TextChanged(object sender, EventArgs e)
{
string checkstr=textBox1.Text;
char[] checkchar = checkstr.ToCharArray();
for (int i = 0; i < checkstr.Length; i++)
{
if (Char.IsLetter(checkchar[i])){
}
else
{
checkchar[i] = '\0';
}
}
checkstr=String.Join("", checkchar);
textBox1.Text = textBox1.Text + checkstr;
Instead of trying to hack the native paste function into pasting something other than what is in the clipboard, or changing the contents of the clipboard, you can just subscribe to an event of the textbox and "correct" it's value there.
If you are okay with allowing the user to input anything into the textbox and then cleaning the value once they move to the next control, use the validation events which will only fire after you move to the next field.
If you want instant correction, use the text changed event. But be careful about the amount of code you run in this event as it will fire multiple times rapidly when the user is typing in it. If possible, use the event that only fires after the textbox looses focus.
There is no need to touch the Clipboard at any point for what you are trying to do.
[EDIT]
Also, be wary of disallowing characters in people's names. There are lots of people who have numbers and weird characters in their names.
Falsehoods Programmers Beleive About Names
try this code
string strClip = Clipboard.GetText();
string textvalue = Regex.Replace(strClip, #"\d", "");
first you copy the text from the Clipboard the you replace the digits with "".It work fine i test it.
Take another point of view:
Consider "being" the textbox and watching what is entered or pasted. Then drop anything that is not allowed or (better user experience): allow any input, but deny "OK" and show an error until only valid input is present.
A very common way to achive this for a specific textbox instance is this:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
// pseudo-code, fell free to implement it yourself.
if(!IsAllowed(e.KeyChar))
e.Handled = true;
}
private readonly char[] allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
private bool IsAllowed(char c)
{
return allowed.Contains(c);
}
Update
You could use a MaskedTextBox but I think your teacher will consider this cheating ;)
I could think of:
private bool reenter = false;
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (reenter || String.IsNullOrEmpty(textBox1.Text)) return;
var in = textBox1.Text.ToCharArray();
var out = Filter(input).ToArray();
var output = new String(out);
if (!textBox1.Text.Equals(output))
{
reenter = true;
textBox1.Text = output;
reenter = false;
}
}
private IEnumerable<char> Filter(IEnumerable<char> input)
{
foreach(var c in input)
if (IsAllowed(c))
yield return c;
}
Update 2
I just modified your own solution a bit.
First you have to prevent the TextChanged event from fireing multiple times (it fires also if you set the Text from code). You can either set a boolean variable like I did with reenter in my previous example or compare text and new text and only set it's value if different.
Setting a value inside the array to '\0' is wrong because \0 is the string terminator and every char after that is ignored. So if you paste a1b from the clipboard you get a char array { 'a', '\0', 'b' }. NET does not need a string terminator so you would see the result as "a\0b" but if you set the textbox value it will be only a not ab
Anyway, this is my solution. It uses another array and I also memorize SelectionStart to prevent the cursor from jumping to the first position after the text changes.
private void textBox1_TextChanged(object sender, EventArgs e)
{
string checkstr = textBox1.Text;
char[] checkchar = checkstr.ToCharArray();
char[] newchar = new char[checkstr.Length];
int pos = 0;
for (int i = 0; i < checkstr.Length; i++)
{
if (Char.IsLetter(checkchar[i]))
{
newchar[pos] = checkchar[i];
pos++;
}
}
checkstr = String.Join("", newchar);
if (textBox1.Text != checkstr)
{
var start = textBox1.SelectionStart;
textBox1.Text = checkstr;
textBox1.SelectionStart = start;
}
}
I have one TextBox with binding on DateTime type. I need to get a dot after first 2 chars and second 2 chars, for example: 12.12.1990.
I'm using behavior in TextChanged event, that code:
void tb_TextChanged(object sender, TextChangedEventArgs e)
{
int i = tb.SelectionStart;
if (i == 2 || i == 5)
{
tb.Text += ".";
tb.SelectionStart = i + 1;
}
}
That is working, but if I want to delete text by backspace, obviously I can't delete dots, because event is called again.
What is better way to solve it?
Solved
It works
But if you can, you may fix my algorithm.
public string oldText = "";
public string currText = "";
private void TextBox1_TextChanged(object sender, TextChangedEventArgs e)
{
oldText = currText;
currText = TextBox1.Text;
if (oldText.Length > currText.Length)
{
oldText = currText;
return;
}
if (TextBox1.Text.Length == currText.Length)
{
if (TextBox1.SelectionStart == 2 || TextBox1.SelectionStart == 5)
{
TextBox1.Text += ".";
TextBox1.SelectionStart = TextBox1.Text.Length;
}
}
}
I would do it in the KeyPress event, so you can filter by what kind of key it was (using the KeyChar argument with Char.IsLetter() and similar functions).
Also, add the dot when the next key is pressed. If the user has typed "12", don't add a dot yet. When the user presses 1 to add the second "12", add it then (before the new character).
Use String Format in the xaml control like so
StringFormat='{}{0:dd.MM.yyyy}'
I just tested it and this will even convert slashes to the dots.
For example
<TextBox.Text>
<Binding Path="Person.DateOfBirth" UpdateSourceTrigger="LostFocus" StringFormat='{}{0:dd.MM.yyyy}'></Binding>
</TextBox.Text>
If you are using a datepicker then you will need to override its textbox template as in the link below with the String Format above.
This link may help if if you are trying to apply it to a datepicker.
I recommend you to use a DateTimePicker and change its Format property to Short. Another option is to change your TextBox to a MaskedTextBox and changing its Mask property to ShortDate (00/00/0000) .DateTimePicker allows you not to do much about validating datetime values. But if you use a MaskedTextBox you should validate it. Sample link shows how to do validation.
I have modified above code
private void txt_in1_TextChanged(object sender, TextChangedEventArgs e)
{
int i = txt_in1.SelectionStart;
if (bsp1 != 1)
{
if (i == 2)
{
txt_in1.Text += ":";
txt_in1.SelectionStart = i + 1;
}
}
}
private void txt_in1_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Back)
{
bsp1 = 1;
}
else
{
bsp1 = 0;
}
}
I have taken another event which is keyup (equivalent keypress event), In that whenever backspace is detected it will flag bsp1 variable, which intern stop the text change event to put ":". here "bsp1" is define as global variable. (Code is for wpf, c#).
I have a problem that is haunting me for a while. I tried some solutions but they didn't worked.
I have a textbox that is for cash input ($999,99 for example). However I need to automatically input the "," and "." to display the value correctly.
I tried two solutions. One of them is this:
private void tx_ValorUnidade_TextChanged(object sender, EventArgs e)
{
string value = tx_ValorUnidade.Text.Replace(",", "").Replace("R$", "");
decimal ul;
//Check we are indeed handling a number
if (decimal.TryParse(value, out ul))
{
//Unsub the event so we don't enter a loop
tx_ValorUnidade.TextChanged -= tx_ValorUnidade_TextChanged;
//Format the text as currency
tx_ValorUnidade.Text = string.Format(System.Globalization.CultureInfo.CreateSpecificCulture("pt-BR"), "{0:C2}", ul);
tx_ValorUnidade.TextChanged += tx_ValorUnidade_TextChanged;
}
}
The result, however, is very weird.
The other one is this:
private void tx_ValorUnidade_KeyUp(object sender, KeyEventArgs e)
{
if (!string.IsNullOrEmpty(tx_ValorUnidade.Text))
{
System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-US");
int valueBefore = Int32.Parse(tx_ValorUnidade.Text, System.Globalization.NumberStyles.AllowThousands);
tx_ValorUnidade.Text = String.Format(culture, "{0:N0}", valueBefore);
tx_ValorUnidade.Select(tx_ValorUnidade.Text.Length, 0); *
}
}
This one kinda works, but there is a issue: if the user wants to insert somethink like $10,00 it can't. It also crashes after 5 numbers.
For original reference, I got the 2 codes from other questions here.
How can I fix it? Am I using the examples wrong? Any thought is welcome.
I think you will be better off when formatting when the user moves to the next control, e.g. like below. Otherwise it will be very confusing as the text will change itself as the user is typing:
private void textBox1_Leave(object sender, EventArgs e)
{
Double value;
if (Double.TryParse(textBox1.Text, out value))
textBox1.Text = String.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:C2}", value);
else
textBox1.Text = String.Empty;
}
Some people might want to actually format a textbox as they type. So this is my solution if anyone is looking for one.
It actually assumes you are entering one digit at a time so therefore as you press "1" it assumes "$0.01" and when they press "2" it then assumes "$0.12" and so on and so forth.
I could not find anything online about formatting as they typed. It has been tested and if any errors let me know.
private void textBox1_TextChanged(object sender, EventArgs e)
{
//Remove previous formatting, or the decimal check will fail including leading zeros
string value = textBox1.Text.Replace(",", "")
.Replace("$", "").Replace(".", "").TrimStart('0');
decimal ul;
//Check we are indeed handling a number
if (decimal.TryParse(value, out ul))
{
ul /= 100;
//Unsub the event so we don't enter a loop
textBox1.TextChanged -= textBox1_TextChanged;
//Format the text as currency
textBox1.Text = string.Format(CultureInfo.CreateSpecificCulture("en-US"), "{0:C2}", ul);
textBox1.TextChanged += textBox1_TextChanged;
textBox1.Select(textBox1.Text.Length, 0);
}
bool goodToGo = TextisValid(textBox1.Text);
enterButton.Enabled = goodToGo;
if (!goodToGo)
{
textBox1.Text = "$0.00";
textBox1.Select(textBox1.Text.Length, 0);
}
}
private bool TextisValid(string text)
{
Regex money = new Regex(#"^\$(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$");
return money.IsMatch(text);
}
To make it look nice I'd recommend starting the text box with the text $0.00 on the form load like so:
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Text = "$0.00";
textBox1.SelectionStart = inputBox.Text.Length;
}
Just a slight modification to GreatNates answer.
private bool KeyEnteredIsValid(string key)
{
Regex regex;
regex = new Regex("[^0-9]+$"); //regex that matches disallowed text
return regex.IsMatch(key);
}
and insert this method into the textboxs preview input event like this.
private void TextBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = KeyEnteredIsValid(e.Text);
}
That way you make sure that you can't make any mistakes when typing anything. You are limited to numbers only with my methods, while nates methods are formatting your string.
Cheers.
We can try following one as well.
txtCost.Text = String.Format("{0:c2}", myObj.Cost);
I struggled with this for hours too. I tried to use maskedTextBox but that was just clunky for the users to enter text. I also didn't like having to deal with the masking for calculations. I also looked into using the databinding formatting but that just seemed overkill.
The way I ended up going was not to use a TextBox for inputting numbers. Use the NumericUpDown object instead. No need conversion and you can set your decimals and thousands commas in the properties if you like ;) I set my increment to 1000 since i was dealing with income.
Do be aware that the .Text that comes through will have commas when there is a penny decimal and amount over 1000 (i.e. 1,000.01) , otherwise the decimal and trailing 0s are dropped.
I also found this short and sweet solution which worked well but was unneccesary with numericUpDown. You can put this on leave event.
Decimal val;
if (Decimal.TryParse(TxtCosPrice.Text, out val))
TxtCosPrice.Text = val.ToString("C");
else
MessageBox.Show("Oops! Bad input!");
This is my solution, it puts only dots, not money symbol. Hope can help somenone.
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = TextBox2Currency((TextBox)sender, e.KeyValue);
}
private bool TextBox2Currency(TextBox sender,int keyval)
{
if ((keyval >= 48 && keyval <= 58) || keyval == 46 || keyval == 8)
{
int pos = sender.SelectionStart;
int oriLen = sender.Text.Length;
string currTx = sender.Text.Replace(".", "").ToCurrency();
int modLen = currTx.Length;
if (modLen != oriLen)
pos += (modLen - oriLen);
sender.Text = currTx;
if ( pos>=0)
sender.SelectionStart = pos;
return false;
}
return true;
}