.NET ---文本框控件 - 等到用户完成输入

时间:2009-03-22 22:40:22

标签: .net vb.net textbox

问候所有人,

是否有内置的方法来了解用户何时输入文本框? (在点击标签之前,或者移动鼠标)我有一个在textchanged事件上发生的数据库查询,一切都很完美。但是,我注意到当然存在一些延迟,因为如果用户正在快速键入文本框,则程序正忙于对每个字符进行查询。所以我希望的是一种查看用户是否已完成输入的方法。因此,如果他们键入“a”并停止,则会触发事件。但是,如果他们输入“一直”,事件将在y键盘后触发。

我脑子里浮现出一些想法,但我确信它们不是最有效的。就像测量自上次textchange事件以来的时间以及它是否是>如果超过某个值,它将继续运行我的其余程序。

让我知道你的想法。

语言:VB.NET 框架:.Net 2.0

- 编辑澄清“完成打字”

6 个答案:

答案 0 :(得分:34)

一种方法:

  1. 创建Timer,其中Interval为X毫秒

    间隔应为约300ms;击键之间的正常时间,以及在完成和更新之间等待的合理时间

  2. 在输入的TextChanged事件中,Stop()然后Start() Timer

    如果Timer已经运行,这将重新启动Tick,因此如果用户继续以正常速率键入,则每次更改都会重新启动计时器。

  3. 在计时器的Stop()活动中,Timer Leave并执行长期交易

  4. 可选:处理KeyDownStop()事件,以便离开控件或按 Enter Timer TextBox和做长期交易。

  5. 如果文本已更改,则会导致更新,并且用户未在X毫秒内进行任何更改。

    您正在考虑的“测量自上次更新以来的时间”方法的一个问题是,如果最后一次更改是快速进行的,则更新将不会发生,并且不会有任何后续更改来触发另一个检查。

    注意: Timer es和UserControl s之间必须进行一对一配对;如果您计划使用多个输入执行此操作,我会考虑构建一个包含此功能的{{1}}。

答案 1 :(得分:5)

对于那些在.NET 2.0中需要这样的东西的人来说,我在这里制作了一个源自TextBox并使用相同方法的Control。 希望这个帮助

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); 
    }

}

答案 2 :(得分:3)

我最终尝试了Scott Weinstein的答案,尽管它需要一些关于线程,委托和基本lambda语法的更深入的知识。它运作得很好。他的原始答案不是纯粹的复制粘贴,所以我不得不做一些游戏来使它工作。

我给Thread.Sleep添加了很少的时间,因为我注意到如果用户输入非常快,但在某些键击之间有很小的随机延迟,则invoke方法可能会发生两次。您还必须添加对WindowsBase程序集的引用以使用Dispatcher。

我用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);
    }

答案 3 :(得分:1)

这取决于“完成打字”的含义。当用户离开该特定控件的焦点时,会有一个事件让您知道。此外,甚至会在文本发生变化时告诉您更改。你能做的就是陷入两件事:

1)失去焦点

2)每次用户更改文本时,启动计时器20秒,如果用户在该时间内完成,则用户“完成”键入。也就是说,如果用户在该时间内没有做任何事情,那么假设用户已经“完成”。

如果这两件事中的任何一件发生,那么用户就完成了,请确保适当地停止并重新启动计时器。显然,你可以改变超时。

这一切都取决于你想如何定义它。

答案 4 :(得分: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);
}

答案 5 :(得分:0)

'vb.net语言 '全局声明

Public Tawal as integer 

'关于timer1的属性

Timer1.enable = true
Timer1.inverval =1000

关于程序

Timer1.start()
if Tawal <2 then T awal =0
if Tawal >3 then 
   Call FillGrid
   Timer1.stop()
end if
相关问题