【问题标题】:Only allow specific characters in textbox只允许文本框中的特定字符
【发布时间】:2012-09-18 09:29:12
【问题描述】:

如何在 Visual C# 文本框中只允许某些字符?用户应该能够在文本框中输入以下字符,并且应该阻止其他所有字符:0-9、+、-、/、*、(、)。

我已使用 Google 查找此问题,但我得到的唯一解决方案是仅允许字母字符、仅数字字符或不允许某些字符。我想要的不是禁止某些字符,我想默认禁止所有字符,除了我在代码中输入的字符。

【问题讨论】:

  • ASP.NET?表格? WPF?所有这些都可以使用C#,而且都是不同的。
  • 这是一个 Windows 窗体应用程序。
  • 您是否尝试过为 PropertyChanged 事件创建一个事件处理程序,如果该字符无效则将其删除?
  • 您希望它不接受无效输入吗?就像用户键入 $ 一样,您是否希望它忽略该击键?需要什么行为?
  • 确切地说,当用户按下 $ 时,它会被忽略并在文本框上留下白色。当用户按下一个合法字符时,它应该被显示出来。

标签: c# winforms textbox


【解决方案1】:

正如评论中提到的(以及我输入的另一个答案),您需要注册一个事件处理程序来捕获文本框上的 keydown 或 keypress 事件。这是因为 TextChanged 仅在 TextBox 失去焦点时触发

下面的正则表达式可以让你匹配那些你想要允许的字符

Regex regex = new Regex(@"[0-9+\-\/\*\(\)]");
MatchCollection matches = regex.Matches(textValue);

而这恰恰相反,会捕获不允许的字符

Regex regex = new Regex(@"[^0-9^+^\-^\/^\*^\(^\)]");
MatchCollection matches = regex.Matches(textValue);

我不会假设会有一个匹配项,因为有人可以将文本粘贴到文本框中。在这种情况下捕获 textchanged

textBox1.TextChanged += new TextChangedEventHandler(textBox1_TextChanged);
private void textBox1_TextChanged(object sender, EventArgs e)
{
    Regex regex = new Regex(@"[^0-9^+^\-^\/^\*^\(^\)]");
    MatchCollection matches = regex.Matches(textBox1.Text);
    if (matches.Count > 0) {
       //tell the user
    }
}

并验证单次按键

textBox1.KeyPress += new KeyPressEventHandler(textBox1_KeyPress);
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
    // Check for a naughty character in the KeyDown event.
    if (System.Text.RegularExpressions.Regex.IsMatch(e.KeyChar.ToString(), @"[^0-9^+^\-^\/^\*^\(^\)]"))
    {
        // Stop the character from being entered into the control since it is illegal.
        e.Handled = true;
    }
}

【讨论】:

  • 您可能需要为代码 8 的密钥添加额外检查,否则退格将不起作用
  • 万一其他人遇到这个......我无法让它在KeyPress处理程序中工作。即使我将e.Handled 设置为true,它仍然会将字符插入到控件中。当我改为处理KeyDown 时,一切正常。我使用的控件是RichTextBox,所以这可能与它有关。让它工作后我没有做太多实验。
  • 附带说明,TextChanged 在文本失去焦点时不会触发,而是在文本更改之后触发(例如,如果文本有效,我会使用它为文本着色)。太晚了,太难了。
  • 精彩回答
【解决方案2】:

您需要订阅文本框上的KeyDown 事件。然后是这样的:

private void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
    if (!char.IsControl(e.KeyChar) 
       && !char.IsDigit(e.KeyChar) 
       && e.KeyChar != '.' && e.KeyChar != '+' && e.KeyChar != '-'
       && e.KeyChar != '(' && e.KeyChar != ')' && e.KeyChar != '*' 
       && e.KeyChar != '/')
    {
        e.Handled = true;
        return;
    }
    e.Handled=false;
    return;
}

要知道的重要一点是,如果您将Handled 属性更改为true,它将不会处理击键。将其设置为false 即可。

