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:
Then just create a new window and drop the behavior onto the grid and Blend creates this:
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 thatDuration
, 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 calledDataContext
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 fromDependencyObject
, as we might expect. But while we can using binding on any class derived fromDependencyObject
, our familiarDataContext
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
andAnimatable
is derived fromFreezable
. TheFreezable
class is where the simplicity of dependency objects intersects with the complexity of framework elements. TheFreezable
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), theFreezable
uses theDataContext
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 allFreezable
objects can use theDataContext
of theirAssociatedObject
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.
Edit: dain is correct you can still bind to the DataContext which is created artificially, how often have you seen people bind to a
SolidColorBrush.Color
? It also works even though SolidColorBrush inherits from DependencyObject and hence has no DataContext.See this blog post on the inheritance context.
The thing is that since the behaviours are attached, they do not appear in the logical tree and hence would not inherit a DataContext anyway.