Click here to Skip to main content
15,881,882 members
Articles / Desktop Programming / Windows Forms
Article

Custom TextBox that Delays the TextChanged Event

Rate me:
Please Sign up or sign in to vote.
4.79/5 (19 votes)
17 Aug 20072 min read 96K   3.3K   27   10
Textbox that inherits the base textbox control that delays the text changed event

Introduction

Although I've been browsing The Code Project for sometime, this is my first article so take it easy on me!

I was creating another control, a pager control to be exact, and ran into a problem. The problem was that when a user would type in for example 100 to navigate to that page, I was trapping the TextChanged event and it would first go to page 1, then page 10, then page 100(get the mental picture). I didn't want this to happen for a couple of reasons but the main one is because I'm not storing data of each page in memory and it gets populated when the page is selected from a SQL server, so I wanted to eliminate 3 queries when one is needed for the example previously mentioned.

So I decided that instead of adding a "go" or "refresh" button to my pager control, I would delay the TextBox TextChanged event so as long as the user was typing it would not fire the event until he/she was done(delay threshold was met).

Hope it is useful for someone!

Using the Control

Using the control is trivial because there isn't anything different about the TextBox other than when the TextChanged Event is fired. The only added property is for the Delay and you would set it like this, assuming you already have the control added to your form.

C#
// Delay in number of milliseconds, the delay gets reset after a key press
// if it hasn't already elapsed
delTextBox1.Delay = 1000;
delTextBox1.TextChanged += new EventHandler(delTextBox1_TextChanged);

Explaining the Source

There are only a few main parts, but could be somewhat confusing for a beginner so I will do my best explaining them.

The first thing to create is a new Control that inherits the base TextBox control, add the timer, and the Delay property. The timer will be used to control the TextChanged event that will be discussed later.

C#
...
using System.Timers;

namespace MyControl
{
     public class DelayTextBox : TextBox
     {
           System.Timers.Timer delayTimer;
       private int _threshold = 1000;   // default it 1 second


       // Delay Property to set the amount of time the control
       // waits before firing the TextChanged Event.
           public int Delay
           {
        set{ _threshold = value; }
           }

       public DelayTextBox()
       {
        delayTimer = new System.Timers.Timer( _threshold );
           }
     }
}

The next thing I did was override the KeyPress Event, I needed this to indicate to the TextChanged event that something was being typed into the TextBox.

C#
private bool KeysPressed = false;

protected override void OnKeyPress(KeyPressEventArgs e)
{

   // check if timer has been started, if not start
   // if it has, restart it.
   if (!DelayTimer.Enabled)
   {
      DelayTimer.Enabled = true;
   }
   else
   {
      DelayTimer.Enabled = false;
      DelayTimer.Enabled = true;
   }

   // used to indicate the text was changed because a key was pressed
   // and not just setting the text property.
   KeysPressed = true;

   // execute base code as usual
   base.OnKeyPress(e);
}

Now we need to override the TextChanged event so we can prevent it from firing everytime it actually changes, until the timer elapses.

C#
// set to true in the Timer_Elapsed event.
private bool TimerElapsed = false;

protected override void OnTextChanged(EventArgs e)
{
   // if the timer elapsed or text was changed by something 
   // besides a keystroke
   // fire base.OnTextChanged
   if ( TimerElapsed || !KeysPressed )
   {
       TimerElapsed = false;  // reset
       KeysPressed = false;   // reset
       base.OnTextChanged(e); // run base TextChanged event code.
   }
}

Finally the code for the Timer_Elapsed Event. This part was a little more tricky than the rest because the Timer runs in its own thread so using the Invoke method to make the event fire is required or else it will cause problems in your parent form or control.

C#
public delegate void DelayOverHandler();

public void DelayOver()
{
    // call on textchanged.
    OnTextChanged(new EventArgs());
}

void delayTimer_Elapsed(object sender, EventArgs e)
{
    // stop timer.
    DelayTimer.Enabled = false;

    // set TimerElapsed to true, so the OnTextChange executes its base code.
    TimerElapsed = true;

    // use invoke to get back on the UI thread.
    this.Invoke(new DelayOverHandler(DelayOver), null);
}

This control seems to fit my needs, and I hope someone can use it for something. I plan on adding a keypress filter to only allow numbers, but there are plenty of articles on the topic here to accomplish that.

History

  • 16th August, 2007: Original article posted

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Markus Kiss28-Mar-12 3:12
Markus Kiss28-Mar-12 3:12 
QuestionGood article and one question Pin
smatusan1-Dec-08 11:30
smatusan1-Dec-08 11:30 
GeneralA Delphi Implementation... Pin
me7me7_19799-Oct-07 3:34
me7me7_19799-Oct-07 3:34 
GeneralRe: A Delphi Implementation... Pin
cdgwinn9-Oct-07 5:31
cdgwinn9-Oct-07 5:31 
GeneralAdditional questions! Pin
Martin#21-Aug-07 5:04
Martin#21-Aug-07 5:04 
GeneralRe: Additional questions! Pin
johannesnestler17-Jan-08 5:21
johannesnestler17-Jan-08 5:21 
GeneralKeyPress Filter Pin
Steve Hansen17-Aug-07 5:03
Steve Hansen17-Aug-07 5:03 
GeneralRe: KeyPress Filter Pin
cdgwinn17-Aug-07 5:14
cdgwinn17-Aug-07 5:14 
GeneralRe: KeyPress Filter Pin
Marc Clifton17-Aug-07 15:14
mvaMarc Clifton17-Aug-07 15:14 
GeneralRe: KeyPress Filter Pin
cdgwinn30-Aug-07 4:24
cdgwinn30-Aug-07 4:24 
Thanks Marc, I like this idea, I will implement the DelayedTextChanged event and update the article when I get some free time.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.