In a previous post about attached properties, we saw how we can change the background of an UI element by attaching an external property to that element. In this post, we’re going to do the same, but this time using the evolved version: Blend Behaviors.

Full example

This is the full code example to show an empty window that changes its background on mouse over and then back to original when the mouse is out of the window. There is no C# code (other then the default code behind that’s automatically generated for each view).

<Window x:Class="BlendBehaviors.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        Background="{DynamicResource NormalStateBrushKey}">
    <Window.Resources>
        <SolidColorBrush x:Key="NormalStateBrushKey" Color="Blue"/>
        <SolidColorBrush x:Key="MouseOverStateBrushKey" Color="Red"/>
    </Window.Resources>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <ei:ChangePropertyAction
                PropertyName="Background"
                Value="{DynamicResource MouseOverStateBrushKey}"/>
        </i:EventTrigger>

        <i:EventTrigger EventName="MouseLeave">
            <ei:ChangePropertyAction
                PropertyName="Background"
                Value="{DynamicResource NormalStateBrushKey}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Window>

In order to use Blend Behaviors you have to install Blend for Visual Studio SDK for .NET. After that in your xaml file you have to add 2 extra namespaces to have access to the behaviors:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

The available behaviors are listed in the Assets panel: Blend Behaviors

The easiest way to add the behavior is to just drag and drop it over the element that you want to apply it to and then to configure it using the Properties panel:

Drag and Drop Behavior

Compose Behaviors

The nice thing about Blend Behaviors is that you can compose them. There are 2 parts to a behavior: triggers and actions. Here are some of the available triggers:

Trigger Types

Let’s change the functionality of the app so when you press F5 then the background will change. For this we just need to change the trigger to a KeyTrigger and keep the same action as before:

<i:Interaction.Triggers>
    <ei:KeyTrigger Key="F5">
        <ei:ChangePropertyAction
            PropertyName="Background"
            Value="{DynamicResource MouseOverStateBrushKey}"/>
    </ei:KeyTrigger>
</i:Interaction.Triggers>

We can even change the background using a TimerTrigger after 3000 milliseconds:

<i:Interaction.Triggers>
    <ei:TimerTrigger MillisecondsPerTick="3000">
        <ei:ChangePropertyAction
            PropertyName="Background"
            Value="{DynamicResource MouseOverStateBrushKey}"/>
    </ei:TimerTrigger>
</i:Interaction.Triggers>

As you can see, these behaviors are quite flexible! Besides changing the triggers we can also change the actions. In order to keep this blog post as simple as possible without having to create new view models, commands and files I’ll use a CallMethodAction on the Window:

<i:Interaction.Triggers>
    <ei:TimerTrigger MillisecondsPerTick="3000">
        <ei:CallMethodAction
            TargetObject="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}"
            MethodName="Close"/>
    </ei:TimerTrigger>
</i:Interaction.Triggers>

All this does is that after 3 seconds the window will close - not a very useful functionality, but it perfectly displays Blend Behavior flexibility.

Behaviors from scratch

Considering that you can compose behaviors by choosing from the available triggers and actions (which by the way also include the InvokeCommandAction) you should rarely need to create your own behavior.

However, if you do need to create your own behavior here’s an example on how to do it:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;

namespace BlendBehaviors
{
    public class BackgroundBrushOnMouseOverBehavior : Behavior<Control>
    {
        private Brush originalBackgroundBrush;

        public Brush MouseOverBackgroundBrush
        {
            get { return (Brush)GetValue(MouseOverBackgroundBrushProperty); }
            set { SetValue(MouseOverBackgroundBrushProperty, value); }
        }

        public static readonly DependencyProperty MouseOverBackgroundBrushProperty =
            DependencyProperty.Register("MouseOverBackgroundBrush",
                typeof(Brush),
                typeof(BackgroundBrushOnMouseOverBehavior),
                new PropertyMetadata(Brushes.White));

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.Loaded += OnLoaded;
            AssociatedObject.Unloaded += OnUnloaded;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.Loaded -= OnLoaded;
            AssociatedObject.Unloaded -= OnUnloaded;
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            AssociatedObject.MouseEnter += OnMouseEnter;
            AssociatedObject.MouseLeave += OnMouseLeave;

            originalBackgroundBrush = AssociatedObject.Background;
        }

        private void OnUnloaded(object sender, RoutedEventArgs e)
        {
            AssociatedObject.MouseEnter -= OnMouseEnter;
            AssociatedObject.MouseLeave -= OnMouseLeave;
        }

        private void OnMouseEnter(object sender, MouseEventArgs e)
        {
            AssociatedObject.Background = MouseOverBackgroundBrush;
        }

        private void OnMouseLeave(object sender, MouseEventArgs e)
        {
            AssociatedObject.Background = originalBackgroundBrush;
        }
    }
}

And here’s how to use it in xaml:

<i:Interaction.Behaviors>
    <local:BackgroundBrushOnMouseOverBehavior 
        MouseOverBackgroundBrush="{DynamicResource MouseOverStateBrushKey}"/>
</i:Interaction.Behaviors>

Normally you would just subscribe to the MouseEnter and MouseLeave events in the OnAttached method (and unsubscribe in the OnDetaching method), but that way the unsubscribe won’t happen until someone specifically calls Detach or removes the behavior from the parent collection. A better way to do it is to subscribe and unsubscribe to the MouseEnter and MouseLeave events in the Loaded and Unloaded events.

Less code, even more flexibility

A better implementation compared to the previous approach is to create a TriggerAction which will then allow us to hook up to existing triggers (like the EventTrigger with an event declared in xaml):

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Media;

namespace BlendBehaviors
{
    [Description("Changes background on the target control")]
    public class ChangeBackgroundAction : TriggerAction<Control>
    {
        [Category("ChangeBackgroundAction")]
        [Description("Sets the background this Action will change to")]
        public Brush Background
        {
            get { return (Brush)GetValue(BackgroundProperty); }
            set { SetValue(BackgroundProperty, value); }
        }

        public static readonly DependencyProperty BackgroundProperty =
            DependencyProperty.Register("Background",
                typeof(Brush),
                typeof(ChangeBackgroundAction),
                new PropertyMetadata(Brushes.White));

        protected override void Invoke(object parameter)
        {
            AssociatedObject.Background = Background;
        }
    }
}

And the corresponding xaml:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseEnter">
        <local:ChangeBackgroundAction 
            Background="{DynamicResource MouseOverStateBrushKey}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

You may have observed that in the previous C# code I have added a few attributes:

[Category("ChangeBackgroundAction")]
[Description("Sets the background this Action will change to")]

These are so if someone else uses the behaviors/actions you’ve written (usually the designer if he also does the UI in Microsoft Blend) then they have an easier time understanding how to use them.

Here’s how the tooltips look like in the Assets panel:

Behaviors in Assets panel tooltip

and in the properties panel:

Properties panel tooltip and category

Hopefully this post cleared up what these behaviors are and how to use them. As you saw, these are quite simple and flexible. It’s very easy to use them in Microsoft Blend: you just have to drag and drop behaviors on top of the controls you want to affect and then configure a few things in the Properties panel.