背景:我是vb的新手,来自javascript。
我的任务是使用txtBox.LostFocus事件进行一些验证。问题是如果用户打算按下三个按钮中的任意一个,我需要取消验证步骤。
插图:
代码
Dim lblInputBox As Label
lblInputBox.Text = "Name:"
Dim txtInputBox As TextBox
Dim btnClear As Button
btnClear.Text = "Clear"
Dim btnSayName As Button
btnSayName.Text = "Say Name"
Dim btnExit As Button
btnExit.Text = "Exit"
' Some boolean to determine what the next action is
Dim UserIntentDetected = False
' When the user moves focus away from the textbox
Private Sub txtInputBox_LostFocus(sender As Object, e As EventArgs) _
Handles txtIputBox.LostFocus
' I want to be able to detect the next focus, but this is where I'm going wrong
If btnExit.GotFocus Or btnClear.GotFocus Then
UserIntentDetected = True
Else
UserIntentDetected = False
End If
' Only call validate if there is no intent to quit or clear
If Not UserIntentDetected Then
Call validate()
End If
' Reset the intent boolean
UserIntentDetected = False
End Sub
' Validate subroutine
Private Sub validate()
' **Fixed description**
' User moved focus away from txtbox and doesn't intend to clear or exit
Console.WriteLine("You're NOT INTENDING to clear or exit")
End Sub
我尝试将两个按钮的GotFocus事件添加到输入框的LostFocus事件处理程序中,但是在循环中多次触发事件时出现了错误。
例如:
Private Sub txtInputBox_LostFocus(sender As Object, e As EventArgs) _
Handles txtIputBox.LostFocus, btnExit.GotFocus, _
btnClear.GotFocus
... (code follows)
这些尝试是完全错误的,但是从javascript背景来看,虽然也完全错误,但我可能会破解这样的事情。
... (assume same element structure from vb)
var eventQueue = [];
var userIntentDetected = false;
txtInputBox.addEventListener("blur", function(event){
// Set a timeout to manually trigger the last event's click method in the eventQueue
setTimeout(function(){
if (eventQueue.length > 0 && userIntetDetected)
runIntendedHandler(eventQueue[eventQueue.length -1]);
}, 500);
})
// Both event listeners listen for click and stop default actions,
// set intent boolean to true, and add it's event object to a queue
btnExit.addEventListener("click", function(event){
event.preventDefault();
userIntentDetected = true;
eventQueue.push(event);
});
btn.addEventListener("click", function(event){
event.preventDefault();
userIntentDetected = true;
eventQueue.push(event);
});
// Validation should occur only if the user moves focus to an element
// that IS NOT either the btnExit or btnClear
function runIntendedHandler(event){
if (event.target.id = "btnExit")
// run exit functions
code...
else if (event.target.id = "btnClear")
// run clear functions
code..
userIntentDetected = false;
}
在vb中处理事件的正确方法是什么?如何在触发操作之前检测队列中的下一个事件? RaiseEvent语句可以帮助吗?
更新3 :答案比我看起来容易得多。显然,您可以使用btn.Focused属性从txtInputBox.LostFocus事件处理程序中检查元素的下一个焦点... Go figure!
UPDATE 2 :关于究竟需要什么,已经存在很多混淆,而且很多是我在描述验证子程序时的错误。我已经更改了一些元素名称并添加了一个图像来总结我的教师给我的所有信息。
更新1 :@TnTinMn提供了可以与次要更改一起使用的最接近的工作答案。 示例如下:
Private LastActiveControl As Control = Me ' initialize on form creation
Protected Overrides Sub UpdateDefaultButton()
' Just added an IsNot condition to stay inline with the requirements
If (LastActiveControl Is txtNumberOfDrinks) AndAlso
((ActiveControl Is btnClear) OrElse (ActiveControl Is btnExit)) Then
Console.WriteLine("Your intent to press either btnClear or btnExit has been heard...")
' Validation happens only if the user didn't intend to click btnClear or btnExit
ElseIf (LastActiveControl Is txtNumberOfDrinks) AndAlso
((ActiveControl IsNot btnClear) OrElse (ActiveControl IsNot btnExit)) Then
Console.WriteLine("You didn't press either btnClear or btnExit.. moving to validation")
validateForm()
End If
LastActiveControl = ActiveControl ' Store this for the next time Focus changes
End Sub
谢谢大家!
答案 0 :(得分:1)
Winform的活动顺序充其量令人困惑。有关摘要,请参阅Order of Events in Windows Forms。
假设我已正确解释了你的目标,我不会回应txtInputBox.LostFocus事件,而是覆盖一个名为UpdateDefaultButton的鲜为人知的Form方法。当Form.ActiveControl属性更改时,将调用此方法,并有效地为您提供ActiveControl更改的伪事件。如果新的ActiveControl是Button,则此方法也会在Button.Click事件被引发之前执行。
由于您只想在焦点从txtInputBox更改为btnPromptForName或btnExit时调用验证代码,您可以使用类似的方式完成此操作。
Public Class Form1
Private LastActiveControl As Control = Me ' initialize on form creation
Protected Overrides Sub UpdateDefaultButton()
If (LastActiveControl Is tbInputBox) AndAlso
((ActiveControl Is btnPromptForName) OrElse (ActiveControl Is btnExit)) Then
ValidateInput()
End If
LastActiveControl = ActiveControl ' Store this for the next time Focus changes
End Sub
Private Sub ValidateInput()
Console.WriteLine("You're either intending to prompt for name or exit")
End Sub
Private Sub btnPromptForName_Click(sender As Object, e As EventArgs) Handles btnPromptForName.Click
Console.WriteLine("btnPromptForName_Click clicked")
End Sub
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
Console.WriteLine("btnExit clicked")
End Sub
End Class
编辑:我忘了提及,因为UpdateDefaultButton
在引发Button.Click事件之前运行,所以只有在验证成功时才可以连接click事件处理程序。然后,您将删除事件处理程序作为Button.Click处理程序代码的一部分。
答案 1 :(得分:0)
看起来解决方案比我想象的容易得多。预期(讲师)的方法是通过检查txtInputBox.LostFocus事件处理程序中的备用“btn.Focused”属性,例如:
' When the user moves focus away from the textbox
Private Sub txtInputBox_LostFocus(sender As Object, e As EventArgs) _
Handles txtIputBox.LostFocus
' Check if the clear or exit button is focused before validating
' Validate only if btnClear and also btnExit IS NOT focused
If Not btnExit.Focused AndAlso Not btnClear.Focused Then
Call validateForm()
End If
End Sub
感谢@TnTinMn UpdateDefaultButton并向我展示了跟踪事件的替代方法。这也非常有用。