【问题标题】:Pressing Enter is not the same as clicking the Windows Form's AcceptButton按 Enter 与单击 Windows 窗体的 AcceptButton 不同
【发布时间】:2015-05-27 20:03:53
【问题描述】:

我有一个简单的 VB.Net Windows 窗体应用程序,它有两个文本框和一个按钮,它是表单的 AcceptButton。唯一的代码在 ButtonClick 上,并使用 Leave 事件对每个 TextBox 进行验证。 (我也尝试了 LostFocus 事件,它似乎工作相同)。我的问题是,如果我用鼠标单击 Button,则用户所在的 TextBox 会发生正确的 Leave(或 LostFocus)事件,但是如果我按 Enter,则焦点不会丢失,因此该 TextBox 的代码确实不跑。

如何使 Enter 键的行为与单击表单的 AcceptButton 相同?

【问题讨论】:

  • 为什么不把验证码放在点击事件中呢?无论他们输入什么都是试探性的,直到他们按下 Enter/Submit/Ok/Done。
  • 在我浏览表单时,每个表单字段不能进行自己的验证吗?有人告诉我最好立即验证,等到提交是糟糕的用户体验。此外,较少面向对象。 1992 年 Petzold 的书和 C.
  • 逐字段验证,顾名思义,意味着您将在浏览表单时弹出 MsgBox 或其他任何东西,每个人都觉得这很麻烦。 FxF 也仅适用于简单的应用程序 - 在其他情况下,B 的验证取决于 A,这意味着如果在验证 B 后它们更改 A,则可能会出现死锁。至于 OO,如果表单的内容表示类似 a CustomerWidget,将输入作为一个整体进行验证是完全 OO 的。
  • 此外,旧 WDIG 的规则 #1 是 用户负责,这意味着他们可以按自己喜欢的任何顺序输入数据,通过制表符/跳过字段来获取到别的东西。一个例子是电话上的 CSR - 如果客户没有按照您的表单期望的顺序获得数据,那么事情不应该突然停止。或者他们可以输入一个年龄的“我喜欢馅饼”,但是他们不能提交它。
  • @Plutonix:我对每个字段都有验证,以及确保两个条目相互兼容的点击验证......思考。空字段 - 确定,直到提交。无效数据 - 不能离开该字段。我的方法将不同事物的责任级别委托给不同的方法,而且在 Windows、OO 和框架之前很长时间我就这样做了。 (我只是暂时停止做其他事情。)我希望我可以将完成的应用程序发布到某个地方......

标签: vb.net validation


【解决方案1】:

当您直接点击按钮时,会出现一系列事件,包括TextBox.LostFocusTextBox.LeaveButton.MouseEnterButton.Click

但是当您按下 Enter 时,它是拦截按键的表单,如果它是 Enter 并且有一个 AcceptButton,则启动它的 PerformClick 方法而不引发大多数这些事件。

您可以轻松验证;通过设计器将 Button 的 DialogResult 设置为一个值,并在将 DialogResult 更改为另一个值时处理 Button 的 GotFocus 事件。 然后测试你的代码(存储Form.ShowDialog的结果);通过直接单击,您将获得在 GotFocus 上设置的值,因为它是在单击表单期间将其设置为按钮的 DialogResult 值上的 DialogResult ;按下 Enter,您将获得初始 Dialogresult(设计者的),有效地证明 GotFocus 未被输入。

回到当前问题;要解决它,您需要在Validating(或Validated)事件中处理您的验证;确保您的 Textbox CauseValidation 设置为 true [默认值],否则不会引发这些事件。您可以在其中将 e.Cancel (使用 e CancelEventArgs 参数)设置为 true 以停止验证(和事件链)有效地将焦点保持在“无效”控件内(并且这也可以防止按钮单击任何用于达到的方式它)

一个例子:这个表单有两个文本框和一个按钮作为表单的 AcceptButton 并“验证”它的输入,这样就不允许空的 TextBox.Text

Public Class NonEmptyTextBoxesForm
    Private Sub TextBoxes_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles TextBox1.Validating, TextBox2.Validating
        Dim tb = DirectCast(sender, TextBox)
        e.Cancel = tb.Text = "" ' e.Cancel = (tb.Text = "") ' if that's make this clearer
    End Sub
End Class

