2009-03-22 18 views
16

अभिवादन सब किया जाता है इंतज़ार,नेट --- पाठ बॉक्स नियंत्रण - जब तक उपयोगकर्ता टाइपिंग

वहाँ है एक तो किसी उपयोगकर्ता द्वारा पाठ बॉक्स में टाइप किया जाता है पता करने के लिए रास्ते में बनाया? (टैब को मारने से पहले, या माउस को ले जाने से पहले) मेरे पास एक डेटाबेस क्वेरी है जो टेक्स्टchanged ईवेंट पर होती है और सब कुछ पूरी तरह से काम करता है। हालांकि, मैंने देखा कि पाठ्यक्रम का थोड़ा सा अंतराल है क्योंकि यदि उपयोगकर्ता जल्दी से टेक्स्टबॉक्स में टाइप कर रहा है तो प्रोग्राम प्रत्येक चरित्र के लिए एक क्वेरी कर रहा है। तो मैं यह देखने का एक तरीका था कि उपयोगकर्ता ने टाइपिंग समाप्त कर दी है या नहीं। तो अगर वे "ए" टाइप करते हैं और रोकते हैं तो एक घटना आग लगती है। हालांकि, अगर वे वाई कुंजीपटल के बाद घटना को "सभी तरह से" टाइप करते हैं।

मेरे पास मेरे सिर के चारों ओर तैरने वाले कुछ विचार हैं लेकिन मुझे यकीन है कि वे सबसे कुशल नहीं हैं। आखिरी टेक्स्टचेंज इवेंट के बाद से समय को मापने की तरह और यदि यह एक निश्चित मूल्य से> तो यह मेरी बाकी प्रक्रियाओं को चलाने के लिए आगे बढ़ेगा।

मुझे बताएं कि आप क्या सोचते हैं।

भाषा: VB.NET फ्रेमवर्क: "। किया टाइपिंग" नेट 2.0

--Edited स्पष्ट करने के लिए

उत्तर

34

एक दृष्टिकोण:

  1. एक्स मिलीसेकेंड के Interval

    अंतराल 300 मि.से के बारे में होना चाहिए के साथ एक Timer बनाएं; कीस्ट्रोक्स, और यह भी उचित समय के बीच एक सामान्य समय की तुलना में अधिक परिष्करण और अद्यतन

  2. इनपुट के TextChanged घटना में, Stop() और फिर Start() होने वाली बीच प्रतीक्षा करने Timer

    यह Timer पुनः आरंभ करेगा अगर यह पहले से ही है चल रहा है, इसलिए यदि उपयोगकर्ता सामान्य दर पर टाइपिंग रखता है, तो प्रत्येक परिवर्तन टाइमर को पुनरारंभ करेगा।

  3. टाइमर के Tick घटना में, Stop()Timer और लंबे समय से लेन-देन

  4. वैकल्पिक कार्य करें: Leave और KeyDown घटनाओं संभाल ताकि नियंत्रण छोड़ने या दर्ज TimerStop() होगा और लंबे समय से कर दबाने लेन-देन।

पाठ बदल गया है, तो उपयोगकर्ता अपडेट मिलेगा, और उपयोगकर्ता ने एक्स मिलीसेकंड में कोई बदलाव नहीं किया है।

"अंतिम अद्यतन के बाद से समय का आकलन करें" दृष्टिकोण आप विचार कर रहे साथ एक समस्या यह है कि अगर अंतिम परिवर्तन जल्दी से किया जाता है, अद्यतन नहीं होगा, और ट्रिगर करने के लिए बाद में किसी भी परिवर्तन नहीं होगी है एक और जांच

नोट: TextBox तों और Timer रों के बीच एक जोड़ी के लिए एक एक वहाँ होना चाहिए; यदि आप इसे एक से अधिक इनपुट के साथ करने की योजना बना रहे हैं, तो मैं UserControl बनाने पर विचार करूंगा जो इस कार्यक्षमता को लपेटता है।

+0

बहुत अधिक दृष्टिकोण हम उपयोग करते हैं। –

+0

अच्छी योजना, सुझाव के लिए धन्यवाद। एमएस मूल्य देना भी बहुत उपयोगी है धन्यवाद। –

+0

@ सीजे एंडरसन: आपको प्रतिक्रिया और टाइपिंग गति के बीच सही संतुलन खोजने के लिए थोड़ा सा खेलना पड़ सकता है –

1

यह आप से क्या मतलब है पर निर्भर करता है "टाइप किया" जब उपयोगकर्ता ने उस विशेष नियंत्रण पर ध्यान दिया है तो आपको यह बताने के लिए एक घटना है। साथ ही, एक बदलाव भी है जो आपको बताता है कि पाठ कब बदलता है। क्या तुम कर सकते हो जाल दो बातें है:

1) खो फोकस

2) हर बार जब उपयोगकर्ता पाठ बदल जाता है, कहते हैं के लिए, 20 सेकंड के एक टाइमर प्रारंभ करें, और उपयोगकर्ता उस समय के भीतर किया जाता है, तो उपयोगकर्ता "किया" टाइपिंग है। ऐसा है कि उपयोगकर्ता ने उस समय कुछ भी नहीं किया है, तो मान लीजिए कि उपयोगकर्ता "किया गया है।"

यदि इनमें से दो चीजें होती हैं तो उपयोगकर्ता किया जाता है, सुनिश्चित करें कि टाइमर को उचित रूप से रोकें और पुनरारंभ करें। जाहिर है, आप टाइमआउट बदल सकते हैं।

यह सब इस बात पर निर्भर करता है कि आप इसे कैसे परिभाषित करना चाहते हैं।

+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

मैं स्कॉट वीन्स्टीन जवाब कोशिश कर समाप्त हो गया है, हालांकि यह सूत्रण, प्रतिनिधियों और बुनियादी लैम्ब्डा सिंटैक्स के बारे में कुछ गहरे ज्ञान की आवश्यकता की तरह कुछ लग रहा है। और यह बहुत अच्छी तरह से काम किया। उनका मूल जवाब शुद्ध प्रतिलिपि नहीं था इसलिए मुझे इसे काम करने के लिए कुछ खेलना पड़ा।

मैंने थ्रेड के लिए बहुत कम समय जोड़ा। सो, चूंकि मैंने देखा कि विधि दो बार हो सकती है यदि उपयोगकर्ता वास्तव में जल्दी टाइप कर रहा है लेकिन कुछ कीस्ट्रोक के बीच छोटे यादृच्छिक विलंब के साथ। आपको डिस्पैचर का उपयोग करने के लिए विंडोजबेस असेंबली का भी संदर्भ जोड़ना होगा।

मैं उपयोगकर्ता अंत टाइपिंग का इंतजार करने के लिए 1,5 सेकंड का उपयोग करता हूं।

// 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

जो लोग कुछ इस तरह की जरूरत के लिए में .NET 2.0, यहाँ मैं एक नियंत्रण है कि पाठ बॉक्स से निकला है और एक ही दृष्टिकोण का उपयोग करता .. आशा बनाया इस मदद

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

अच्छा समाधान। मैंने आपके कोड को मेरा एडाप्टर किया है। ईवेंट ऑनयूसर स्टॉप टाइपिंग और अब मेरे लिए काम कर रहा है। आपकी सहायता के लिए धन्यवाद. –

संबंधित मुद्दे