【讨论】:

  • KeyDown KeyEventArgs 参数没有 KeyChar 属性。也许您的意思是 KeyPressEventArgs 和具有该属性的 KeyPress 事件?
【解决方案3】:

您可能可以使用KeyDown eventKeyPress eventKeyUp event。我会首先尝试我认为的 KeyDown 事件。

您可以设置事件参数的 Handled 属性来停止处理事件。

【讨论】:

    【解决方案4】:

    在我看来,拦截 KeyPressed 事件是一个很好的可靠解决方案。如果使用 RegExp,请注意触发代码字符(e.KeyChar 低于 32)。

    但是,只要用户从剪贴板粘贴文本,这种方式仍然可以注入超出范围的字符。不幸的是,我没有找到正确的剪贴板事件来解决这个问题。

    所以一个防水的解决方案是拦截TextBox.TextChanged。这里有时会在短时间内看到原始的超出范围的字符。我建议同时实施。

    using System.Text.RegularExpressions;

    private void Form1_Shown(object sender, EventArgs e)
    {
        filterTextBoxContent(textBox1);
    }
    
    
    string pattern = @"[^0-9^+^\-^/^*^(^)]";
    
    private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if(e.KeyChar >= 32 && Regex.Match(e.KeyChar.ToString(), pattern).Success) { e.Handled = true; }
    }
    
    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        filterTextBoxContent(textBox1);
    }
    
    private bool filterTextBoxContent(TextBox textBox)
    {
        string text = textBox.Text;
    
        MatchCollection matches = Regex.Matches(text, pattern);
        bool matched = false;
    
        int selectionStart = textBox.SelectionStart;
        int selectionLength = textBox.SelectionLength;
    
        int leftShift = 0;
        foreach (Match match in matches)
        {
            if (match.Success && match.Captures.Count > 0)
            {
                matched = true;
                Capture capture = match.Captures[0];
    
                int captureLength = capture.Length;
                int captureStart = capture.Index - leftShift;
                int captureEnd = captureStart + captureLength;
    
                int selectionEnd = selectionStart + selectionLength;
    
                text = text.Substring(0, captureStart) + text.Substring(captureEnd, text.Length - captureEnd);
    
                textBox.Text = text;
    
                int boundSelectionStart = selectionStart < captureStart ? -1 : (selectionStart < captureEnd ? 0 : 1);
                int boundSelectionEnd = selectionEnd < captureStart ? -1 : (selectionEnd < captureEnd ? 0 : 1);
    
                if (boundSelectionStart == -1)
                {
                    if (boundSelectionEnd == 0)
                    {
                        selectionLength -= selectionEnd - captureStart;
                    }
                    else if (boundSelectionEnd == 1)
                    {
                        selectionLength -= captureLength;
                    }
                }
                else if (boundSelectionStart == 0)
                {
                    if (boundSelectionEnd == 0)
                    {
                        selectionStart = captureStart;
                        selectionLength = 0;
                    }
                    else if (boundSelectionEnd == 1)
                    {
                        selectionStart = captureStart;
                        selectionLength -= captureEnd - selectionStart;
                    }
                }
                else if (boundSelectionStart == 1)
                {
                    selectionStart -= captureLength;
                }
    
                leftShift++;
            }
        }
    
        textBox.SelectionStart = selectionStart;
        textBox.SelectionLength = selectionLength;
    
        return matched;
    }
    

    【讨论】:

      【解决方案5】:

      对于您的验证事件 IMO,最简单的方法是使用字符数组来验证文本框字符。是的 - 迭代和验证不是特别有效,但很简单。

      或者,对输入字符串使用白名单字符的正则表达式。您的活动在 MSDN 上可用:http://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx

      【讨论】:

        【解决方案6】:
            private void txtuser_KeyPress(object sender, KeyPressEventArgs e)
            {
                if (!char.IsLetter(e.KeyChar) && !char.IsWhiteSpace(e.KeyChar) && !char.IsControl(e.KeyChar))
                {
                    e.Handled = true;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-24
          • 2022-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多