Pulsy Button

After much umming and ahhing, and developing several versions of BrokeyButton I have the first cut of the PulsyButton.

What is PulsyButton? Well, it’s a button – that pulses. By pulsing I mean that it ‘pulses’ between the Background colour and a ‘PulseColour’ (that you set!).

Pulsy Button

Easy usage:
<PulsyButton Content="Hello" BackgroundColor="LightGray" PulseColor="Red" IsPulsing="True"/>

Obviously if IsPulsing is set to false then the button won’t pulse.
As it’s just based off the ‘Button’ base class, you can literally insert it wherever you have a Button, and all your styles etc will work fine.

I have plans to add more properties, and will over time:
* PulseTime — A TimeSpan for the pulse.
* PauseTime — A TimeSpan to pause the pulse for, i.e. pulse-paaaaauuuuusssseeeee-pulse etc

Also plans to fix some problems:
* Use StoryBoard and set the Background property directly
* Get rid of BackgroundColor property, so only Background is needed

Erm, can’t think of others at the moment.


Bit more detail -> What have I done?

Well, I had a lot of trouble getting a StoryBoard to work programmatically, I don’t know why, and I will perservere. But in the mean time, I’ve resorted to just a simple ColorAnimation.

How have I used a ColorAnimation with a Background brush?

Well, first I created a DependencyProperty:

public static readonly DependencyProperty BackgroundColorProperty
= DependencyProperty.Register( "BackgroundColor", typeof( Color ), typeof( PulsyButton ),
new UIPropertyMetadata( BackgroundColorChanged ) );

private static void BackgroundColorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
PulsyButton pb = (PulsyButton) d;
pb.Background = new SolidColorBrush( (Color) e.NewValue );
}

This was my ahem workaround to the setting of the Background property directly, as the ColorAnimation will only animate Color properties (i.e. target the SolidColorBrush.Color property for the brush). By the by, it was the targeting of that property that caused me much hassle.

Anyhews, once we’re there, we should also have a PulseColor property (yes I know colour should have a ‘u’ in it, but I’ve gone all americanized :))

public static readonly DependencyProperty PulseColorProperty
= DependencyProperty.Register( "PulseColor", typeof( Color ), typeof( PulsyButton ),
new UIPropertyMetadata( PulseColorChanged ) );

public Color PulseColor { get { return (Color) GetValue( PulseColorProperty ); } set { SetValue( PulseColorProperty, value ); } }

private static void PulseColorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
PulsyButton pb = (PulsyButton) d;
pb._pulseAnimation.To = (Color) e.NewValue;
}

Here I’ve included the PulseColor property, rest assured there is a BackgroundColor property as well. So, now we have the two colours to animate between, Background -> Pulse -> Background… We just need to create the animation.

private readonly ColorAnimation _pulseAnimation = new ColorAnimation();

There’s no need to recreate it, so it’s a readonly member. But when do I set this bad boy up? Not the constructor – nooooo, the colour properties won’t have been set up at that point, so I’ve gone for a ‘Loaded’ event consumer.

public PulsyButton()
{
Loaded += PulsyButton_Loaded;
}

private void PulsyButton_Loaded( object sender, RoutedEventArgs e )
{
_pulseAnimation.From = BackgroundColor;
_pulseAnimation.To = PulseColor;
_pulseAnimation.Duration = new Duration( TimeSpan.FromSeconds( 1 ) );
_pulseAnimation.AutoReverse = true;
_pulseAnimation.RepeatBehavior = RepeatBehavior.Forever;


this.BeginAnimation( BackgroundColorProperty, _pulseAnimation );
}

The animation will now begin, and the pulsy fun is nearly there!
But wait… what about turning pulse on/off?

All that is done in the IsPulsingChanged property:

private static void IsPulsingChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
bool isPulsing = (bool) e.NewValue;
PulsyButton pb = (PulsyButton) d;
if( !isPulsing )
{
pb._pulseAnimation.RepeatBehavior = new RepeatBehavior( 0 );
pb.BeginAnimation( BackgroundColorProperty, pb._pulseAnimation );
}
else
{
pb._pulseAnimation.RepeatBehavior = RepeatBehavior.Forever;
pb.BeginAnimation( BackgroundColorProperty, pb._pulseAnimation );
}
}

Now, I’m not 100% sure this is the correct way to do this, in fact I’m certain it’s not. However, it does work, which at the moment is what matters.

So there you have it, a button that pulses.

——————=====================———————–

Can’t attach the code to the post, so gonna have to past it here, sorry!!

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

public class PulsyButton : Button
{
private readonly ColorAnimation _pulseAnimation = new ColorAnimation();

public readonly DependencyProperty IsPulsingProperty
= DependencyProperty.Register( “IsPulsing”, typeof( bool ), typeof( PulsyButton ),
new UIPropertyMetadata( IsPulsingChanged ) );

public bool IsPulsing
{
get { return (bool) GetValue( IsPulsingProperty ); }
set { SetValue( IsPulsingProperty, value ); }
}

private static void IsPulsingChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
bool isPulsing = (bool) e.NewValue;
PulsyButton pb = (PulsyButton) d;
if( !isPulsing )
{
pb._pulseAnimation.RepeatBehavior = new RepeatBehavior( 0 );
pb.BeginAnimation( BackgroundColorProperty, pb._pulseAnimation );
}
else
{
pb._pulseAnimation.RepeatBehavior = RepeatBehavior.Forever;
pb.BeginAnimation( BackgroundColorProperty, pb._pulseAnimation );
}
}

public static readonly DependencyProperty PulseColorProperty
= DependencyProperty.Register( “PulseColor”, typeof( Color ), typeof( PulsyButton ),
new UIPropertyMetadata( PulseColorChanged ) );

public Color PulseColor { get { return (Color) GetValue( PulseColorProperty ); } set { SetValue( PulseColorProperty, value ); } }

private static void PulseColorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
PulsyButton pb = (PulsyButton) d;
pb._pulseAnimation.To = (Color) e.NewValue;
}

public Color BackgroundColor
{
get { return (Color) GetValue( BackgroundColorProperty ); }
set { SetValue( BackgroundColorProperty, value ); }
}

public static readonly DependencyProperty BackgroundColorProperty
= DependencyProperty.Register( “BackgroundColor”, typeof ( Color ), typeof ( PulsyButton ),
new UIPropertyMetadata( BackgroundColorChanged ) );

private static void BackgroundColorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
PulsyButton pb = (PulsyButton) d;
pb.Background = new SolidColorBrush( (Color) e.NewValue );
}

public PulsyButton()
{
Loaded += PulsyButton_Loaded;
}

private void PulsyButton_Loaded( object sender, RoutedEventArgs e )
{
_pulseAnimation.From = BackgroundColor;
_pulseAnimation.To = PulseColor;
_pulseAnimation.Duration = new Duration( TimeSpan.FromSeconds( 1 ) );
_pulseAnimation.AutoReverse = true;
_pulseAnimation.RepeatBehavior = RepeatBehavior.Forever;

this.BeginAnimation( BackgroundColorProperty, _pulseAnimation );
}
}

Leave a Reply