I was wondering if it's possible to raise a PropertyChanged
event when the user pauses while typing text into a TextBox
? Or more specifically, I want to run a method X
seconds after the user stops typing in a TextBox.
For example, I have a form with a TextBox and nothing else. The user types in a 1-9 digit Id value into the TextBox, a fairly resource-intensive background process loads the record.
I do not want to use the UpdateSouceTrigger=PropertyChanged
because that would cause the resource-intensive background process to run whenever a character gets typed, so a 9-digit ID number starts off 9 of these processes.
I also don't want to use UpdateSourceTrigger=LostFocus
because there is nothing else on the form to make the TextBox lose focus.
So is there a way to cause my background process to run only after the user pauses when typing in the Id number?
I think this is exactly what you're looking for: DelayBinding for WPF
It is custom binding that does exactly what the two answers above suggest. It maxes it as easy as writing
<TextBox Text="{z:DelayBinding Path=SearchText}" />
or to specify the delay interval<TextBox Text="{z:DelayBinding Path=SearchText, Delay='00:00:03'}" />
Why not use
UpdateSouceTrigger=PropertyChanged
, but instead of directly firing off your background process have it reset a timer that will fire off that process after, say, 3 seconds. That way if they type something else in before 3 seconds is up, the timer gets reset and the background process will occur +3 more seconds from now.Set
UpdateSourceTrigger=PropertyChanged
, and then each time the property changes, kick off a timer for the delay you'd like. If the property is changed again prior to the timer tick, then cancel the old timer and kick off a new one. If the timer does tick, then you know the property hasn't changed in X seconds, and you can kick off the background process.Prepare for code-dump.
I've done this with a WPF Fake Behavior (an attached DP that acts like a behavior). This code works, but it isn't pretty and it may result in leaks. Probably need to replace all the references with weak references, etc.
Here's the Behavior class:
And here's an example of how it is used:
The gist of this is...
You set the attached property on the bound UIElement, passing in the DP you wish to delay. At this point, I have the target of the attached property and the property to be delayed, so I can set things up. I do have to wait until the binding is available, so I have to use the Dispatcher to instantiate my watcher class after databinding has been set up. Fail to do this and you can't grab the binding expression.
The watcher class grabs the binding and adds an update listener to the DependencyProperty. In the listener, I set up a timer (if we haven't updated) or reset the timer. Once the Timer ticks, I fire off the binding expression.
Again, it works, but it definitely needs cleanup. Also, you can just use the DP via its name with the following code snippet:
You might have to tack "Property" onto
name
, but that's easy compared to usingx:Static
.If you are using .NET 4.5 or above you can use the Delay property of a Binding. It's really easy: