2009-03-22 11 views
16

挨拶のすべてを入力して行われるまで待って、.NET --- TextBoxコントロールを - ユーザーが

は、ユーザーがテキストボックスに入力して実行されたときに知っている方法で構築ありますか? (タブを押す前、またはマウスを動かす前)textchangedイベントで発生するデータベースクエリがあり、すべてが完全に機能します。しかし、ユーザーがテキストボックスにすばやく入力すると、プログラムは各文字のクエリを実行しているため、少し遅れがあることに気付きました。だから私が望んでいたのは、ユーザーが入力を完了したかどうかを確認する方法でした。したがって、「a」と入力して停止すると、イベントが発生します。ただし、「すべての方法」と入力すると、yキーアップ後にイベントが発生します。

私の頭の周りに浮かぶアイデアがありますが、私は彼らが最も効率的ではないと確信しています。最後のtextchangeイベント以降の時間を測定する場合と同様に、ある値よりも大きい場合は、残りの手順を実行します。

あなたの意見を教えてください。

言語:VB.NET フレームワーク: "済タイピング" .NET 2.0

--Editedは、それはあなたが何を意味するかに依存し

答えて

34

一つのアプローチ:

  1. は、間隔は300ミリ秒であるべきであるXのミリ秒のInterval

    Timerを作成します。それがすでにある場合、これはTimerを再起動しますTimer

    を終え、更新が入力のTextChangedイベント、Stop()

  2. を発生し、その後Start()の間に待機するキーストローク、また、合理的な時間の間に通常時よりもユーザーが通常の速度で入力を続けている場合は、それぞれの変更がタイマーを再起動します。タイマーのTickイベントで

  3. TimerStop()とは

  4. オプションの長いトランザクションを実行します。LeaveKeyDownイベントを処理するように制御を残したりTimerStop()ますを入力して、長いを行う押しますトランザクション。

これは、テキストが変更され、ユーザーがXミリ秒で変更を加えなかった場合に更新を行います。

"最後の更新からの経過時間を測定する"アプローチの1つの問題は、最後の変更がすぐに行われた場合、更新は行われず、引き続きトリガする変更がないことです別の小切手。

注:TextBoxTimerの間に1対1のペアが存在する必要があります。あなたが複数の入力でこれを行う上で計画している場合、私はこの機能をラップUserControlの構築を検討したいです。

+0

私たちが使うアプローチはかなりです。 –

+0

良い計画、提案していただきありがとうございます。 ms値を与えることも非常に有益です。 –

+0

@Cj Anderson:応答性とタイピングスピードのバランスが適切になるようにするには、ちょっと試してみる必要があるかもしれません。 –

1

"入力完了" を明確にしますユーザーがその特定のコントロールのフォーカスを放置したときに通知するイベントがあります。また、変更された偶数があり、テキストがいつ変更されるかがわかります。 、

1)ロストフォーカス

2)ユーザーがテキストを変更し、20秒、と言うのためのタイマーを起動し、ユーザーがその時間内に行われたかどうかたび:何あなたができることはトラップ二つのことですユーザーは入力を「完了」します。つまり、ユーザーがその時間内に何もしなかった場合、ユーザーは「完了」していると想定します。

これらの2つのいずれかが発生した場合は、ユーザーが完了したので、タイマーを適切に停止して再起動してください。明らかに、あなたはタイムアウトを変更することができます。

すべての定義方法によって異なります。

+0

・ホープ..テキストボックスに由来し、同じアプローチを使用してコントロールを作りましたユーザはその時間内に完了する」という意味ですか?追加の文字を入力していないことは? –

+0

はい、申し訳ありませんが、私はこれを反映するためにポストを編集しました。 – BobbyShaftoe

0

私は、過去に首尾よく使用されてきたアプローチは、ユーザが入力を停止したときを検出するために、手動リセットイベントと非同期呼び出しを使用しています。コードは、それがスレッド、代表団との基本的なラムダ構文に関するいくつかのより深い知識が必要なものの、私はスコット・ワインスタインの答えをしようとしてしまったこの

