如何在C#中实现TextBox的输入限制最佳方式?

7

如何最优雅地限制TextBox控件(或任何其他标准.NET 3.5控件)的输入为浮点数?

目前,我通过继承TextBox并覆盖OnKeyPress方法来完成所有繁重的工作。但是,我不禁想知道是否有更好的方法。

7个回答

13

如果您按照您提议的路线前进,不要忘记以下问题/边角情况:

  • 用户可以使用 Ctrl-VShift-Insert 粘贴“无效”的值(第二个值有点棘手)……但是用户可能应该允许将合法值粘贴到控件中。
  • 用户可以右键单击,使用默认上下文菜单粘贴无效的值。
  • 即使您尝试通过为文本框提供其自己的上下文菜单来修复先前的问题,用户也可以右键单击您的控件外部,按住右键,拖动到您的文本框上并松开以访问默认上下文菜单(并粘贴无效值)。
  • 您所做的任何按键处理都不应禁用 Alt - F4 等键组合。 (如果您对除有效数字之外的所有内容设置了 SuppressKeyPress,那么是的,您将打破它)。
  • 用户可能应该能够输入部分值(例如 "-.",当他们开始输入 "-.23" 时),而不会受到您的文本框的惩罚。
  • "-.1e-2" 这样的数字可能是合法的。
  • 用户可以合理地输入一个仅包含数字但会溢出 float 的值。
  • 最糟糕的是: 您在上线后用户将发现其他神秘的边角情况(!!)。

故事?做你建议的事情可能非常棘手。

您可能希望进行以下组合:

  • 使用某个已经知道所有角落情况的控件(例如 Microsoft)。
  • TextChanged 事件中进行基本验证(并执行某些被动操作,例如更改文本框背景色)。
  • 在实际尝试使用用户键入的值之前保存验证。
  • 使用系统库为您解析用户的值。

@ecarF:别开玩笑了;这就是为什么像OP所要求的那样构建一个强大的输入控件如此痛苦的原因。 - Daniel LeCheminant
等待用户完成操作(按下“确定”),然后使用正则表达式增加值,然后继续或抛出消息框。这比覆盖OnKeyPress要好得多。 - Karl
感谢您的努力。;) - ecarF
@Karl:MessageBox 是邪恶的,应该消失。在一些保留区域或无效文本框周围禁用“确定”按钮并提供原因对于普通用户来说要简单得多。 - Julien Roncaglia
+1 VirtualBlackFox。我可能会闪烁输入控件的背景并使用工具提示。 - ecarF
显示剩余2条评论

2

请看MaskedTextBox控件。它也继承自TextBoxBase,可能具有您正在构建的功能。


谢谢你的快速回复,Mike。实际上,在手动操作之前,我确实研究了MaskedTextBox控件,但是,我无法让它像我想要的那样处理浮点数。也许我做了一些愚蠢的事情... - ecarF
我认为MaskedTextBox在这里做不了任何好事,因为它似乎不允许无限(用户定义)数量的字符。 - Julien Roncaglia

1

使用NumericUpDown怎么样?


0

或者使用检查匹配

void TextBox_KeyUp(object sender, KeyEventArgs e)
{
  if(..) // your condition
  {
    e.SuppressKeyPress = false;
  }
  else
  {
    e.SuppressKeyPress = true;
  }
}

或者

void TextBox_KeyUp(object sender, KeyEventArgs e)
{
   e.SuppressKeyPress = CheckInput(e.KeyValue); // where CheckInput is boolean method
}

0
我发现了maskedTextBox的ValidatingType属性:
maskedTextBox1.ValidatingType = typeof(System.Double);

它确实会告诉你它是否有效。不幸的是,它似乎只在焦点改变时进行验证(即使那样它实际上并没有做任何事情);但也许有一些方法可以利用它。


您可以随时调用“ValidateText”方法。为了避免聚焦变化限制,为TextChanged设置处理程序,如果(maskedTextBox1.MaskCompleted),则调用maskedTextBox1.ValidateText(); - CJBrew

0

我认为该功能尚未被发明(至少在.NET框架中)。但我确定CodeProject或类似网站上有类似的东西,这可能值得一试。

不过,这项工作并不是特别困难。只是看起来需要多花一点功夫。

一个过于简单的例子是你可以处理OnKeyPress,并用新字符附加进行Float.TryParse。如果返回true,则保留键盘输入;如果返回false,则取消它(e.Handled = true)。

困难的部分是,如果用户删除、剪切或粘贴选定内容会怎样。另外一件事情是当他们刚开始时(你可能希望接受“-”作为部分有效输入)...


谢谢你的建议,但事情并不那么简单。如果用户更改了插入符的位置怎么办?据我所见,你不能盲目地追加。 - ecarF
感谢VirtualBlackFox提供的链接。我一定会去看看。 - ecarF
关于这一点说得好,但是你不能使用SelectionStart和SelectionLength获取当前选择吗? - lc.
顺便说一句,我认为仅限制输入并不是一个好方法。复制粘贴的情况本身就是一个问题,因为有些用户希望能够在输入框开头粘贴数字,并手动删除旧文本以使其有效... - Julien Roncaglia
@VirtualBlackFox 在这两点上都同意,有时候限制输入可能会对你不利。最好按照你在最后一条评论中建议的去做。 - lc.
显示剩余2条评论

0

在数据输入期间进行验证是必要的吗?还是可以在焦点失去后检查输入的最终值?

如果是后者,您还可以使用ErrorProvider控件来帮助限制功能,直到输入得到解决。


谢谢,我想我应该解释得更清楚。我正在进行数据输入期间的用户输入验证。 - ecarF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接