get wrong textbox.TextLength in winforms - c#

I am making a simple email sender and what I want to do is to check if the textbox.text has 14 characters. If it's 14 - then text turns to green, if less it turns to red. I've encountered a problem when I type 14th character. It doesn't turn green. It does when I type another character which is not shown since I have MaxLength = 14, but I still need to type in that 15th character. Also when I try deleting characters, the string doesn't turn red with the first deleted char, but after a few. I've tried things like Regex and trim() thinking that there might be some special characters but it doesn't seem to work. I also recorded a video with the issue to make it more describing.
private void trackBox1_KeyPress(object sender, KeyPressEventArgs e)
{
trackBox1.Text = RemoveSpecialCharacters(trackBox1.Text);
trackBox1.Text = trackBox1.Text.Replace("\r\n", "\n");
errorBox.Text = trackBox1.TextLength.ToString();
if (trackBox1.TextLength < 14)
{
trackBox1.ForeColor = Color.Red;
} else if (trackBox1.TextLength == 14)
{
trackBox1.ForeColor = Color.Green;
}
trackBox1.Text.TrimEnd();
}
public static string RemoveSpecialCharacters(string str)
{
return Regex.Replace(str, "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled);
}

Instead of using the trackBox1_Keypress put your if statement in the trackBox1_TextChanged event and to count the length of the text you should use trackbox.Text.Length instead of trackbox1.TextLength
Here is a sample snippet int the TextChanged event that changes the color from red to green if the text length is greater than or equal to 14.
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text.Length <= 14)
{
textBox1.ForeColor = Color.Red;
}
else
{
textBox1.ForeColor = Color.Green;
}
}

Im not sure if trackBox1.TextLength is the proper way to get the length
trackBox1.Text.Length //try this
//and also your event
private void yourTextBox_TextChanged(object sender, EventArgs e)
{
}

Have a look at the Control.KeyPress docs... the event fires after a key has been pressed, but before the character actually enters the textbox. This means that the length you're checking is one less than the length you were expecting (unless the key just pressed was backspace, which KeyPress also catches, in which case it is one greater than the length you were expecting).

Related

(C#) Getting the index from a remove char of a TextBox WinForms

I have a TextBox where the user can add and remove text, however each char relates to a row on a DataGridView, with a variety of user-selectable options. So knowing what char is being removed is very important because the DataGridView needs to know what row must be removed.
At first, I had a simple string-compare method, but with duplicate char sequences (e.i. "aaaa") it couldn't figure out which letter was removed and defaulted to returning the index of last char in the sequence. So I went online to see if there was a way to track the text caret's position, and there is...but not for WinForms. The only aspects I found for the Caret was SelectionStart, SelectionLength and SelectionText; which will be usefully for batch remove, but not when the user hits the backbutton/deletebutton.
I'm pretty stumped right now. The "easiest" solution is switching to XAML because it tracks the Caret Position... but that feels like quiter talk. Though with that said, I still have no idea how to tackle this problem.
You can try to define the variable originalText to save origianl textbox text and textlength to save text length.
Subscribe to textBox1_Enter to give them the initial value.
private void textBox1_Enter(object sender, EventArgs e)
{
textlength = textBox1.Text.Length;
originalText = textBox1.Text;
}
Then subscribe to textBox1_TextChanged to get the deleted chars.
int textlength;
string originalText;
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textlength > textBox1.Text.Length)
{
Console.WriteLine($"You deleted the char from {textBox1.SelectionStart} to {textBox1.SelectionStart + textlength - textBox1.Text.Length - 1}");
Console.WriteLine($"deleted substring {originalText.Substring(textBox1.SelectionStart, textlength - textBox1.Text.Length)}");
}
// reset
textlength = textBox1.Text.Length;
originalText = textBox1.Text;
}

Add character every 2 characters entered to textbox Windows Phone 8

