我有未绑定文本框控件。用户输入一些有效文本并离开控件。然后用户返回控件并输入一些无效文本。我想向用户显示一条消息,然后将控件的值回滚到之前的状态,将焦点保持在该控件。
我尝试了以下方法,但没有一种能让我得到我想要的东西:
选项A :SendKeys
Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
Cancel = DataIsInvalid(Me.MyTextBox.Value)
If Cancel Then SendKeys "{Esc}"
End Sub
这正是我想要的,但我真的想避免使用SendKeys
。使用SendKeys会遇到许多问题:Vista+ compatibility,密钥被发送到其他应用程序等。
选项B :撤消控制方法
Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
Cancel = DataIsInvalid(Me.MyTextBox.Value)
If Cancel Then Me.MyTextBox.Undo
End Sub
对于未绑定的控件(至少从MS Access 2002 / XP开始),这是简单的。此方法不会将MyTextBox的值还原为有效输入。但是,它确实允许用户将焦点更改为新控件,同时在Me.MyTextBox中保留无效输入!难以置信!!!
选项C :撤消表单
的方法Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
Cancel = DataIsInvalid(Me.MyTextBox.Value)
If Cancel Then Me.Form.Undo
End Sub
Undo
这里绝对没有。但至少它不会破坏BeforeUpdate Cancel = True代码并允许无效数据站立。
选项D :在BeforeUpdate事件中明确恢复旧值
Private mPrevMyTextBoxValue As Variant
Private Sub MyTextBox_AfterUpdate()
mPrevMyTextBoxValue = Me.MyTextBox.Value
End Sub
Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
Cancel = DataIsInvalid(Me.MyTextBox.Value)
If Cancel Then Me.MyTextBox.Value = mPrevMyTextBoxValue
'If Cancel Then Me.MyTextBox.Text = mPrevMyTextBoxValue
End Sub
尝试将以前的值分配给文本框的.Value
或.Text
属性会导致出现相同的错误消息:
为此字段设置为BeforeUpdate或ValidationRule属性的宏或函数阻止{Program Name}在字段中保存数据。
选项E :在AfterUpdate事件中明确恢复旧值
Private mPrevMyTextBoxValue As Variant
Private Sub MyTextBox_AfterUpdate()
If DataIsInvalid(Me.MyTextBox.Value) Then
Me.MyTextBox.Value = mPrevMyTextBoxValue
Me.MyTextBox.SetFocus
Else
mPrevMyTextBoxValue = Me.MyTextBox.Value
End If
End Sub
这非常接近期望的行为。遗憾的是,由于AfterEpdate事件在处理Tab / Enter按键或鼠标单击事件之前运行,因此无法将注意力集中在控件上。因此,即使我们试图强调焦点到适当的控制(通过上面的.SetFocus
语句),程序也会立即将焦点转移到用户选择的控件上。
在我看来,"对"这样做的方法是使用控件的.Undo
方法。但是,这对于未绑定的控件不起作用。这是一个令人无法解释的缺点,特别是考虑到Escape按键为未绑定的字段执行此功能这一事实。
有更好的方法可以做到这一点,还是应该坚持使用SendKeys
?
答案 0 :(得分:1)
在google上进入第3页后,我决定只是瞎逛,看看在尝试选项E时会发生什么样的排序。以下是我能够使用的最佳解决方法,让我们专注于“留在”文本框中有问题。
Private mPrevMyTextBoxValue As Variant
Private Sub Text0_AfterUpdate()
If Me.Text0.Value = 0 Then
Me.Text0.Value = mPrevMyTextBoxValue
Me.Text12.SetFocus
Me.Text0.SetFocus
Else
mPrevMyTextBoxValue = Me.Text0.Value
End If
End Sub
0模拟验证失败。看起来如果你将焦点设置为别的东西,然后再将它设置回你正在使用的文本框,那么它将保留在那里。不幸的是,我没有答案。
编辑:我已经决定尝试编写我的理论,以确定其工作原理
Private blnGoToNextControl as Boolean
Private Function SetFocus(ctrl As control)
blnGoToNextControl = True
If ctrl.HasFocus = True Then
'Do nothing
Else
ctrl.HasFocus = True
blnGoToNextControl = False
End If
End Function
这是我对SetFocus函数如何工作的想法。因此,在AfterUpdate事件运行之后,它将检查是否要转到下一个控件的标志,并查看它是否设置为false而不是转到下一个控件。
粗略的编码显然但希望这可以解释我的理论?
答案 1 :(得分:0)
如果未绑定,为什么不使用AfterUpdate事件:
Private Sub MyTextBox_AfterUpdate()
If DataIsInvalid(Me!MyTextBox.Value) Then
Me!MyTextBox.Value = Null
Me!MyTextBox.SetFocus
End If
End Sub
或修改您的其他解决方案:
Private Sub MyTextBox_AfterUpdate()
Static mPrevMyTextBoxValue As Variant
If IsEmpty(mPrevMyTextBoxValue) Then
mPrevMyTextBoxValue = Null
End If
If DataIsInvalid(Me!MyTextBox.Value) Then
Me!MyTextBox.Value = mPrevMyTextBoxValue
Me!MyTextBox.SetFocus
Else
mPrevMyTextBoxValue = Me!MyTextBox.Value
End If
End Sub
尝试将焦点从文本框移开,然后返回:
Me!MyTextBox.Value = mPrevMyTextBoxValue
Me!SomeOtherControl.SetFocus
Me!MyTextBox.SetFocus
另一个控件可能是一个几乎隐藏的小文本框。