完成后才做事件

Only do event after complete

当用户按下回车键或将焦点留在特定文本框上时,如何进行事件处理?我尝试了 KeyChanged 事件,但它会不断更新数字,而不是在完成后仅更新一次。

private void txtNumber_TextChanged(object sender, EventArgs e)
{
    txtNumber.Text = double.Parse(txtNumber.Text).ToString("F2");
}

在输入完成后必须在 TextBox 中格式化文本值。

TextChanged,当 Text 属性 值改变时发生。所以这并不理想。

您唯一可以信赖的活动。

private void textBox1_LostFocus(object sender, System.EventArgs e)
{
   // Code here
}

有时我们希望在单击键盘上的某个内容后更改格式,因此这里是可能发生的事件。 The non-character keys do raise the KeyDown and KeyUp events.

  • KeyDown,在控件具有焦点时按下某个键时发生。
  • KeyUp,在控件具有焦点时释放键时发生。
  • KeyPress,当一个字符出现。 space 或 backspace 键在控件具有焦点时被按下。 注意:当使用 KeyPress 时,您还需要考虑表单是否是第一个处理输入事件的表单,检查 Remarks here.
private void textBox1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
  if (e.KeyCode == Keys.Return) // You can also use: e.KeyValue == 13
  {
      // Do your code here
  }
};

发布的代码存在一些问题。一个问题是,每次用户“键入”一个字符时都进行格式化,这对用户来说会很尴尬。此外,如果用户按下“Enter”键,事件 txtNumber_TextChanged 不会触发。我想你可能已经知道了。

接下来,当从用户那里获取输入时,必须在调用解析方法之前检查输入的有效数字……例如,代码行……

double.Parse(txtNumber.Text).ToString("F2");

如果文本框中的文本... txtNumber.Text 不是有效的双精度值,将失败并导致程序崩溃。

您应该始终假设用户会犯错并且您不希望您的代码在他们犯错时崩溃。

因此我建议使用 double.TryPasre 方法来避免这些可能的崩溃,调用此方法将永远不会抛出异常并且会使验证数字更容易。

为了获得您想要的结果,我建议您为文本框连接三 (3) 个事件……

Leave 事件,用于在用户离开文本框时设置文本格式,例如当他们单击另一个控件时。

接下来是PreviewKeyDown事件,当用户按下“Enter”键时使用。

还有一个额外的事件来帮助用户只添加数字和一个点。 KeyPressed 事件已连接并将忽略任何不是数字或点(句点)的按键。另外,它只允许一个句点,如果用户试图添加第二个小数位,它将被忽略。

请记住,按键事件有助于防止用户在文本框中“键入”字母文本……但是,用户仍然可以粘贴文本。幸运的是,由于我们使用的是 TryParse 方法,当粘贴的文本是无效数字时,try parse 将简单地 return “0.00” 而不会使代码崩溃。

private void txtNumber_Leave(object sender, EventArgs e) {
  double.TryParse(txtNumber.Text.Trim(), out double number);
  txtNumber.Text = number.ToString("F2");
}

private void txtNumber_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
  if (e.KeyCode == Keys.Enter) {
    double.TryParse(txtNumber.Text.Trim(), out double number);
    txtNumber.Text = number.ToString("F2");
  }
}

private void txtNumber_KeyPress(object sender, KeyPressEventArgs e) {
  if (!char.IsControl(e.KeyChar) // <- key pressed is not a control key
    && !char.IsDigit(e.KeyChar)  // <- key pressed is not a digit (number)
    && e.KeyChar != '.') {       // <- key pressed is not a dot (.)
    e.Handled = true;            // <- if its not a control key, digit or dot... then ignore it
  }
  // only allow one decimal point - if there is already a dot, then ignore the second one
  if (e.KeyChar == '.' && txtNumber.Text.IndexOf('.') > -1) {
    e.Handled = true;            // <- if there is already a dot in the text... then ignore it
  }
}