Hi i want to make textbox to enter mac adress and every 2 characters i want to automaticly add ':'
I wanted to use TextChanged event
private void MacAdressTextBox_TextChanged(object sender, TextChangedEventArgs e) {
if (MacAdressTextBox.Text.Length > 2)
MacAdressTextBox.Text += ":";
}
here i am adding : after 2 characterrs entered but after those 2 characters the app frezes ... have no idea why any help?
When the text changes MacAdressTextBox_TextChanged is triggered.
In MacAdressTextBox_TextChanged you change the text.
see step 1
your text change causes an infinite recursion on MacAdressTextBox_TextChanged.
One way to do it would be to grab the Text, remove the colons, then add them back in at the correct positions. In order to keep the app from hanging in an endless recursive loop, you can add a variable to track whether or not the text is being changed by our code or the user.
For example:
// When this is true it means our code is changing the text
private bool updatingTextWithCode = false;
private void MacAdressTextBox_TextChanged(object sender, EventArgs e)
{
if (updatingTextWithCode)
{
// Our code is doing the update, so just reset the variable
updatingTextWithCode = false;
}
else
{
// The user is updating the text, so process the contents
var newText = "";
// Store the mac address without the ':' characters
var plainText = MacAdressTextBox.Text.Replace(":", "");
// Then add ':' characters in correct positions to 'newText'
for (int i = 1; i <= plainText.Length; i++)
{
newText += plainText[i - 1];
if (i % 2 == 0) newText += ":";
}
// Set our global variable and update the text
updatingTextWithCode = true;
MacAdressTextBox.Text = newText;
MacAdressTextBox.Select(MacAdressTextBox.TextLength, 0);
}
}
UPDATE: CodeCaster correctly pointed out that this code does not allow the user to backspace over a colon. One way to fix this is to add the following event handler as well:
private void MacAdressTextBox_KeyDown(object sender, KeyEventArgs e)
{
// Disable formatting code when backspacing
if (e.KeyCode == Keys.Back) { updatingTextWithCode = true; }
}

How to restrict user to TextBox if value entered is incorrect

