Today I am going to explore Silverlight three behaviors a little more. In this post I am going to look at different events that can trigger an action in a behavior. Essentially, we can specify any event on a target element to invoke a behavior.
Again, we are going to use TargetedTriggerAction base class. This time however we are going to enable this behavior to be able to be used on a larger suite of targets. We are going to use UIElement as the target type: TargetedTriggerAction<UIElement>. We are only going to override one method – InvokeAction. Here is what the class looks like:
public class MakeLargerSmallerAction : TargetedTriggerAction<UIElement>
{
protected override void Invoke(object parameter)
{
StoryBoardHelper.PlayControlAnimation(Target, Percent);
}
Here are a couple of things I need to explain.
- This behavior is going to perform one function – change dimensions (increase or decrease the size) of the target control base on an event. We are going to add a property that would allow our behavior to specify the factor by which the target’s size needs to increase or decrease.
- We are going to use animations to perform this function. We will build animations in code.
- We will invoke animations based on event specified in XAML.
Here is full source code for behavior class:
using System;
using System.Windows.Interactivity;
using System.Windows;
namespace Behaviors
{
public class MakeLargerSmallerAction : TargetedTriggerAction<UIElement>
{
protected override void Invoke(object parameter)
{
StoryBoardHelper.PlayControlAnimation(Target, Percent);
}
public double Percent
{
get { return (double)GetValue(PercentProperty); }
set { SetValue(PercentProperty, value); }
}
public static readonly DependencyProperty PercentProperty =
DependencyProperty.Register("Percent", typeof(double), typeof(MakeLargerSmallerAction), new PropertyMetadata((double)1));
}
}
Here is source code for animation controller:
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace Behaviors
{
public static class StoryBoardHelper
{
public static void PlayControlAnimation(UIElement controlToAnimate, double factor)
{
Storyboard story = new Storyboard();
//stretch horizontally
DoubleAnimationUsingKeyFrames scaleXAnimation = new DoubleAnimationUsingKeyFrames();
scaleXAnimation.BeginTime = TimeSpan.FromMilliseconds(0);
scaleXAnimation.KeyFrames.Add(CreateFrame(factor, 100));
Storyboard.SetTarget(scaleXAnimation, controlToAnimate);
Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
story.Children.Add(scaleXAnimation);
//stretch vertically
DoubleAnimationUsingKeyFrames scaleYAnimation = new DoubleAnimationUsingKeyFrames();
scaleYAnimation.BeginTime = TimeSpan.FromMilliseconds(0);
scaleYAnimation.KeyFrames.Add(CreateFrame(factor, 100));
Storyboard.SetTarget(scaleYAnimation, controlToAnimate);
Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));
story.Children.Add(scaleYAnimation);
if (!(controlToAnimate.RenderTransform is TransformGroup))
{
TransformGroup group = new TransformGroup();
ScaleTransform transform = new ScaleTransform();
transform.ScaleX = 1;
transform.ScaleY = 1;
group.Children.Add(transform);
controlToAnimate.RenderTransformOrigin = new Point(0.5, 0.5);
controlToAnimate.RenderTransform = group;
}
story.Begin();
}
private static SplineDoubleKeyFrame CreateFrame(double value, double duration)
{
SplineDoubleKeyFrame frame = new SplineDoubleKeyFrame();
frame.Value = value;
frame.KeyTime = TimeSpan.FromMilliseconds(duration);
return frame;
}
}
}
Here is how we are setting up behaviors in XAML:
<TextBox x:Name="FirstBox" TextWrapping="Wrap" Margin="20,0,0,7" d:LayoutOverrides="Height">
<i:Interaction.Triggers>
<i:EventTrigger>
<Behaviors:SelectOnFocusAction/>
</i:EventTrigger>
<i:EventTrigger EventName="GotFocus">
<Behaviors:MakeLargerSmallerAction Percent="1.2"/>
</i:EventTrigger>
<i:EventTrigger EventName="LostFocus">
<Behaviors:MakeLargerSmallerAction Percent="1"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
In the XAML above we are setting up three different behaviors. First one I covered in previous post. The second trigger increases the size of the control by factor of 1.2 – 20 %. This action is executed when GotFocus event fires. The last trigger changes the control’s size back to original size.
You can download full sample project here.