C#文本框中的负数

C#文本框中的负数,c#,winforms,textbox,C#,Winforms,Textbox,我已经完成了这里的问题,并找到了让文本框只接受开头有一个小数点和负号的数值的答案 if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && e.KeyChar != '.' && e.KeyChar != '-') { e.Handled = true; } // only allow one decimal point if

我已经完成了这里的问题,并找到了让文本框只接受开头有一个小数点和负号的数值的答案

    if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && e.KeyChar != '.' && e.KeyChar != '-')
    {
        e.Handled = true;
    }

    // only allow one decimal point
    if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1)
    {
        e.Handled = true;
    }

    if (e.KeyChar == '-' && (sender as TextBox).Text.Length > 0)
    {
        e.Handled = true;
    }
然而,我确实有一个问题。假设用户键入了一个数字:

123455789764


然后他意识到这个数字是负数。他回到开头,试着输入负号,结果发现它不起作用。有没有办法解决这个问题,而不是让用户删除他键入的数字,添加负数,然后重新键入数字?

您可以检查光标位置并放弃“-”,而不是检查字符串的长度(当字符串不为零时,放弃“-”当光标不在开头或开头已有“-”时

但是在提交过程中稍后进行整个检查,而不是吞下键盘可能会更好。

尝试以下方法:

Regex reg = new Regex(@"^-?\d+[.]?\d*$");
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (char.IsControl(e.KeyChar)) return;
        if (!reg.IsMatch(textBox1.Text.Insert(textBox1.SelectionStart, e.KeyChar.ToString()) + "1")) e.Handled = true;
    }
对于keyboardP的建议,我添加此代码以完全防止非数值,我认为您应该尝试
TextBox.ShortcutsEnabled=false
    Regex reg = new Regex(@"^-?\d+[.]?\d*$");
    bool textChangedByKey;
    string lastText;
    private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (char.IsControl(e.KeyChar)) return;
        if (!reg.IsMatch(textBox1.Text.Insert(textBox1.SelectionStart, e.KeyChar.ToString()) + "1"))
        {
            e.Handled = true;
            return;
        }
        textChangedByKey = true;
    }
    private void textBox1_TextChanged(object sender, EventArgs e)
    {            
        if (!textChangedByKey)
        {
            if (!reg.IsMatch(textBox1.Text))
            {
                textBox1.Text = lastText;
                return;
            }                
        }
        else textChangedByKey = false;
        lastText = textBox1.Text;
    }

我尝试过使用
Undo()
方法重置
SelectedText
,但是有点不好,即使上面的方法也不能带来良好的视觉效果(在尝试将文本粘贴到数字文本框时,您可以看到文本更改并恢复到有效值).