// use manual reset event to Q up waiting threads. 
// each new text changed event clears the Q 
// only the last changed will hit the timeout, triggering the action 
private ManualResetEvent _delayMSE; 
private Func<bool> TBDelay =() => !_delayMSE.WaitOne(600, false); 
private void TextBox_TextChanged(object sender, TextChangedEventArgs e) 
{ 
    SendOrPostCallback ActionToRunWhenUserStopsTyping = o => 
    { 
     // ... 
    }; 

    _delayMSE.Set(); // open the ResetEvent gate, to discard these delays 
    Thread.Sleep(0); // let all pending through the gate 
    _delaySearchMSE.Reset(); // close the gate 
    TBDelay.BeginInvoke(res => 
    { 
     // callback code 
     // check how we exited, via timeout or signal. 
     bool timedOut = TBDelay.EndInvoke(res); 
     if (timedOut) 
      Dispatcher.Invoke(DispatcherPriority.Input, 
          ActionToRunWhenUserStopstyping,null); 
    }, null); 
} 
3

ようになります。そしてそれはかなりうまくいった。彼のオリジナルの答えは純粋なコピーペーストではなかったので、私はそれを動作させるために遊んでいなければなりませんでした。

私は、ユーザーがすぐになく、キーストロークの一部の間の小さなランダム遅延で本当に入力している場合はinvokeメソッドが二回発生する可能性が気づいたので、私は、のThread.sleepにほんの少しの時間を追加しました。また、Dispatcherを使用するためにWindowsBaseアセンブリへの参照を追加する必要があります。

私は、ユーザエンド入力を待つために1,5秒を使用します。このようなもので、.NET 2.0を必要とする人のために

// use manual reset event to Q up waiting threads. 
    // each new text changed event clears the Q 
    // only the last changed will hit the timeout, triggering the action 
    private ManualResetEvent _delayMSE; 
    private Func<bool> TBDelay; 
    private delegate void ActionToRunWhenUserStopstyping(); 

    public Form1() 
    { 
     InitializeComponent(); 

     _delayMSE = new ManualResetEvent(false); 
     TBDelay =() => !_delayMSE.WaitOne(1500, false); 
    } 

    private void textBox1_TextChanged(object sender, EventArgs e) 
    { 
     _delayMSE.Set(); 

     // open the ResetEvent gate, to discard these delays  
     Thread.Sleep(20); 
     // let all pending through the gate  
     _delayMSE.Reset(); 
     // close the gate 
     TBDelay.BeginInvoke(res =>  
     {   
      // callback code   
      // check how we exited, via timeout or signal.   
      bool timedOut = TBDelay.EndInvoke(res); 
      if (timedOut) 
       Dispatcher.CurrentDispatcher.Invoke(
        new ActionToRunWhenUserStopstyping(DoWhatEverYouNeed), 
        DispatcherPriority.Input); 
     }, null); 
    } 

    private void DoWhatEverYouNeed() 
    { 
     MessageBox.Show(textBox1.Text); 
    } 
5

、ここに私がしている場合、「何このヘルプ

public partial class TextBox : System.Windows.Forms.TextBox 
{ 

    private ManualResetEvent _delayMSE; 
    public event EventHandler OnUserStopTyping; 
    private delegate bool TestTimeout(); 

    public TextBox() 
    { 
     _delayMSE = new ManualResetEvent(false); 
     this.TextChanged += new EventHandler(TextBox_TextChanged); 
    } 

    void TextBox_TextChanged(object sender, EventArgs e) 
    { 


     _delayMSE.Set(); 
     Thread.Sleep(20); 
     _delayMSE.Reset(); 

     TestTimeout tester = new TestTimeout(TBDelay); 
     tester.BeginInvoke(new AsyncCallback(Test), tester); 

    } 


    private void Test(IAsyncResult pResult) 
    { 
     bool timedOut = (bool)((TestTimeout)pResult.AsyncState).EndInvoke(pResult); 
     if (timedOut) 
     { 
      if (OnUserStopTyping != null) 
       OnUserStopTyping(this, null); 
     } 
    } 

    private bool TBDelay() 
    { 
     return !_delayMSE.WaitOne(500, false); 
    } 

} 
+0

良い解決策。私はあなたのコードを私のものにアダプターしました。イベントOnUserStopTypingを拡張して、現在私のために働いています。ご協力いただきありがとうございます。 –