DelayBinding: a custom WPF Binding

Published on: 2 Oct 2009

When you use the Outlook 2007 search, Vista's start search, or the Search bar in Explorer, there's often a short delay between when you press a key, and when the search begins.

In WPF, we could simulate this through a series of event handlers, timers and code-behind directly on controls, but we usually want to be able to use this alongside WPF's data binding capabilities. To use WPF data binding in a delayed fashion, I created a simple markup extension which creates a binding and manages the timer delay between commits.

Here's how you can use it:

<TextBox Text="{z:DelayBinding Path=SearchText}" />

You can also set an explicit delay. By default, it uses 0.5 seconds, which felt consistent with Outlook, though I didn't spend that much time working out exactly how long Outlook waits. I did look to see if there was a SystemParameters class for something like "SearchDelay", but couldn't find one. Suggestions for a better default are welcome.

<TextBox Text="{z:DelayBinding Path=SearchText, Delay='00:00:01'}" />

Instead of creating a new type of Binding, I'm using the standard WPF Binding, but setting the UpdateSourceTrigger to Explicit. As the text changes, the timer is reset, and when it ticks the value is pushed to the source.

I imagine this would be useful for Silverlight, but since Silverlight does not support custom MarkupExtensions, and since Silverlight Binding's can't have an UpdateSourceTrigger (to set it to Explicit), I expect you would end up creating it through an attached dependency property and triggering the binding to push manually. Let me know if you write one.

Welcome, my name is Paul Stovell. I live in Brisbane and work on Octopus Deploy, an automated deployment tool for .NET applications.

Prior to founding Octopus Deploy, I worked for an investment bank in London building WPF applications, and before that I worked for Readify, an Australian .NET consulting firm. I also worked on a number of open source projects and was an active user group presenter. I was a Microsoft MVP for WPF from 2006 to 2013.

Hi Paul,
Nice post, just a puntualization: Silverlight 3 support UpdateSourceTrigger but unfortunately still misses MarkupExtensions.

James Chaldecott

02 Oct 2009

Hi Paul. Glad to see you're blogging again!

I remember the first time you posted this, and had cause to use it a month or two ago. When I dug through the sources I found an issue, though, and I think it's still there. The AddValueChanged call on the DependencyPropertyDescriptor will stop the binding source from being garbage collected, as it ends up in a static HashTable.

We've had loads of problems with leaks of this nature in our app (not using DelayBinding), as we add & remove UI as the user navigates, and one rooted control will root everything it's connected to in the visual tree (through the Parent and Child/Children properties of all the controls).

Anyway, I've previously gone to a lot of effort with hooking Loaded & Unloaded events on controls and things like that to be able to add and remove the ValueChanged handlers at the right times. I've just found this blog post, though, which looks like it might offer an answer.

Cheers,

James

P.S. Did you lose all your old website content when it went down, or is there a chance you could restore your old blog posts? There was some gold in there, particularly w.r.t. Bindable.Linq, which we're using a lot.

I'll read the post you linked to and see if I can improve the article - this one was a post of the original article, but I think I have modified code myself somewhere that also made it more reliable.

I still have the old content which I'm slowly converting over. Hopefully in a couple of weeks it will all be back up.

Paul

Reilly

17 Nov 2009

Any idea how you could modify this code so that the extension could be used as part of a MultiBinding?

PV

05 Dec 2009

I have a small problem with it. For me the BindingTargetTargetPropertyChanged gets called which starts the timer, and then BindingTargetKeyUp gets called stopping the timer.
In BindingTarget_KeyUp is there a reason the _timer.Stop() isn't inside the if statement?

Hi. First, thanks for this great delayed binding. It's exactly what I need, once I get it working. The problem I'm encountering is that bindingTarget in

var bindingTarget = valueProvider.TargetObject as DependencyObject;

is always null. The TargetObject is some kind of System.Windows.SharedDp, per the exception thrown: "The property 'Text' on target 'System.Windows.SharedDp' is not valid for a DelayBinding...." I'm using this DelayedBinding extension to bind a TextBox to a large string (of xml). Normal bindings work fine. The TextBox is in a DataTemplate. The binding is: