我正在尝试创建某种许可证验证文本框,该文本框会自动将用户输入拆分为由连字符分隔的块。我的许可证长度为25个字符,因此分开:
XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
我已经提出以下代码来解析用户输入,或者通过复制/粘贴解析用户输入,方法是处理文本框控件的TextChanged
事件,如下所示:
public static string InsertStringAtInterval(string source, string insert, int interval)
{
StringBuilder result = new StringBuilder();
int currentPosition = 0;
while (currentPosition + interval < source.Length)
{
result.Append(source.Substring(currentPosition, interval)).Append(insert);
currentPosition += interval;
}
if (currentPosition < source.Length)
{
result.Append(source.Substring(currentPosition));
}
return result.ToString();
}
private bool bHandlingChangeEvent = false;
private void txtLicense_TextChanged(object sender, EventArgs e)
{
if (bHandlingChangeEvent == true)
return;
bHandlingChangeEvent = true;
string text = txtLicense.Text.Replace("-", "").Replace(" ","");
int nPos = txtLicense.SelectionStart;
if((text.Length==5||text.Length==10||text.Length==15||text.Length==20) && txtLicense.Text[txtLicense.Text.Length-1]!='-')
{
txtLicense.Text += "-";
txtLicense.SelectionStart = nPos + 1;
}
if(text.Length>=25)
{
string tmp = text.Substring(0, 25);
tmp = InsertStringAtInterval(tmp, "-", 5);
txtLicense.Text = tmp;
txtLicense.SelectionStart = nPos;
}
bHandlingChangeEvent = false;
}
当我在框内输入用户类型和粘贴时,这种方法非常有效。我唯一的问题是,当用户尝试通过按退格键或删除时从输入的键中删除字符。
由于强制连字符插入@位置5,10,15,20一旦用户在退格键上按下其中一个标记,按下上面的逻辑会强制连字符添加到字符串中,并且用户不能超过该值。
我尝试摆弄KeyDown事件,但无法提出任何有用的信息。请有人帮忙。
我也尝试过使用MaskedTextbox,但是这件事很丑,因为我不希望在焦点上看到蒙版/连字符,我当然不想用白色空格替换提示,因为它会给人一些混乱单击框内部,因为当“假定”为空时,光标不会始终位于框的开头。
答案 0 :(得分:2)
您可以尝试以下版本:
void txtLicense_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Back) {
int index = txtLicense.SelectionStart;
while (index > 0 && txtLicense.Text[index - 1] == '-') {
--index;
}
if (index > 0) {
--index;
}
txtLicense.Select(index, txtLicense.SelectionLength + Math.Max(index, 1));
txtLicense.SelectedText = string.Empty;
e.SuppressKeyPress = true;
}
}
答案 1 :(得分:2)
这种事情多年来一直是我痛苦的原因。我接近它的方法是将每个对文本的更改视为从头开始粘贴 - 我删除连字符,然后将它们放回适当的位置。然后你可以只处理用户删除了最后一个字符的特殊情况。在这种情况下,您将TextChanged事件之前的文本与之后的文本进行比较。如果它们是相同的,但前一个文本的长度是一个字符,则不要做任何特殊的事情。
以下是一些似乎适用于文本输入,剪切/复制/粘贴等的代码。它可以通过一些花哨的LINQ,一些错误处理等进行改进,但希望它可以解决这个问题。
private string previousText = string.Empty;
private bool processing = false;
private void textBox1_TextChanged(object sender, EventArgs e)
{
// If we're already messing around with the text, don't start again.
if (processing)
return;
processing = true;
// The current textbox text
string newText = textBox1.Text;
// What was there before, minus one character.
string previousLessOne = previousText == string.Empty ? string.Empty : previousText.Substring(0, previousText.Length - 1);
// Get where the user is, minus any preceding dashes
int caret = textBox1.SelectionStart - (textBox1.Text.Substring(0, textBox1.SelectionStart).Count(ch => ch == '-'));
// If the user has done anything other than delete the last character, ensure dashes are placed in the correct position.
if (newText.Length > 0 && newText != previousLessOne)
{
textBox1.Text = string.Empty;
newText = newText.Replace("-", "");
for (int i = 0; i < newText.Length; i += 5)
{
int length = Math.Min(newText.Length - i, 5);
textBox1.Text += newText.Substring(i, length);
if (length == 5)
textBox1.Text += '-';
}
}
// Put the user back where they were, adjusting for dashes.
textBox1.SelectionStart = caret + (caret / 5);
previousText = textBox1.Text;
processing = false;
}
答案 2 :(得分:1)
我之前做过类似的事情。我要做的是在插入点后面有一个字符时才添加连字符。例如,不要在输入5个字符后添加连字符,而是在6处进行连字符,以便最后不会添加连字符。
以下是我用于在特定位置插入连字符的算法:
public static string FormatLicenseNumber(string str)
{
if (string.IsNullOrEmpty(str))
return str;
else
{
str = str.Replace("-", string.Empty);
if (str.Length > 20)
str = str.Insert(20, "-");
if (str.Length > 15)
str = str.Insert(15, "-");
if (str.Length > 10)
str = str.Insert(10, "-");
if (str.Length > 5)
str = str.Insert(5, "-");
return str;
}
}