Providing delay on textbox_textchanged
I have a barcode scanner that emulates keyboard input. I use it to enter ISBN numbers into a text box, which then searches for that title. I need the textbox method to wait for a 10 or 13 chars record binding before doing anything, however I'm not sure how.
So far I have the following:
private void scanBox_TextChanged(object sender, EventArgs e)
{
if (scanBox.Text.Length == 10)
{
getRecord10();
}
else if (scanBox.Text.Length == 13)
{
getRecord13();
}
else
{
MessageBox.Show("Not in directory", "Error");
}
}
I'm considering some kind of timer implementation to hold on to this last condition, but I really need the method to expect 10 or 13 digits. The barcode scanner emulates individual keystrokes, so it doesn't currently work.
source to share
You can use Timer (or DispatcherTimer in WPF). This sample application updates the window title 300ms after the last key press.
System.Windows.Forms.Timer _typingTimer; // WinForms
// System.Windows.Threading.DispatcherTimer _typingTimer; // WPF
public MainWindow()
{
InitializeComponent();
}
private void scanBox_TextChanged(object sender, EventArgs e)
{
if (_typingTimer == null)
{
/* WinForms: */
_typingTimer = new Timer();
_typingTimer.Interval = 300;
/* WPF:
_typingTimer = new DispatcherTimer();
_typingTimer.Interval = TimeSpan.FromMilliseconds(300);
*/
_typingTimer.Tick += new EventHandler(this.handleTypingTimerTimeout);
}
_typingTimer.Stop(); // Resets the timer
_typingTimer.Tag = (sender as TextBox).Text; // This should be done with EventArgs
_typingTimer.Start();
}
private void handleTypingTimerTimeout(object sender, EventArgs e)
{
var timer = sender as Timer; // WinForms
// var timer = sender as DispatcherTimer; // WPF
if (timer == null)
{
return;
}
// Testing - updates window title
var isbn = timer.Tag.ToString();
windowFrame.Text = isbn; // WinForms
// windowFrame.Title = isbn; // WPF
// The timer must be stopped! We want to act only once per keystroke.
timer.Stop();
}
Parts of the code are taken from the Roslyn syntax visualizer
source to share
I suggest a solution using Microsoft Reactive Extensions which are available as a nuget package.
Reactive Extensions is a library for creating asynchronous and event-based programs using observable collections and LINQ type query operators.
If you are using RX extensions, your problem can be solved with just two lines of code:
Sign up for the event: here with score == 10
IObservable<string> textChangedObservable =
Observable.FromEventPattern(textBox1, "TextChanged")
.Select(evt => ((TextBox)evt.Sender).Text).Where(x => x.Length == 10);
Subscribe to the event:
textChangedObservable.Subscribe(e => MessageBox.Show(e));
source to share
Check if this helps.
private System.Timers.Timer timer;
private void scanBox_TextChanged(object sender, EventArgs e)
{
if (scanBox.Text.Length == 10)
{
//wait for 10 chars and then set the timer
timer = new System.Timers.Timer(2000); //adjust time based on time required to enter the last 3 chars
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
}
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
timer.Enabled = false;
if (scanBox.Text.Length == 10)
{
getRecord10();
}
else if (scanBox.Text.Length == 13)
{
getRecord13();
}
else
{
MessageBox.Show("Not in directory", "Error");
}
}
source to share