Welcome to EMC Consulting Blogs Sign in | Join | Help

Richard Griffin's Blog

Behaviors, Actions and View Models in Silverlight

Behaviors are new to Silverlight 3 and WPF.

The main reason we now have Behaviors in Silverlight was due to the lack of support in Silverlight of triggers. Triggers in WPF are incredibly useful as they provide the ability to change the look and feel  of UI Elements dynamically based on the state of the application directly in the Xaml. In fact they are so useful we have 2 types Data Triggers and UI Triggers. Data Triggers can be used to respond to changes in the data that the UI Elements are bound to. UI Triggers can be used to respond to UI level events.

My current view of Behaviors is that of Triggers on steroids, in that they are an evolution from what we know in WPF and matured into a more componentised mechanism allowing designers the ability to drag and drop behaviors onto elements with out the need to create them manually. There are some standard behaviors that have been posted around on various blogs which i strongly suggest taking a look at and check out Pete Blois’s session at Mix09. Now, designers will still need to chat to a developer in order to create custom behaviors, however this is worth the investment as there is an opportunity to create a behaviors control library that can be used by your applications. Not only can we easily provide consistent experiences within our Silverlight applications but also in WPF and Surface applications, libraries will need to be recompiled to work with the specified deployment targets.

So what are behaviors and how can they be used to help out when building applications ??

Behaviors in general are best thought of in a metaphorical view, lets clear this up with an example. When going to a friends party we generally behave differently in comparison to when we go to dinner party at our CEO’s house. When we drive a car our behavior is to fasten the seat belt. Therefore, behaviors can be thought of as something that is intrinsic to us in that its in our nature to behave in a certain way under particular environments, when our environment changes this will also have an affect on our behavior. If we take this analogy and apply it to a UI Element in our application it makes thinking about what should be classified as a behavior. For example, if we want a UI Element that can be dragged around the screen we would provide the UI Element with the drag behavior, if we want to provide deep zoom capabilities to our application we would provide the Multi Scale Image with the deep zoom behavior.

What is slightly confusing at first is that we have 2 types of behaviors, behaviors and actions. When sub classing a behavior its my current belief that we are suggesting that this behavior is a UI behavior and an Action is performed in response to a state change. To prove this statement I have a couple of simple implementations that I wrote to test out this theory. At this stage you will need to download the code in order to follow the descriptions below.

Creating the behavior

First I started with the approach we have been using for a while, create your animation in Xaml using Blend then write some code behind to trigger the animation, if we were in WPF then we could use a Trigger in Xaml to do this but for the examples below I am targeting Silverlight. Fairly straight forwards apart from the fact we had to write some code behind, which is not great for the designer. I created 2 animations, Fade In and a Fade Out animation that can be applied to any Framework element. Now that we have these its time to create a behavior. The first task here is to ensure you have the right assembly referenced in your project Microsoft.Expression.Interactivity that provides the base classes that your behavior and actions will subclass. Once you have this in your project create a new class and derive it from Behavior<T>.

Expression_Blend_Behavior0In my example I am using Behavior<FrameworkElement> and due to this I have added a local field which is also of the same type so that there is a reference wired up to the UI Element that we are attaching the behavior too. The behavior requires values to be setup so that the element in order to tweak the behavior to match our requirements this is done using dependency properties. In order to expose the properties in Blend add the Category attribute to you properties. The final step is to override the OnAttached and OnDetached methods. In my example I only override the OnAttached method and it in here where the Storyboard animations to FadeIn and Out the Framework Element live. Nothing to difficult about that. Now that we have created the behavior we need to attach it to the Framework Expression_Blend_Behavior1Element we can do this in Blend very easily.

Expression_Blend_BehaviorOpen up the project in Blend and open up the asset library and there is a new tab called behaviors where there is a listing of available Behaviors and Action can be used in the project. To apply the FadeBehavior in our case to the image element, select the correct behavior and drag this onto the image element, this will wire up the behavior to the image. To change the granularity of the behavior Blend provides a UI in order to change the values which we provided.  

 

 

Creating the action

Expression_Blend_Action In essence the process for building the action is identical to creating a behavior. The only change required is an obvious one which is the base class needs changing to TargetedTriggerAction<T>. Sweet… There are also a couple of other subtle changes. In the behavior I used a local variable to hold an instance of the element which the behavior was being applied to, this was done using a rather helpful method in the base class called AssociatedObject. The method is not provide by this particular Trigger class, an additional Dependency Property has been added in order for the action to know what it has been applied to. The other change is that although there are OnDetached and OnAttached method overrides in this example I chose to override the Invoke method. Expression_Blend_Action2

To apply the action follow the same steps but select the required action this time round and associate the action with a button. Here we want to trigger the Fade Action in response to a users interaction, in this case clicking on a button. Here is where the metaphoric use of behaviors and actions differ, the fading of the image in this case is required when a user interacts with a UI Element on screen, in the behavior scenario we wanted the fading to be intrinsic to the control.

 

Creating a View Model action

Expression_Blend_Action3 In the previous examples the we used the behavior pattern specifically in the Xaml. I wanted to try out what the code would look like when data binding a custom action to a property on the View Model. The idea came from previous projects where I would require a loading animation to fire up while the View Model went and got the required data from the data service. Once the data has started to come back the animation would fade out and the control displayed with data ready for the user. These animations were controlled using a Dependency Property declared in the User Control and then data bound to a property on the View Model, each View Model implements INotifyPropertyChanged. This seems like a prime candidate for a reusable action that the developer can write once and then allow the designer to apply in Blend. This method reminds me of those collections of extension methods or type converters that we build during the implementation of a UI, I am sure that the same approach can be used with behaviors. For this example I created a Visibility behavior which was then data bound to a property on the View Model called CurrentVisibility. Unfortunately this is where I found a couple of problems, I wanted to data bind the behaviors in the Xaml.

 

<Image x:Name="image_Copy1"
               Source="01.jpg"
               Stretch="Uniform"
               Height="Auto"
               Width="Auto"
               d:LayoutOverrides="Width, Height"
               Grid.Column="2">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Loaded">
                    <SilverlightApp_Behaviours:VisibilityBehavior CurrentVisibilityBehavior="{Binding Path=CurrentVisibility}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Image>

This was giving me runtime errors so i tried to do the data binding from the code behind like so.

this.AssociatedObject.SetBinding(UIElement.VisibilityProperty, new Binding("CurrentVisibility") { Mode = BindingMode.TwoWay });

But this did not seem to work out either. In the end i wired the behavior to the View Model’s property changed event handler and sniffed out the CurrentVisibility property, which is not all too nice. The data context of the behavior is right so there must be a reason for the binding not to work which I am yet to discover. However, the ability for the developer to create behaviors that can extend the View Model in such away that the designer now has the ability to apply these using Blend is a very powerful mechanism.

Behaviors are a powerful addition to Silverlight. What I have found to be most poignant is that I no longer have a reliance on Commands and the command binding pattern that I have been using in WPF and Silverlight. In the previous sample I would have used Commands to force separation between View and View Model in order for me to write code in the View Model which responded to a user interaction that would have required doing some processing on a data set. Now with behaviors data binding can be used. Personally I like Commands and they have served me extremely well in the past, however I do like the behavior metaphor as this makes the problem easier to visualise when talking about behaviors of the visual elements rather than using the Command terminology.

Published Monday, March 30, 2009 11:38 AM by Anonymous
New Comments to this post are disabled
Powered by Community Server (Personal Edition), by Telligent Systems