我认为依靠文本框事件是解决问题的更好方法。在任何情况下,您都可以继续使用您的方法,并用事件补充它,以说明标题“-”问题。此代码删除文本框中的任何破折号,除非位于第一个位置:

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        if (textBox1.Text.Trim().Length > 0)
        {
            if (textBox1.Text.Contains("-") && (textBox1.Text.Substring(0, 1) != "-" || textBox1.Text.Split('-').Length > 2))
            {
                bool headingDash = false;
                if (textBox1.Text.Substring(0, 1) == "-")
                {
                    headingDash = true;
                }
                textBox1.Text = textBox1.Text.Replace("-", "");
                if (headingDash)
                {
                    textBox1.Text = "-" + textBox1.Text;
                }
            }
        }
    }
  • 仅当单击某些“确定”或“提交”按钮时才评估字符,而不是每次击键时
  • 使用正则表达式检查整个文本的有效性,而不仅仅是键入的字符
  • 尝试使用
    Int64.TryParse
    将文本解析为
    long
    ,并计算调用的
    bool
    结果
  • 阅读了以上所有内容:为什么不简单地使用
    NumericUpDown
    控件?
  • <>这对我有用(虽然你可以考虑一些修改,取决于你想如何处理小数分隔符(因为数字格式依赖当前的文化设置)

    这只接受数字,输入的长度和进一步的格式(例如,小数点分隔符前只允许有一个数字)不被处理,尽管我认为可以修改它来实现这一点

    public enum NumericTextBoxType { TDecimal = 1, TByte, TShort, TInt, TLong }
    
        public class NumericTextBox : TextBox
        {
            #region ARRAYS
    
            private static readonly Keys[] separators = 
            {
            Keys.Decimal,
            Keys.Oemcomma,
            Keys.OemPeriod
            };
    
            private static readonly Keys[] allowed =
            {
            Keys.D1,
            Keys.D2,
            Keys.D3,
            Keys.D4,
            Keys.D5,
            Keys.D6,
            Keys.D7,
            Keys.D8,
            Keys.D9,
            Keys.D0,
            Keys.NumPad0,
            Keys.NumPad1,
            Keys.NumPad2,
            Keys.NumPad3,
            Keys.NumPad4,
            Keys.NumPad5,
            Keys.NumPad6,
            Keys.NumPad7,
            Keys.NumPad8,
            Keys.NumPad9,
            Keys.Decimal,
            Keys.Oemcomma,
            Keys.OemPeriod,
            Keys.OemMinus,
            Keys.Subtract,
            Keys.Back,
            Keys.Delete,
            Keys.Tab,
            Keys.Enter,
            Keys.Up,
            Keys.Down,
            Keys.Left,
            Keys.Right
            };
    
            private static readonly Keys[] intallowed =
            {
            Keys.D1,
            Keys.D2,
            Keys.D3,
            Keys.D4,
            Keys.D5,
            Keys.D6,
            Keys.D7,
            Keys.D8,
            Keys.D9,
            Keys.D0,
            Keys.NumPad0,
            Keys.NumPad1,
            Keys.NumPad2,
            Keys.NumPad3,
            Keys.NumPad4,
            Keys.NumPad5,
            Keys.NumPad6,
            Keys.NumPad7,
            Keys.NumPad8,
            Keys.NumPad9,
            Keys.OemMinus,
            Keys.Subtract,
            Keys.Back,
            Keys.Delete,
            Keys.Tab,
            Keys.Enter,
            Keys.Up,
            Keys.Down,
            Keys.Left,
            Keys.Right
            };
    
            #endregion ARRAYS
    
            #region PROPERTY NumericTextBoxType
    
            private NumericTextBoxType _NumericTextBoxType = NumericTextBoxType.TDecimal;
    
            public NumericTextBoxType NumericTextBoxType
            {
                get
                {
                    return
                    _NumericTextBoxType;
                }
                set
                {
                    _NumericTextBoxType = value;
                }
            }
    
            #endregion PROPERTY NumericTextBoxType
    
            #region PROPERTY AllowMinus
    
            public bool AllowMinus { get; set; }
    
            #endregion
    
            string prvText = "";
            int prevSelStart = 0;
    
            public NumericTextBox()
                : base()
            {
                this.NumericTextBoxType = NumericTextBoxType.TDecimal;
                this.AllowMinus = true;
            }
    
            #region EVENT METHOD OnKeyDown
    
            protected override void OnKeyDown(KeyEventArgs e)
            {
                base.OnKeyDown(e);
    
                if (e.Modifiers == Keys.Control)
                {
                    prvText = this.Text;
                    prevSelStart = this.SelectionStart;
                    return;
                }
    
                // ignore not allowed
                if (NumericTextBoxType != NumericTextBoxType.TDecimal)
                {
                    if (!intallowed.Contains(e.KeyCode)) e.SuppressKeyPress = true;
                }
                else
                {
                    if (!allowed.Contains(e.KeyCode)) e.SuppressKeyPress = true;
                    else if (separators.Contains(e.KeyCode))
                    {
                        NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
                        string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
    
                        int selLength = this.SelectionLength;
                        int selStart = this.SelectionStart;
    
                        if (!this.Text.Remove(selStart, selLength).Contains(decimalSeparator))
                        {
                            this.Text = this.Text
                            .Remove(selStart, selLength)
                            .Insert(this.SelectionStart, decimalSeparator);
                            this.SelectionStart = selStart + decimalSeparator.Length;
                        }
                        e.SuppressKeyPress = true;
                    }
                }
    
                // ignore minus if not first or not allowed
                if (e.KeyCode == Keys.OemMinus || e.KeyCode == Keys.Subtract)
                {
                    if (!this.AllowMinus) e.SuppressKeyPress = true;
                    else if (NumericTextBoxType == NumericTextBoxType.TByte) e.SuppressKeyPress = true;
                    else if (this.SelectionStart > 0) e.SuppressKeyPress = true;
                }
    
                prvText = this.Text;
                prevSelStart = this.SelectionStart;
            }
    
            #endregion EVENT METHOD OnKeyDown
    
            #region METHOD OnTextChanged
    
            protected override void OnTextChanged(EventArgs e)
            {
                base.OnTextChanged(e);
    
                // don't allow incorrect paste operations
                if (Regex.IsMatch(this.Text, (!AllowMinus ? "[-" : "[") + @"^\d.,]") ||
                Regex.Matches(this.Text, @"[.,]").Count > 1)
                {
                    this.Text = prvText;
                    this.SelectionStart = prevSelStart;
                }
            }
    
            #endregion
    
        }
    

    也许您不应该计算每一个字符的笔划,但仅在提交表单时计算?只需使用正则表达式检查提交表单时文本框是否仅包含数字。此表达式仅用于数字:
    ^[0-9]+$
    。但由于正则表达式不是我的专长,我无法告诉您需要添加什么才能允许负号…:(与粘贴相比,您的解决方案没有帮助。如果您复制文本,您仍然可以粘贴它,从而绕过您的解决方案。@keyboard P OK我将其更新为允许十进制数字,但是破折号无法按您所说的多次输入。我已经测试过它。+1-不确定它为什么不起作用。我创建了一个新项目(在现有的沙盒Winform上进行了测试),它工作正常。您需要防止粘贴文本,因此在
    TextChanged
    事件中,您需要添加
    if(!reg.IsMatch(textBox1.text))textBox1.Clear();
    @keyboard谢谢,我想OP应该注意到,代码只是演示:)这很好,只是发布以防OP跳过它。这个问题的最佳解决方案是:)1.该值被其他控件使用,因此我无法等待OK或Submit。另外,看到弹出一个消息框说数据无效令人恼火:P2.感谢刚才使用了King Kong对REGEX的回答。3.我不知道如何执行此操作。4.Donno在这种情况下似乎对用户不友好。我认为用户将是moWe’’我们对文本框而不是数字updown很满意,因为每次移动光标时它都会检查,所以这不会使程序变慢吗?@Kris134:检查速度非常快,不会使程序变慢,不会。而且你已经在每次按下一个键时进行检查了。另外,你只需要在“-”时检查光标的位置被按下,不是每次移动光标。谢谢,但这里面有太多的编码。它可能会降低程序的速度。它可能会进一步优化,但我不认为它有那么慢。它不会闪烁,它处理“粘贴”问题,并且是可重用的:)感谢您的帮助,但我认为这对我的情况没有帮助。如果第一个字符是“-”,您提供的代码将运行代码。我希望系统只允许用户添加“-”作为第一个字符。我确实误解了您的观点(不是太好的一天:),但我的代码可以轻松地更新到您想要的。我改变了它:现在你完全得到了你想要的。PS:你可以做同样的事情来解释你想要的一切,而不必依赖于按键。