2017-01-21 9 views
0

背景:私はVBで新しく、javascriptから来ています。VB:イベントを手動で呼び出したり遅延させる方法は?

私の割り当ては、txtBox.LostFocusイベントを使用して検証を行うことです。問題は、ユーザが3つのボタンのうちの2つを押すことを意図している場合、検証ステップをキャンセルする必要があることです。

イラスト:私は入力ボックスのLostFocusイベントハンドラに2つのボタンのGotFocusイベントを追加しようとしましたが、イベントの発火とのバグがありました

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 

Project Instructions and Outline

コードループで複数回

例:

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ステートメントのヘルプはありますか?

UPDATE 3:答えは、私が思ったよりもずっと簡単でした。どうやら、btn.Focusedプロパティを使用して、txtInputBox.LostFocusイベントハンドラ内から要素の次のフォーカスを確認できます。

UPDATE 2:正確に何が必要なのかについて多くの混乱がありました。その多くは、検証サブルーチンを記述する際の私の責任でした。私はいくつかの要素名を変更し、インストラクターによって私に与えられたすべての情報をまとめたイメージを追加しました。

UPDATE 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

winformsの土地では、通常、検証をキャンセルしません。ユーザーが遅れないようにすばやく実行するか、ユーザーが実際に操作を試みるまで検証しないでください。意図は関係ありません。 –

+0

私はこの任務の性質がそのようなものなのかどうかはわかりませんが、指示がはっきりしているので、これは私が掘ったウサギの穴です。 – 4UmNinja

+0

上の宣言で、3つのボタンをまだStringとして割り当てようとしています - Option Strictをonにして、すぐにエラーを見てください。典型的にはこれらはデザイナーに組み込まれるべきです。 – OneFineDay

答えて

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 

UpdateDefaultButtonためにあなた@TnTinMnに感謝し、私に追跡する別の方法を示しますイベント。これもとても役に立ちました。

1

Winformのイベントの順序は、まったく混乱します。要約はOrder of Events in Windows Formsを参照してください。

あなたの目標を正しく解釈したと仮定すると、私はtxtInputBox.LostFocusイベントに応答せず、UpdateDefaultButtonという少し知られているフォームメソッドをオーバーライドします。このメソッドは、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が実行されていることを忘れてしまいました。Clickイベントが発生した場合、検証が成功した場合にのみクリックイベントハンドラのワイヤーアップが可能です。その後、Button.Clickハンドラコードの一部としてイベントハンドラを削除します。

+0

これは私が[マイナーチェンジ](https://gist.github.com/phreelyfe/b2850d0cc6637a5289bfffc9d22c7832)で探しているソリューションとほぼ同じです。また、私はこれを実行すると、テキストボックスから離れてタブするとき、それは2回検証しようとします。 – 4UmNinja

+1

なぜ検証コードが2回実行されるのかわかりません。 UpdateDefaultButtonは、ActiveControlの変更時に1回だけ実行され、このアプローチを前提としています。リンクされたコードは、私があなたの質問から推測した意図とは反対の第2の条件を示しています。他の多くの人があなたの意図を理解するのに問題があったので、私はそれに驚かない。この方法で問題が解決された場合は、それを答えとしてマークし、問題解決のために時間を無駄にしないようにしてください。 – TnTinMn

+0

ご返信ありがとうございます。方向がわかりづらいことは申し訳ありませんが、可能な限り明確にしようとしました。オリジナルの投稿では、ユーザーが2つのボタンのいずれかをクリックしたときに検証をキャンセルする必要があることに言及しています。私が別の答えを待っていたのはもともと私がtxtBox.LostFocusを使ってあなたが提供したことを正確に行うソリューションを求めたのですが、あなたのソリューションはうまく動作します。この擬似コードの例では、十分にはっきりしていると思っていましたが、私が望む言葉を言葉で表現するのに十分なこの言語についてはわかりません。どうも! – 4UmNinja

関連する問題