.Focus() doesn't work in TextChangedEvent - c#

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

Related

RegularExpressionValidation - is there a better way to write this?

I have a textbox that the requirements are for it to be five numeric characters followed by 3 letters that will match what was selected in a dropdownlist. This is the way I'm having it check:
protected void ddlLegalEntity_SelectedIndexChanged(object sender, EventArgs e)
{
if (ddlLegalEntity.SelectedItem.Text == "FID")
{
RegularExpressionValidator1.ValidationExpression = "^[0-9]{5}(FID)$";
}
else if (ddlLegalEntity.SelectedItem.Text == "FLM")
{
RegularExpressionValidator1.ValidationExpression = "^[0-9]{5}(FLM)$";
}
else if (ddlLegalEntity.SelectedItem.Text == "FOF")
{
RegularExpressionValidator1.ValidationExpression = "^[0-9]{5}(FOF)$";
}
And then it continues with a few more else if.......
So if in ddlLegalEntity you select the choice FLM, then the textbox will have to equal five numbers followed by FLM.
Such as...
13423FLM
56543FLM
This code works fine, but I feel like there must be an easier way to code this. maybe I'm wrong and this is the easiest way, but I'm just curious.
Maybe something like:
protected void ddlLegalEntity_SelectedIndexChanged(object sender, EventArgs e)
{
RegularExpressionValidator1.ValidationExpression = "^[0-9]{5}("+ddlLegalEntity.SelectedItem.Text+")$";
}
And better use string.Format( string, params) for this purposes;
private static readonly string validationRegEx= "^[0-9]\{5\}({0})$";
String.Format(validationRegEx, ddlLegalEntity.SelectedItem.Text);

c# TextBox how to get the last letter of a string?

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

Extract numbers from a textbox [duplicate]

This question already has answers here:
How do I make a textbox that only accepts numbers?
(41 answers)
Closed 8 years ago.
I have a textbox with both letters and numbers in and other symbols in which you can find on your keyboard. I have this code which works fine when I manually put the data in and it only lets me put numbers in and deletes letters. Everything what I want, apart from none of it works if the data is copied and pasted in. Below is my code.
private void textBox7_TextChanged(object sender, EventArgs e)
{
Exception X = new Exception();
TextBox T = (TextBox)sender;
T.Text = T.Text.Trim();
try
{
if (T.Text != "-")
{
int x = int.Parse(T.Text);
}
}
catch (Exception)
{
try
{
int CursorIndex = T.SelectionStart - 1;
T.Text = T.Text.Remove(CursorIndex, 1);
//Align Cursor to same index
T.SelectionStart = CursorIndex;
T.SelectionLength = 0;
}
catch (Exception) { }
}
}
The problem with your current code is that you're removing only the last entered character from the cursor position. Pasting text with more than a character breaks your algo.
So let's say you're pasting in 9 letters, the CursorIndex is at 9, you remove only one character (that's the T.Text = T.Text.Remove(CursorIndex, 1); line) and you're left with 8 incorrect ones left.
A better approach (which isn't overly complex like yours) would look like this :
private void textBox7_TextChanged(object sender, EventArgs e)
{
textBox7.Text = string.Concat(textBox7.Text.Where(char.IsDigit));
}
So here we're replacing on each change the text with a new text containing each characters that passes the char.IsDigit test. The cursor won't be at the good position however. Unless multiple edits in the middle of the string are expected, it's probably best to only strap a
textBox1.SelectionStart = textBox1.Text.Length;
at the end of the method, it'll handle pasted text too.
To handle the case where you don't want to erase the character - when it is the only text in your textbox, you can add an obvious if condition. Globally, it'll look like this:
private void textBox7_TextChanged(object sender, EventArgs e)
{
if (textbox7.Text != "-")
textBox7.Text = string.Concat(textBox7.Text.Where(char.IsDigit));
textBox1.SelectionStart = textBox1.Text.Length;
}
Try this. It saves the old value in a var and if the new value cannot be parsed, it reverts the text to old. Otherwise it updates old to the most recent valid value. It's a different approach then you took, but much simpler in my opinion.
string old;
private void textBox7_TextChanged(object sender, EventArgs e) {
int i;
if (textBox1.Text == "" || int.TryParse(textBox7.Text, out i)) {
old = textBox7.Text;
} else {
textBox7.Text = old;
}
}
Basically your problem is that pasting a value will only call the TextChanged event once for the entire change. Your code is relying on the event being called for each character that is put into the textbox.
It sounds like all you really want to do is filter all non numeric values after a possible negative sign. If that is the case you can do it like this.
private void textBox7_TextChanged(object sender, EventArgs e)
{
textBox7.Text = string.Concat(
textBox7.Text.Trim().Where((c,i)=>char.IsDigit(c) || (i==0 && c=='-')));
}
This code is using Linq to go through each character, after trimming leading and trailing white space, and only keeping the ones that are digits or a negative sign if it is the first character. It's equivalent to the following.
private void textBox7_TextChanged(object sender, EventArgs e)
{
StringBuilder builder = new StringBuilder()
string trimmed = textBox7.Text.Trim();
for(int i=0; i<trimmed.Length; i++)
{
char c = trimmed.Text[i];
if(char.IsDigit(c) || (i==0 && c=='-'))
{
builder.Append(c);
}
}
textBox7.Text = builder.ToString();
}
To remove non-numeric characters from the textbox's text, try a regular expression replacement using Regex.Replace
private void numericTextbox_TextChanged(object sender, EventArgs e)
{
TextBox tb = (TextBox)sender;
tb.Text = Regex.Replace(tb.Text, "\\-?[^\d]", "");
}
This will replace any non-numeric character (except a dash at the front, for negative numbers) in your text with nothing every time the text in the box changes, whether the user types something directly or pastes in text from somewhere else.
Alternatively, if you want to keep any dashes (for, say, a phone number):
tb.Text = Regex.Replace(tb.Text, "\\[^-\d]", "");

c# apply same rules to all textboxes

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.

Copy only letters from clipboard to textbox

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

Categories

Resources