I am currently migrating a number of attached behaviours I have created to Blend Behaviours so that they support drag and drop within Expression Blend. I have noticed that authors of Blend behaviours tend to define the behaviour properties as dependency properties.
I have created a behaviour, TiltBehaviour
, which exposes a public dependency property, TiltFactor
, of type double. Within Expression Blend I can set the value of this property, however, the option to add a "Data Binding ..." is grayed out:
I have also noticed that Behaviors extend DependencyObject
, therefore they do not have a DataContext
and therefore cannot inherit the DataContext
of the element to which they are attached. This feels like a real weakness to me!
So, the bottom-line is, if I cannot set a binding to my behaviors dependency property in Blend, and it does not inherit a DataContext
, why bother using dependency properties at all? I could just use CLR properties instead.
Blend behaviors would be almost useless unless they supported binding! I recreated your tilt behavior and it supports binding in Blend 4 with no problems so I don't know exactly where you went wrong. Perhaps you can reproduce my simple example and then infer what's wrong with your setup.
Here's the (non-functional) tilt behavior with dependency property:
public class TiltBehavior : Behavior<FrameworkElement>
{
public double TiltFactor
{
get { return (double)GetValue(TiltFactorProperty); }
set { SetValue(TiltFactorProperty, value); }
}
public static readonly DependencyProperty TiltFactorProperty =
DependencyProperty.Register("TiltFactor", typeof(double), typeof(TiltBehavior), new UIPropertyMetadata(0.0));
}
Then just create a new window and drop the behavior onto the grid and Blend creates this:
<Grid>
<i:Interaction.Behaviors>
<local:TiltBehavior/>
</i:Interaction.Behaviors>
</Grid>
and the Blend "Data Binding..." option is available in the properties tab.
I tested this with both WPF and Silverlight projects. The built-in behaviors, triggers and actions all support binding by virtue of using being dependency properties and all the Blend samples use binding heavily and so this has to work.
In fact you can just drop a built-in behavior like FluidMoveBehavior
onto your grid and check that Duration
, which is a dependency property, supports binding. If that doesn't work, I have no idea what's going on!
Let's consider then how binding works for these strange beasts called behaviors.
As WPF or Silverlight programmers we are very familiar with binding for things like FrameworkElement
. It has a property called DataContext
that we can manipulate to control the default binding source and that property is inherited by nested elements when we don't override it.
But behaviors (and triggers and actions) are not of type FrameworkElement
. They are ultimately derived from DependencyObject
, as we might expect. But while we can using binding on any class derived from DependencyObject
, our familiar DataContext
is missing at this low-level and so the binding has to supply the source. That's not very convenient.
So behaviors are derived (on WPF anyway) from Animatable
and Animatable
is derived from Freezable
. The Freezable
class is where the simplicity of dependency objects intersects with the complexity of framework elements. The Freezable
class is also the base class for more familiar things like brushes and image sources. These classes don't need the full complexity of a framework element, but they want to participate, in a limited way with the elements that they are associated with.
Through a complicated magical process, Freezable
instances acquire an inheritance context: the framework element they are most closely associated with, and when a default binding is used (one without a source), the Freezable
uses the DataContext
of it's associated element instead.
In fact as you learn about behaviors the AssociatedObject
is a central concept; for a behavior it is the thing that the behavior is attached to. But the important point is that all Freezable
objects can use the DataContext
of their AssociatedObject
by proxy.
All this magic is what Josh Smith calls the:
And so all this leads up to saying that due to the Hillberg Freezable Trick, Blend behaviors support binding using the data context of their associated element as the default source. As a result, bindings for behaviors seem to "just work" without any effort on our part. Behaviors are a thousand times more useful because of this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With