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:你可以做同样的事情来解释你想要的一切,而不必依赖于按键。