Reputation: 2681
I have a TextBox
where a user is meant to enter a product code that looks like this:
XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
What I'm trying to do is automatically placing the dashes in the right place as the user is typing, so that they only have to enter the actual code itself (similar to what's done in various pieces of software).
The problems I'm encountering have got to do with the position of the cursor as the user is typing.
My current solution (partially working) is as the following:
private void textBoxProductKey_KeyPress(object sender, KeyPressEventArgs e)
{
if (char.IsControl(e.KeyChar))
{
return;
}
if (!char.IsLetterOrDigit(e.KeyChar) || textBoxProductKey.Text.Length == 29)
{
e.Handled = true;
return;
}
var cursorPosition = textBoxProductKey.SelectionStart;
string text;
if (cursorPosition == 0)
{
text = e.KeyChar + textBoxProductKey.Text;
}
else if (cursorPosition == textBoxProductKey.Text.Length)
{
text = textBoxProductKey.Text + e.KeyChar;
}
else
{
text = textBoxProductKey.Text.Insert(cursorPosition, e.KeyChar.ToString());
}
text = Regex.Replace(text, "-", "");
text = Regex.Replace(text, ".{5}", "$0-");
textBoxProductKey.Text = text.Length <= 29 ? text : text.Substring(0, 29);
textBoxProductKey.SelectionStart = cursorPosition / 6 == (cursorPosition + 1) / 6
? cursorPosition + 1
: cursorPosition + 2;
e.Handled = true;
}
The two problems with my current solution are
cursorPosition == textBoxProductKey.Text.Length
.The latter is very easy to fix, but I'm struggling with the former and also feel like the code is a bit convoluted.
How can I more easily achieve this (note the plan is to continue using a TextBox
object).
EDIT
I am aware of the MaskedTextBox
control, I do not want to use a MaskedTextBox
, I want to use a TextBox
.
What I am trying to do is not outside the realms of possibility for a TextBox
, even if there are "easier" ways to accomplish this with other controls.
Also I feel like this is a great question for teaching people how to work with the cursor in a TextBox
(among other things probably).
Upvotes: 0
Views: 333
Reputation: 598
Continuing our conversation, save your current caret position, parse the whole text as if it's new, and return the caret to its original position.
That way you handle deleting as well as copy-pasting
Upvotes: 0
Reputation: 5165
Have you considered using the MaskedTextBox control? It might be more appropriate.
The MaskedTextBox is designed precisely for this type of requirement and would answer your original question.
You may find it more difficult to implement this functionality yourself with a normal TextBox. It's also worth weighing up which solution is more likely to be be bug-free and easier to maintain.
It may helpful if you could to explain to us why you would prefer use a TextBox over a MaskedTextBox.
Upvotes: 2