【讨论】:

  • 哇。鼠标和键盘的工作方式不同。真是一团糟!好的,我会将函数的名称从 Leave 更改为 Validating 并改为捕获该事件。我希望如果我按 Enter 验证会发生,否则会有一个小问题。
  • 鼠标和键盘的工作方式并不是一样的(如果您使用文本框(例如使用选项卡)更改焦点控制,则事件链与鼠标相同。在您的确切情况下拦截按键并取代事件链的是“负责”的表单。
  • 叮叮叮!我在 4 个地方将“离开”一词更改为“验证”,现在它按我预期的方式工作。他们需要更多的文档。我正在尝试查找显示在各种场景中触发的事件的流程图,但我还没有看到。
  • 请参阅Validating documentation 中的 Notes 部分;)
  • 嗯,“笔记”这个词没有出现在那个网页的任何地方?我看到了注意不要使用 Focus()。正如你所说,我将不得不使用 e.Cancel 来防止离开现场。
【解决方案2】:

所以当您单击 Enter 键时,您会失去从文本框到按钮的焦点?! 如果是这样,你可以试试这个:

   Protected Overrides Function ProcessCmdKey(ByRef sMessage As Message, ByVal oKeyData As Keys) As Boolean
    If oKeyData = Keys.Enter Then
        Me.Textbox1.Focus()
        AcceptButton.PerformClick()
        Return True
    ElseIf oKeyData = Keys.Escape Then
        Application.Exit()
        Return True
    Else
        Return MyBase.ProcessCmdKey(sMessage, oKeyData)
    End If
   End Function

希望对你有所帮助;)

【讨论】:

  • 不,当我按下 Enter 键时,我没有收到 LostFocus(或离开)事件,但它确实发生在鼠标单击时。那么,这些年来拥有 Windows 和框架,我仍然需要拦截键盘事件才能运行一个简单的表单?失败。
【解决方案3】:

我同意 Plutonix - 为什么不将两个文本框的验证都放在点击事件中? (除非这是出于教育目的?)

如果您真的想验证文本框的离开事件,并且您需要在当前文本框上的验证在您按下 Enter 时按钮执行任何操作之前运行,那么您需要一个按键事件来处理按键对于两个文本框。在那里,检查按下的键是否是输入,如果是,那么你可以获取具有焦点的文本框...调用它的离开事件,然后调用按钮的单击事件。

这有意义吗?

【讨论】:

  • 那么,Windows 没有被设计成在设置了 AcceptButton 的情况下按 Enter 就等于单击所述按钮?我必须解决 Windows 中的设计缺陷?我认为键盘导航和鼠标导航应该是等效的。你问为什么我希望每个 TextBox 都有一个函数来验证自己而不是一个大的验证函数:因为它更面向对象?
【解决方案4】:

如何使 Enter 键的行为与单击表单的 AcceptButton 相同?

要使 ENTER 键的行为与单击 ACCEPT 按钮的行为相同,您可以使用表单的 ACCEPTBUTTON 属性并分配您希望在按下 ENTER 键时单击的按钮。

虽然这会导致按钮点击事件中的代码执行, 不知道TEXTBOX-LOSTFOCUS事件中的代码会不会执行!

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  '
  ' Assign default button for ENTER key (Okay Button)
  Me.AcceptButton = Me.MyOkayButton
  '
  ' Assign default button for ESCAPE key (Cancel Button)
  Me.CancelButton = Me.MyCancelButton
  '
End Sub

【讨论】:

  • 我在表单本身而不是代码中设置了 AcceptButton 属性。有重要的区别吗?按下 Enter 会做 Click 事件所说的事情,它只是不会做 LostFocus / Leave 的东西......但是用鼠标点击会。为什么我希望 Enter 触发与 Clicking 不同的事件?
  • 通过设置 ACCEPTBUTTON 或 CANCELBUTTON 它只需在按下时拿起输入/退出键并执行指定的按钮事件。放置验证代码的最佳位置是 Sehnsucht 上面所写的 VALIDATING 和 VALIDATED 事件。许多设计人员喜欢在按钮单击事件中提交表单时一次验证所有数据,有时您会使用 ACCEPTBUTTON 来运行该按钮事件。如果您希望每个文本框都验证自己的数据,那么您应该遵循 Sehnsucht 的模型。这就是这些事件存在的原因。
  • 是的,我将事件更改为 Validating,它主要按我预期的方式工作。对我来说,用鼠标单击包括首先离开当前字段的操作似乎很奇怪,但按 Enter(在导航方面应该做完全相同的事情)不会离开当前字段。如何解释这种行为差异?是否存在我希望他们做不同事情的情况?我无法想象一个。我认为这是 Windows 的设计缺陷。
猜你喜欢
  • 2011-06-11
  • 2017-07-13
  • 1970-01-01
  • 1970-01-01
  • 2010-11-10
  • 1970-01-01
  • 2019-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多