Reputation: 1081
I want to extend the TextBox control, so it will fire a custom event with a specified delay.
Here is the code i have so far:
public class DelayTextBox : TextBox
{
private Timer _delayTimer;
private int _threshold = 1000;
public DelayTextBox()
{
_delayTimer = new Timer(_threshold);
_delayTimer.Elapsed += new ElapsedEventHandler(_delayTimer_Elapsed);
}
public int Delay
{
set { _threshold = value; }
}
private void _delayTimer_Elapsed(object sender, ElapsedEventArgs e)
{
_delayTimer.Stop();
RaiseDelayedTextChangedEvent();
}
protected override void OnTextChanged(TextChangedEventArgs e)
{
_delayTimer.Stop();
_delayTimer.Start();
}
private static readonly RoutedEvent DelayedTextChangedEvent = EventManager.RegisterRoutedEvent(
"DelayedTextChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DelayTextBox));
public event RoutedEventHandler DelayedTextChanged
{
add { AddHandler(DelayedTextChangedEvent, value); }
remove { RemoveHandler(DelayedTextChangedEvent, value); }
}
private void RaiseDelayedTextChangedEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(DelayTextBox.DelayedTextChangedEvent);
RaiseEvent(newEventArgs);
}
}
The problem is that whenever i fire RaiseDelayedTextChangedEvent(), i get an exception, telling me
'The calling thread cannot access this object because a different thread owns it.'
The exception is thrown here:
private void RaiseDelayedTextChangedEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(DelayTextBox.DelayedTextChangedEvent);
RaiseEvent(newEventArgs);
} <---- Here
Upvotes: 0
Views: 1500
Reputation: 10533
That's because the Timer runs in a different thread, and UI cannot be modified from that thread (like your exception says). Try using a DispatcherTimer instead. You can learn more about it here: http://code.dortikum.net/2008/08/06/timer-vs-dispatchertimer-in-wpf/
Upvotes: 2
Reputation: 13222
You need to use the dispatcher to raise the event in the STA Thread.
This article explains the threading issues you are having http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher
private void RaiseDelayedTextChangedEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(DelayTextBox.DelayedTextChangedEvent);
this.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
(UpdateTheUI)delegate(RoutedEventArgs eArgs)
{
RaiseEvent(eArgs);
}, newEventArgs );
}
Upvotes: 0