ActionMessage on Behaviors?

Jan 25, 2011 at 11:57 AM

I am becoming a big big BIG fan of using System.Windows.Interactivity.Behaviors.  I just tried using Message.Attach on a behavior, and it appears that this cannot happen because ActionMessage has a type constraint of FrameworkElement.

I'm wondering if we can change this type constraint to DependencyObject to allow behaviors to consume the ActionMessage goodness?  It would involve creating an adapter interface like such:

public interface IFrameworkElementAdapter
	FrameworkElement FrameworkElement { get;  }

And then creating a convenience property within ActionMessage:

FrameworkElement TargetElement
    	var frameworkElement = AssociatedObject as FrameworkElement;
    	if ( frameworkElement != null )
    		return frameworkElement;

    	var result = AssociatedObject as IFrameworkElementAdapter;
		if ( result != null )
			return result.FrameworkElement;
    	return null;

And then updating all references to AssociatedObject to TargetElement.


Jan 25, 2011 at 12:16 PM

Blah... Naturally, once I tried this it didn't work as expected.  I guess the better question is: is there any guidance/best practice on how to make Message.Attach work with behaviors?

Jan 25, 2011 at 12:41 PM

ActionMessage is designed to work with Triggers. You only need to implement a custom TriggerBase.

Jan 30, 2011 at 9:55 PM

Hm.  In this case, I still want to use an EventTrigger to trigger the action.  However, if I understand it correctly, ActionMessage can't be added to a Behavior's Triggers.Actions collection because Behavior doesn't derive from FrameworkElement.  When I call trigger.Actiions.Add( new ActionMessage() ), I get the following exception:

Cannot attach type "ActionMessage" to type "<BehaviorType>". Instances of type "ActionMessage" can only be attached to objects of type "FrameworkElement".

If I create a custom TriggerBase, I will run into the same problem, correct?  It's entirely possible I don't understand this correctly.

Jan 30, 2011 at 10:39 PM

I don't understand why you would want to use a Behavior. It seams you want an ActionMessage to send, so the only other part is the trigger? Am I missing some important use case?

Jan 31, 2011 at 2:34 PM

I want to create an event on the Behavior and then bind the ActionMessage to that event.  The event trigger works just fine, but the ActionMessage can't be used within the trigger because it has a type constraint of FrameworkElement (Behaviors derive from DependencyObject).

Jan 31, 2011 at 10:42 PM

I think I get what Michael is saying.

Michael, I would first ask what you're attaching to in XAML that has an event but is not derived from FrameworkElement? To do what you want ActionMessage would have be refactored (or maybe supply your own) so that it constrains against a DependencyObject if the attached object is a framework element it would need code to correctly attach things like availability effects. Also binding relays don't work Windows Phone 7 (don't know if Micro uses binding relays like nRoute in Phone 7) when attached to DependencyObjects as opposed to FrameworkElements, last I checked Phone 7 had the same limitation as Silverlight 3 when it comes to binding to non FrameworkElement targets.

Feb 1, 2011 at 3:09 PM

I'm trying to attach to a Behavior in Xaml.  Something like this:

<Interaction:DataFormCompensations Micro:Message.Attach="[Event Submitted] = [Action SendChangesToServer]" />

When Attach is parsed and added to the DataFormCompensations instance (which has an event "Submitted"), the exception noted above is thrown.

I've been able to work around this issue twice now with some cleverness.  I'm just getting the sense that in the future it would be nice to be able to attach to behaviors without so much workaround. :)

Feb 1, 2011 at 3:18 PM

That's not going to be a supported use case because that's not the way Behaviors/Triggers were designed to be used. You should so something like this:



      <ActionMessage ... />



Feb 1, 2011 at 3:36 PM


<Interactivity:EventTrigger SourceName="Compensations" EventName="Submitted">
<Micro:ActionMessage MethodName="Submit" />
<Interaction:DataFormCompensations x:Name="Compensations" />