So, I am looking for the best way to get the text that has changed either using the keyPressed event, put preferably the TextChanged event. What I'm looking for is what has been changed. I have a program that should send events to another window and populate the rich textbox there with a color. I tried the following using the keyPressed event:
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
char keyChar = (char) e.KeyChar;
if (Char.IsLetterOrDigit(keyChar) || Char.IsSeparator(keyChar)
|| Char.IsWhiteSpace(keyChar))
{
string changedText = keyChar.ToString();
VinduEventArgs ve = new VinduEventArgs(colorDialog1.Color, changedText);
VinduEndret(this, ve);
}
}
But it doesn't really work as it's buggy, doesn't show all signs, and seems kindof like a bad solution.
Related
I have a TextBox which I use in Settings page of my app. Now, this textbox should only accept/display digits. There are several examples and solutions for this problem however, none of them work for WinUI 3 as they are mostly from 5-10 years ago.
KeyPress event does not exists in WinUI 3 TextBox. While looking for alternatives I saw KeyDown event however this event arguments are different and KeyRoutedEventArgs do not contain any property like KeyChar.
The example code I found that's applicable for WPF applications:
private void txtbox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
How can I achieve this behaviour in WinUI 3 TextBox?
You can use InputScope!
You can find a reference from the Microsoft docs.
Here's an example from Microsoft:
<TextBox Header="Telephone Number" InputScope="TelephoneNumber"/>
You can also do further verifications in the code-behind by listening to the TextChanged event:
<TextBox TextChanged="OnTextChanged" />
<!-- In your code-behind file -->
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
// Get the current text of the TextBox
var text = ((TextBox)sender).Text;
// Use a regular expression to only allow numeric values
var regex = new Regex("^[0-9]*$");
// If the text does not match the regular expression, undo the change
if (!regex.IsMatch(text))
{
((TextBox)sender).Undo();
}
}
Edit:
In WinUI 3, you can use KeyDown event too.
It's very similar to the way you did in WPF:
<TextBox KeyDown="OnKeyDown" />
private void OnKeyDown(object sender, KeyRoutedEventArgs e)
{
// Check if the key pressed is a numeric key
if (!((e.Key >= VirtualKey.Number0 && e.Key <= VirtualKey.Number9) || (e.Key >= VirtualKey.NumberPad0 && e.Key <= VirtualKey.NumberPad9)))
{
// If the key is not numeric, cancel the event and prevent the key from being entered
e.Handled = true;
}
}
#Link Hylia's answer was somehow correct in achieving the behaviour requested. I expanded on that answered by:
Changed the event used. The KeyDown or TextChanged events were asynchronous events and would not block the entered input to appear on the screen. I changed this to TextChanging event which is run synchronously and before the TextBox.Text is rendered. Using this method, I can control the text before its rendered and improve UX.
Instead of undoing, I now do just remove the char entered from the text and pass it back to the TextBox.
I put the cursor back to where it was before so that the user can continue typing from where they left.
The code can be found below:
private void textBox1_TextChanging(TextBox sender, TextBoxTextChangingEventArgs args)
{
var currentPosition = textBox1.SelectionStart - 1;
var text = ((TextBox)sender).Text;
var regex = new Regex("^[0-9]*$");
if(!regex.IsMatch(text))
{
var foundChar = Regex.Match(textBox1.Text, #"[^0-9]");
if(foundChar.Success)
{
textBox1.Text = textBox1.Text.Remove(foundChar.Index, 1);
}
textBox1.Select(currentPosition, 0);
}
}
I have a textbox in my winform in which after puting a validation using regex on keypress event, the default functionalities like copy paste etc of the textbox is not working.
How can i handle this?
Regex used code
private void textbox_keypress(object sender,keypresseventargs e)
{
var regex= new regex(#"^[0-9,]*$");
if(!regex.ismatch(e.keychar.tostring()))
{
e.handled=true;
}
}
after removing the keypress event handler everything is working fine but i have to restrict user to enter comma separated number value and also copy paste delete backspace in that textbox.
The Ctrl-Commands don't work because you abort their entries. To avoid this you must either
check if the Ctrl-Key has been pressed. The KeyPress event doesn't tell you that. This example from MSDN shows you how to do it: You script the KeyDown event to set (or clear) a flag variable, which you can then test in the KeyPress. No, not exactly elegant imho, but that's how MS tells you to do it.. (Note that I have added the Backspace code \b, as it isn't covered by the Ctrl-check..)
bool ctrlPressed = false;
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
ctrlPressed = (Control.ModifierKeys == Keys.Control);
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!ctrlPressed)
{
var regex= new Regex(#"^[0-9,\b]*$");
if (!regex.IsMatch(e.KeyChar.ToString()))
{
e.Handled = true;
}
}
}
Or, if you want better control over which Ctrl-Keys are allowed, skip the whole flags-affair and instead simply include them one by one in the allowed keys-brackets like this for ^C, ^X, ^A, ^V ^Z etc..:
var regex= new Regex(#"^[0-9,\b\cC\cX\cA\cV\cZ]*$");
Here is the description from MSDN:
\cX Matches an ASCII control character, where X is the letter of the
control character. For example, \cC is CTRL-C.
On a side note: The old fashioned copy&paste commands of Ctl-Ins and Shift-Ins work as normal even in your original code.
I have RichTextBox and I want to calculate the length of text entered in the KeyDown event. The problem is for characters in capital form I have to press Shift which is also getting calculated in the length. See the following code:
private void rtfText_KeyDown(object sender, KeyEventArgs e)
{
if (e.Modifiers != Keys.Shift)
{
var val = (char)e.KeyValue;
string _typed += val;
}
}
For texts like Win with capital W the length of _typed is shown as 4 where as it should be 3. How to solve this ? I wrote the above code to overcome this but now the length is shown as 2 instead of 3 because of suppressing Shift.
Just change your code to this:
private void rtfText_KeyDown(object sender, KeyEventArgs e)
{
if (!char.IsControl((char)e.KeyValue))
{
var val = (char)e.KeyValue;
string _typed += val;
}
}
that way if a control key is pressed you won't count it or aggregate it to your string.
(PS: control keys are shift, ctrl ...)
see this link: http://msdn.microsoft.com/fr-fr/library/18zw7440(v=vs.95).aspx
it lists the control characters and explains what exactly the method char.IsControl does
EDIT: actually there is quite a lot of situations where it won't work. Of course you can try to handle every specific situation (such as backspace, ctrl+V...) but the simplest way would be to use the TextLenght property and the TextChanged event
You should just get the TextLength property from the ritch text box directly:
var textLength = rtfText.TextLength
I am using c# winform.
I have 2dimensional array of text boxes I want them to accept only Letters from A-I I've created the method but that works for only one text box.
Here is my code:
textbox[i,j].Validated+=new EventHandler(TextBox_KeyPress);
private void TextBox_KeyPress(object sender, EventArgs e)
{
bool bTest = txtRegExStringIsValid(textbox[1,1].Text.ToString());
ToolTip tip = new ToolTip();
if (bTest == false)
{
tip.Show("Only A-I", textbox[1,1], 2000);
textbox[1,1].Text = " ";
}
}
private bool txtRegExStringIsValid(string textToValidate)
{
Regex TheRegExpression;
string TheTextToValidate;
string TheRegExTest = #"^[A-I ]+$";
TheTextToValidate = textToValidate;
TheRegExpression = new Regex(TheRegExTest);
if (TheRegExpression.IsMatch(TheTextToValidate))
{
return true;
}
else
{
return false;
}
}
Can anyone please guide what should I do make this code work for all text boxes?
if this works for textbox[1,1] you could register your private void TextBox_KeyPress(object sender, EventArgs e) as eventhandler for all your textboxes and instead of textbox[1,1] you could use ((TextBox)sender)
i want text boxes to accept only letters from a-i actually i am trying to make sudoku
There's a much simpler solution than regular expressions, and you don't even need to handle the Validated event to implement it.
In a situation like this, where there are only certain characters that you want to prevent the user from entering, handling the KeyDown event is a much better solution. The user gets immediate feedback that the letter they tried to enter was not accepted. The alternative (the Validating and Validated events) actually wait until the user tries to leave the textbox to rudely alert them that their input was invalid. Especially for a game, this tends to break concentration and isn't particularly user-friendly.
Doing it this way also makes it irrelevant which individual textbox raised the event. Instead, you will handle it the same way for all of the textboxes—by completely ignoring all invalid input.
Here's what I'd do:
First, attach a handler method to your textbox's KeyDown event. You can do this from the Properties window in the designer, or you can do it through code, as you have in the question:
textbox[i,j].KeyDown += TextBox_KeyDown;
Then, you need to put the logic into your event handler method that determines if the key that the user just pressed is in the allowed range (A through I), or outside of it:
private void TextBox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
// Determine if the keystroke was a letter between A and I
if (e.KeyCode < Keys.A || e.KeyCode > Keys.I)
{
// But allow through the backspace key,
// so they can correct their mistakes!
if (e.KeyCode != Keys.Back)
{
// Now we've caught them! An invalid key was pressed.
// Handle it by beeping at the user, and ignoring the key event.
System.Media.SystemSounds.Beep.Play();
e.SuppressKeyPress = true;
}
}
}
If you want to restrict the user to typing in only one letter, you can add code to handle that in the above method, or you can take an even simpler route and let the textbox control handle it for you automatically. To do that, set the MaxLength property of the textbox to true, either in the designer or through code:
textbox[i,j].MaxLength = true;
Check the text of the sender instead of whatever textbox[1,1] is.
Use the sender parameter of the event handler to identify the textbox responsible for the event.
The first thing that will help you is casting the sender of your event to a TextBox like this:
(Also, as Cody Gray said, this is a TextBox_Validated event, not a KeyPress event so I've renamed it appropriately)
private void TextBox_Validated(object sender, EventArgs e)
{
TextBox tb = sender as TextBox()
if (sender == null)
return;
bool bTest = txtRegExStringIsValid(tb.Text.ToString());
ToolTip tip = new ToolTip();
if (bTest == false) {
tip.Show("Only A-I", tb, 2000);
tb .ext = " ";
}
Next you need to actually get into that code for every textbox. There are two obvious approaches to that, you can either assign the eventhandler to each textbox in the array or you can use a custom textbox which always does this validation and then add that to your array.
Assign eventhandler to textboxes
foreach(var tb in textbox)
{
tb.Validated += new EventHandler(TextBox_KeyPress);
}
Create custom textbox control
Create the custom text box control (Add a user control to the project) and then just use it exactly as you would a normal textbox.
public partial class ValidatingTextBox: TextBox
{
public ValidatingTextBox()
{
InitializeComponent();
}
protected override void OnValidating(CancelEventArgs e)
{
bool bTest = txtRegExStringIsValid(this.Text.ToString());
ToolTip tip = new ToolTip();
if (bTest == false)
{
tip.Show("Only A-I", this, 2000);
this.Text = " ";
}
}
private bool txtRegExStringIsValid(string textToValidate)
{
// Exactly the same validation logic as in the same method on the form
}
}
I have prevented numbers from being typed in text box using key down event. But when using Ctrl+V or pasting content through mouse, the numbers are being entered in the text box. How to prevent this? I have to allow all text to be pasted/typed except numbers.
On quite simple approach would be to check the text using the TextChanged event. If the text is valid, store a copy of it in a string variable. If it is not valid, show a message and then restore the text from the variable:
string _latestValidText = string.Empty;
private void TextBox_TextChanged(object sender, EventArgs e)
{
TextBox target = sender as TextBox;
if (ContainsNumber(target.Text))
{
// display alert and reset text
MessageBox.Show("The text may not contain any numbers.");
target.Text = _latestValidText;
}
else
{
_latestValidText = target.Text;
}
}
private static bool ContainsNumber(string input)
{
return Regex.IsMatch(input, #"\d+");
}
This will handle any occurrence of numbers in the text, regardless of where or how many times they may appear.
use the TextBox.TextChanged event. Then use the same code as you have in the KeyDown event. In fact, you no longer need the keydown event
You can use the JavaScript change event (onchange) instead of the keydown event. It'll check only when the user leaves the textbox though.