2

I've got a custom control (inheriting from TextBox) that I'm working with in .NET 4.0.

What I need to be able to do is execute some code after the user has finished his input, e.g. one second after he stops typing.

I can't execute this code block each time the Text changes, for efficiency's sake and because it is somewhat time-consuming. It should ideally only be called once each time the user starts and stops typing. I have begun by using Stopwatch's Restart() inside the OnTextChanged method.

Here's my setup:

public class MyBox : TextBox
{
    private readonly Stopwatch timer;

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        timer.Restart();

        base.OnTextChanged(e);
    }
}

How can I do this efficiently? Are async threads the answer? Or is there some other way?

2
  • Reactive extensions is currently the best way to do this, but the library is difficult to understand. Commented Mar 25, 2013 at 20:43
  • on .net 4.5 bindings have Delay property that does exactly this. Commented Mar 25, 2013 at 23:21

3 Answers 3

7

You can easily do the using a DispatcherTimer:

public class MyBox : TextBox
{
    private readonly DispatcherTimer timer;

    public MyBox()
    {
        timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
        timer.Tick += OnTimerTick;
    }

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        timer.Stop();
        timer.Start();
    }

    private void OnTimerTick(object sender, EventArgs e)
    {
        timer.Stop();
        // do something here
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Use Binding with Delay. Sample:

<StackPanel>
    <TextBox Text="{Binding ElementName=TextBlock, 
                            Path=Text, 
                            Delay=1000}" />
    <TextBlock x:Name="TextBlock" />
</StackPanel>

1 Comment

Nice, but only available with .Net 4.5+
0

If your code can be run on a separate thread, then design your thread code so that it can be just killed off by killing the thread. Then on every key press, kill the old thread (if it exists) and restart a new one with your code.

Note: if your code needs to interact with the UI thread, then you have to make sure to either invoke back to the main thread, or use the 'UpdateStatus' calls which basically do that for you.

Alternately, your timer method will work, but with the caveat when it executes, the main thread will be locked until it's done, hence my first suggestion of a terminable thread.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.