In my program I have a TextBox who's value must be set in a specific integer range. If it is not within this range, it should warn the user and then highlight the incorrect text inside of the TextBox for re-editing (implying that the user must enter a value that is in the correct range before they are allowed to leave the TextBox). How would I change my code so that it performs these operations?
This is what I have so far. I am using a TextChanged event. This code warns the user about the restriction breach and refocuses (I would like to highlight the value instead) on the TextBox, but does not prevent the user from clicking out of it afterward:
int maxRevSpeed;
//Max Rev Speed -- Text Changed
private void maxRevSpeed_textChanged(object sender, RoutedEventArgs e)
{
if (maxRevSpeed_textBox.Text == "" || maxRevSpeed_textBox.Text == " ")
maxRevSpeed = 0;
else
{
maxRevSpeed = Convert.ToInt32(maxRevSpeed_textBox.Text);
if (maxRevSpeed <= 0 || maxRevSpeed > 45)
{
MessageBox.Show("Reverse Sensor speed must be between 0 and 45 FPM", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
maxRevSpeed_textBox.Focus();
}
}
Please note that this question is a revisit of a former question of mine. I am aware that it may be "frowned upon" to take this approach to a TextBox, but regardless I would still like to figure out how to implement such a thing. Thank you.
Update 1:
After looking at everyone's suggestions I have updated my code:
//Max Rev Speed -- Text Changed
private void maxRevSpeed_textChanged(object sender, RoutedEventArgs e)
{
if (maxRevSpeed_textBox.Text == "" || maxRevSpeed_textBox.Text == " ") //Is Empty or contains spaces
maxRevSpeed = 0;
else if (!Regex.IsMatch(maxRevSpeed_textBox.Text, #"^[\p{N}]+$")) //Contains characters
maxRevSpeed = 0;
else
maxRevSpeed = Convert.ToInt32(maxRevSpeed_textBox.Text);
}
//Max Rev Speed -- Lost Focus
private void maxRevSpeed_LostFocus(object sender, RoutedEventArgs e)
{
if (maxRevSpeed <= 0 || maxRevSpeed > 45)
{
MessageBox.Show("Reverse Sensor speed must be between 0 and 45 FPM", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
//Supposed to highlight incorrect text -- DOES NOT WORK
maxRevSpeed_textBox.SelectionStart = 0;
maxRevSpeed_textBox.SelectionLength = maxRevSpeed_textBox.Text.Length;
}
}
The integer representing the text in the textBox is now dealt with in the textChanged event. The LostFocus event handles the warning and the re-selection of the incorrect text value. However, the highlight text method works when it is in the textChanged event, but not in it's current location. Why is that, and how can I fix it?
If you just want to stop focus from leaving a TextBox, all you need to do is to set the Handled property of the KeyboardFocusChangedEventArgs object to true in a PreviewLostKeyboardFocus handler when your invalid condition is true:
private void PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = IsInvalidValue;
}
This of course assumes that you have a property named IsInvalidValue that you set to true when the entered data is invalid and false otherwise.
You can prevent the user from entering the text or out of range by using PreviewTextInput handler of textbox, call it like this.
private void textBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (!char.IsDigit(e.Text, e.Text.Length - 1))
{
e.Handled = true;
}
}
The code above is for entering numbers only, you can change it according to your requirements, hope it helps :)
Hi I suppose you are using C#, here you can find a relevant post: C# auto highlight text in a textbox control
As they stated the following code should select the text inside texbox
In Windows Forms and WPF:
maxRevSpeed_textBox.SelectionStart = 0;
maxRevSpeed_textBox.SelectionLength = textbox.Text.Length;

C# - format specific number using format.string in runtime (live) on texbox

i made code to format number when total lengh is == 11, it run on texbox change, but only format when it have 11 characters, i would like to make it on runtime (live), understood ? Its possible ? See my code:
private void textBox3_TextChanged(object sender, EventArgs e)
{
Int64 cpf = Convert.ToInt64(textBox3.Text);
if (textBox3.TextLength == 11)
{
textBox3.Text = string.Format(#"{0:000\.000\.000-00}", Convert.ToInt64(cpf));
}
}
Thanks
As lazyberezovsky stated, use a masked textbox, but set the PromptChar to whatever you want. Something along the lines of:
//In your form_load
//Based on your code above, assuming textBox3 is a MaskedTextbox
textBox3.KeyUp += CheckEvent()
textBox3.Mask = "000000000000";
textBox3.PromptChar = 'x'; //set this to a space or whatever you want ' ' for blank!
//check AFTER every key press
private void CheckEvent(object Sender, KeyEventArgs e)
{
if(textBox3.Text.Count() < 12)
{
return;
}
//change the textboxMask when all chars present
maskedTextBox1.Mask = "0:000.000.000-00";
}
Consider to use MaskedTextbox with Mask equal to 000.000.000-00. It will fill mask in usual way from left to right. Input will look like:
___.___.___-__
When use types 1 it will show 1__.___.___-__.
When use types 12 it will show 12_.___.___-__. And so on.

WPF (with C#) TextBox Cursor Position Problem

I have a WPF C# program where I attempt to delete certain characters from a text box at TextChanged event. Say, for instance, the dollar sign. Here is the code I use.
private void txtData_TextChanged(object sender, TextChangedEventArgs e)
{
string data = txtData.Text;
foreach( char c in txtData.Text.ToCharArray() )
{
if( c.ToString() == "$" )
{
data = data.Replace( c.ToString(), "" );
}
}
txtData.Text = data;
}
The problem I have is that whenever the user enters $ sign (Shift + 4), at the TextChanged event it removes the $ character from the textbox text alright, but it also moves the cursor to the BEGINNING of the text box which is not my desired functionality.
As a workaround I thought of moving the cursor the the end of the text in the text box, but the problem there is that if the cursor was positioned at some middle position then it would not be very user friendly. Say, for instance the text in the textbox was 123ABC and if I had the cursor after 3, then moving the cursor to the end of the text would mean that at the next key stroke user would enter data after C, not after 3 which is the normal functionality.
Does anybody have an idea why this cursor shift happens?
Its not an answer to your question, but probably a solution for your problem:
How to define TextBox input restrictions?
If it is overkill for you, set e.Handled = true for all characters you want to avoid in PreviewKeyDown (use Keyboard.Modifiers for SHIFT key) or PreviewTextInput.
Try TextBox.CaretIndex for restoring cursor position in TextChanged event.
Hope it helps.
You can use the Select function of TextBox to change the cursor position.
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
textBox1.Text = textBox1.Text.Replace("$", "");
textBox1.Select(textBox1.Text.Length, 0);
}
You can see more about Position the Cursor on the MSDN
You can use the SelectionStart property of the textbox. Probably something along these lines should work:
private void txtData_TextChanged(object sender, TextChangedEventArgs e)
{
var pos = txtData.SelectionStart;
string data = txtData.Text.Replace("$", "");
txtData.Text = data;
txtData.SelectionStart = pos;
}
You can try Regular Expression
Sample
1) Use PreviewTextInput="CursorIssueHandler" in .xaml file
2) In your .cs file ,write the below code:
private void CursorIssueHandler(object sender, TextCompositionEventArgs e)
{
var TB = (sender as TextBox);
Regex regex = new Regex("[^0-9a-zA-Z-]+");
bool Valid = regex.IsMatch(e.Text);
//System.Diagnostics.Debug.WriteLine(Valid); // check value for valid n assign e.Handled accordingly your requirement from regex
e.Handled = Valid;
}

Categories