Image transition animation on ribbon button - wpf

How can I create a WPF ribbon button switching between two images, with an animated "wipe" transition between images? I can't place both images within a a grid within the button and animate the opacity of each image in turn (as suggested here) because I can't set the content of the ribbon directly, only the LargeImageSource/SmallImageSource and Label properties.
Update
I tried BorisB.'s suggestion together with the animation from the link above, but there is now no image displayed in the ribbon button. Removing the animation, opacity mask and multiple images, and leaving the following code also doesn't show the image at all.
<RibbonToggleButton Label="Dashboard" Name="btnDashboard" IsChecked="True">
<RibbonToggleButton.LargeImageSource>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup>
<ImageDrawing ImageSource="/Icons/Dashboard.png" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</RibbonToggleButton.LargeImageSource>
</RibbonToggleButton>

You can use a DrawingImage as an ImageSource. Then you can assign a DrawingGroup as a DrawingImage.Drawing. That drawing group can contain two ImageDrawings wrapped in their own DrawingGroups, so you could apply the approach from your link:
<Grid>
<Ribbon>
<RibbonTab x:Name="HomeTab" Header="Home">
<RibbonGroup x:Name="Group1" Header="Group1">
<RibbonButton x:Name="Button1" Label="Button1">
<RibbonButton.LargeImageSource>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup>
<DrawingGroup>
<ImageDrawing Rect="0, 0, 32, 32" ImageSource=ImageOne.png"/>
</DrawingGroup>
<DrawingGroup>
<ImageDrawing Rect="0, 0, 32, 32" ImageSource="ImageTwo.png"/>
<DrawingGroup.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="Black" x:Name="BlackStop"/>
<GradientStop Offset="0" Color="Transparent" x:Name="TransparentStop"/>
</LinearGradientBrush>
</DrawingGroup.OpacityMask>
</DrawingGroup>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</RibbonButton.LargeImageSource>
</RibbonButton>
</RibbonGroup>
</RibbonTab>
</Ribbon>
</Grid>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TransparentStop"
Storyboard.TargetProperty="Offset" By="1" Duration="0:0:2" />
<DoubleAnimation Storyboard.TargetName="BlackStop"
Storyboard.TargetProperty="Offset" By="1" Duration="0:0:2"
BeginTime="0:0:0.05" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Window.Triggers>
The wrapping DrawingGroups are used so you can use OpacityMask, which is essential for the effect.

Related

Animate an Object Along a Path

I strted to play around with shapes in wpf, I need the following: I have an image and I draw some shape, I want the the image would walk on the lines of this shape.
I mean like:
For example with the shape:
<Path Stroke="Black" StrokeThickness="5" Fill="Goldenrod">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="100,50" IsClosed="True">
<LineSegment Point="140,60"/>
<LineSegment Point="150,100"/>
<LineSegment Point="125,120"/>
<LineSegment Point="90,110"/>
<LineSegment Point="80,80"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
And here is the moving image:
<UserControl ...
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" ..>
<UserControl.Resources>
<PathGeometry x:Key="AnimationPath"
Figures="M 10,100 C 40,0 300,0 300,300 0,300 285,200 300,300 "
PresentationOptions:Freeze="True" />
</UserControl.Resources>
<Image
Source="/Resources/Myimage.png"
Width="200" >
<Image.RenderTransform>
<TranslateTransform x:Name="AnimatedTranslateTransform" />
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<!-- Animates the rectangle horizotally along the path. -->
<DoubleAnimationUsingPath
Storyboard.TargetName="AnimatedTranslateTransform"
Storyboard.TargetProperty="X"
PathGeometry="{StaticResource AnimationPath}"
Source="X"
Duration="0:0:5"
AutoReverse="True"
/>
<!-- Animates the rectangle vertically along the path. -->
<DoubleAnimationUsingPath
Storyboard.TargetName="AnimatedTranslateTransform"
Storyboard.TargetProperty="Y"
PathGeometry="{StaticResource AnimationPath}"
Source="Y"
Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
Related links: link1, link2
I have tried like:
Figures="M 10,100 C 100,50 140,60 150,100 125,120 90,110 80,80 "
i.e start at point 100,50 --> 140,60 and so on...
but it doesnt go exactly on this path
Your sketch seems to indicate that you want to animate kind of a red arrow along the path, including a rotation to the tangent angle of the current path segment.
You could achieve this by animating the Matrix property of a MatrixTransform with a MatrixAnimationUsingPath. The example below uses an additional TranslateTransform to center the image. As there is a DrawingImage in the Source property of the Image element, you may as well use another Path instead of an Image.
<Window.Resources>
<PathGeometry x:Key="AnimationPath"
Figures="M100,50 L140,60 150,100 125,120 90,110 80,80Z"/>
</Window.Resources>
<Canvas>
<Path Stroke="Black" StrokeThickness="5" Fill="Goldenrod"
Data="{StaticResource AnimationPath}"/>
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Geometry="M0,0 L10,8 0,16">
<GeometryDrawing.Pen>
<Pen Thickness="3" Brush="Red"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
<Image.RenderTransform>
<TransformGroup>
<TranslateTransform X="-5" Y="-8"/>
<MatrixTransform x:Name="AnimatedTransform"/>
</TransformGroup>
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<MatrixAnimationUsingPath
Storyboard.TargetName="AnimatedTransform"
Storyboard.TargetProperty="Matrix"
Duration="0:0:5"
DoesRotateWithTangent="True"
PathGeometry="{StaticResource AnimationPath}"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
</Canvas>

Rotating Ellipse Around Center

I'm trying to build a generic loading control. I have the dummy control all set up with the gradient and masking, but I'm finding when I actually run it in a window it appears to rotate slightly off kilter. If you drop the below code into a user control, then drop that control into a window you should see the behavior I'm describing. I defined RenderTransformOrigin, so I'm a little confused as to why it's still not centering the rotation to the middle of the ellipse.
<UserControl x:Class="SpinningGradient.LoadingControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SpinningGradient"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<Grid>
<Ellipse Stretch="Uniform"
RenderTransformOrigin=".5,.5">
<Ellipse.RenderTransform>
<RotateTransform x:Name="noFreeze" />
</Ellipse.RenderTransform>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Ellipse.RenderTransform).(RotateTransform.Angle)"
By="10"
To="360"
Duration="0:0:1"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
<Ellipse.Fill>
<RadialGradientBrush RadiusX="0.5"
RadiusY="0.5">
<RadialGradientBrush.GradientOrigin>
<Point X=".9"
Y=".9" />
</RadialGradientBrush.GradientOrigin>
<RadialGradientBrush.Center>
<Point X="0.5"
Y="0.5" />
</RadialGradientBrush.Center>
<RadialGradientBrush.GradientStops>
<GradientStop Color="Blue"
Offset="1" />
<GradientStop Color="Red"
Offset="-.5" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Ellipse.Fill>
<Ellipse.OpacityMask>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Brush>
<SolidColorBrush Color="Black" />
</GeometryDrawing.Brush>
<GeometryDrawing.Geometry>
<GeometryGroup FillRule="EvenOdd">
<RectangleGeometry Rect="0,0,100,100" />
<EllipseGeometry RadiusX="30"
RadiusY="30"
Center="50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="0"
Brush="Black" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Ellipse.OpacityMask>
</Ellipse>
</Grid>
</UserControl>
The UserControl below creates a very similar or the same visual result with a lot less XAML. The ratio between StrokeThickness and RadiusX/RadiusY determines the relative stroke width.
<UserControl ...>
<Viewbox>
<Path StrokeThickness="1" Stretch="Uniform" RenderTransformOrigin="0.5,0.5">
<Path.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="RenderTransform.Angle"
To="360" Duration="0:0:1" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
<Path.RenderTransform>
<RotateTransform/>
</Path.RenderTransform>
<Path.Data>
<EllipseGeometry RadiusX="2" RadiusY="2"/>
</Path.Data>
<Path.Stroke>
<RadialGradientBrush GradientOrigin="0.9,0.9">
<RadialGradientBrush.GradientStops>
<GradientStop Color="Blue" Offset="1" />
<GradientStop Color="Red" Offset="-0.5" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Path.Stroke>
</Path>
</Viewbox>
</UserControl>
The reason for that is that even though your Ellipse looks like a circle, it is still stretching to the size of its container (or, more precisely, to the size of the LoadingControl). So, unless the said LoadingControl is contained within a perfect square, the Ellipse's actual center point is going to be offset from the center point of the visible circle, either horizontally or vertically. And around that actual center point (rather than the apparent center point) the Ellipse is rotated.
#Clemens already gave you a handful of options to remedy this situation in the comments section, but let me quickly go over them:
Set Width and Height of your Ellipse to the same value - this is limiting since you have to hard-code the size of your control
Bind the Width to the ActualHeight of the Ellipse (or the other way around) - this gives you some extent of dynamic behavior, but things go bad if the target dimension constraint is smaller than the source dimension constraint (e.g. if you bind Width to ActualHeight, things go bad when your control is contained within a rectangle with its width smaller than its height - the Ellipse is clipped)
Put the Ellipse in a square container - or more precisely, within a container that would always arrange it in a square
I strongly recommend the last approach, since it gives you full flexibility in sizing your control. Now I don't think there's a component shipped with WPF that could accomplish this task, but it is fairly simple to devise one of your own, and I guarantee from my experience, that it'll become a useful tool in your toolbox. Here's an example implementation, which is based on a Decorator:
public class SquareDecorator : Decorator
{
protected override Size ArrangeOverride(Size arrangeSize)
{
if (Child != null)
{
var paddingX = 0d;
var paddingY = 0d;
if (arrangeSize.Width > arrangeSize.Height)
paddingX = (arrangeSize.Width - arrangeSize.Height) / 2;
else
paddingY = (arrangeSize.Height - arrangeSize.Width) / 2;
var rect = new Rect
{
Location = new Point(paddingX, paddingY),
Width = arrangeSize.Width - 2 * paddingX,
Height = arrangeSize.Height - 2 * paddingY,
};
Child.Arrange(rect);
}
return arrangeSize;
}
protected override Size MeasureOverride(Size constraint)
{
var desiredSize = new Size();
if (Child != null)
{
Child.Measure(constraint);
var max = Math.Min(constraint.Width, constraint.Height);
var desired = Math.Max(Child.DesiredSize.Width, Child.DesiredSize.Height);
desiredSize.Width = desiredSize.Height = Math.Min(desired, max);
}
return desiredSize;
}
}
Then you only need to slightly modify your control:
<UserControl (...)>
<local:SquareDecorator>
<Ellipse (...) />
</local:SquareDecorator>
</UserControl>

Animate Text Glint On Animated Text

I have a button that loads more data into a datagrid when clicked. To indicate progress, I change the text of the button to change from "More" to "Loading..." where the periods are animated. Next, I wanted to add a "glint" effect so that the text catches your eye. If you've used an iPhone/iPod Touch, I'm thinking of the effect on the "Slide To Unlock" text of the lock screen.
To do so, I shift a middle, lighter gradient stop from left to right. Because the animation continuously loops, I used offsets outside of the valid range to create a delay between the times when the light gradient stop is actually visible.
I got this implemented but I can tell that for some reason, the light gradient is not starting at the left edge of the text. It starts at about the 'a' in the "Loading". I accepted that and it's been in place for a while, but I'm now coming back to it just to try to understand why. It seems like maybe it's using the measure of the original text when calculating the animation, but I thought the animations were supposed to apply to each other when in the same storyboard. Here is my code:
<UserControl.Resources>
<local:EmptyBatchNumConverter x:Key="emptyBatchNumConverter" />
<BeginStoryboard x:Key="bsbLoadingMore" x:Name="bsbLoadingMore">
<Storyboard x:Name="sbLoadingMore">
<StringAnimationUsingKeyFrames Storyboard.TargetName="txtBtnMoreText" Storyboard.TargetProperty="Text" Duration="0:0:2" FillBehavior="Stop" RepeatBehavior="Forever">
<DiscreteStringKeyFrame Value="Loading" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="Loading." KeyTime="0:0:0.5" />
<DiscreteStringKeyFrame Value="Loading.." KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value="Loading..." KeyTime="0:0:1.5" />
</StringAnimationUsingKeyFrames>
<!--Animate the OffSet of the light gradient stop for a "glint" effect. Using -4.5 to 4.5 to delay the visible effect between repeats (and
control the speed relative to the duration). Using an extra .4 seconds to offset the frequency from the text animation. -->
<DoubleAnimation Storyboard.TargetName="gs2" Storyboard.TargetProperty="Offset" From="-4.5" To="4.5" Duration="0:0:2.4" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</UserControl.Resources>
...
<Button Name="btnMore" Grid.Row="1" Style="{StaticResource OasisGridMoreButton}" Click="btnMore_Click" Visibility="Visible" Height="16">
<Button.Content>
<TextBlock Name="txtBtnMoreText" MinWidth="48" Text="More..." /> <!--MinWidth = width of "Loading..."-->
</Button.Content>
<Button.Foreground>
<LinearGradientBrush StartPoint="0.2,0" EndPoint="1,1">
<GradientStop x:Name="gs1" Color="Black" Offset="0"/>
<GradientStop x:Name="gs2" Color="Cyan" Offset="-4.5"/>
<GradientStop x:Name="gs3" Color="Black" Offset="1" />
</LinearGradientBrush>
</Button.Foreground>
</Button>
Here is the problem:
<LinearGradientBrush StartPoint="0.2,0" EndPoint="1,1">
Change it to:
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
Here is the full test app I made (slowed down glint to see it better):
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="WpfApplication4.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<Storyboard x:Key="OnLoaded1"/>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard x:Name="bsbLoadingMore">
<Storyboard x:Name="sbLoadingMore">
<StringAnimationUsingKeyFrames Storyboard.TargetName="txtBtnMoreText" Storyboard.TargetProperty="Text" Duration="0:0:2" FillBehavior="Stop" RepeatBehavior="Forever">
<DiscreteStringKeyFrame Value="Loading" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="Loading." KeyTime="0:0:0.5" />
<DiscreteStringKeyFrame Value="Loading.." KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value="Loading..." KeyTime="0:0:1.5" />
</StringAnimationUsingKeyFrames>
<!--Animate the OffSet of the light gradient stop for a "glint" effect. Using -4.5 to 4.5 to delay the visible effect between repeats (and
control the speed relative to the duration). Using an extra .4 seconds to offset the frequency from the text animation. -->
<DoubleAnimation Storyboard.TargetName="gs2" Storyboard.TargetProperty="Offset" From="-4.5" To="4.5" Duration="0:0:5.4" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Button x:Name="btnMore" Visibility="Visible" Margin="0,213,0,182" d:LayoutOverrides="GridBox">
<Button.Foreground>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop x:Name="gs1" Color="Black" Offset="0"/>
<GradientStop x:Name="gs2" Color="Cyan" Offset="0"/>
<GradientStop x:Name="gs3" Color="Black" Offset="1" />
</LinearGradientBrush>
</Button.Foreground>
<TextBlock x:Name="txtBtnMoreText" MinWidth="48" Text="More..." />
</Button>
</Grid>
For some reason, it is not showing the </Window> at the end...

Button animation on view model property change?

I have the following xaml code. The XAML displays an animation on the button whenever the button is click. I want to start/stop the animation whenever a boolean property in the view model is changed. Any help is appreciated in advance.
<Button Name="button5" Width="100" Margin="10" HorizontalContentAlignment="Left">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="myBorder" Storyboard.TargetProperty="Width" From="0" To="94" Duration="0:0:1" AutoReverse="True" RepeatBehavior="5x" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
<Button.Content>
<Grid Width="94">
<Border HorizontalAlignment="Left" Width="0" Name="myBorder">
<Border.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.115" Color="Black" />
<GradientStop Offset="0.715" Color="Red" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
</Border>
<TextBlock FontSize="14" HorizontalAlignment="Center">Search</TextBlock>
</Grid>
</Button.Content>
</Button>
Also how can i animate the button in such a way that once the border width has reached its max width a reverse animation should occur. I mean i want a wave like effect(using gradient) inside the button. The wave should turn back once it hits the rightmost end of the button. Same should repeat indefinitely. This animation will be controlled using a ViewModel boolean property.

Can I access a named fill gradient in a WPF Datatemplate?

I have a DataTemplate with a number of layered text and graphic objects. One of them is a glow effect that comes from the RadialGradientBrush Fill property of a Rectangle. At first, I named the Rectangle and bound to the Fill property and changed it using a DataTrigger. This worked fine, but I have a number of RadialGradientBrush objects in the Resources section and as you can see below, it is a lot to repeat when all I want to do is change the GradientStops. So I removed the Fill binding and added and named a RadialGradientBrush and although I can bind to the brush from Resources, I can't access it in the DataTrigger. I get the 'Cannot find Trigger target' error.
<Rectangle x:Name="Glow" IsHitTestVisible="False" RadiusX="1.5" RadiusY="1.5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" StrokeThickness="0" Opacity="1.0">
<Rectangle.Fill>
<RadialGradientBrush x:Name="GlowGradient" Center="0.5,0.848" GradientOrigin="0.5,0.818" RadiusX="-1.424" RadiusY="-0.622" GradientStops="{StaticResource DefaultGradient}">
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.848" ScaleX="1" ScaleY="1.8"/>
<SkewTransform AngleX="0" AngleY="0" CenterX="0.5" CenterY="0.848"/>
<RotateTransform Angle="-33.418" CenterX="0.5" CenterY="0.848"/>
<TranslateTransform Y="0.278"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
In the resources, I have several RadialGradientBrush objects like this one.
<RadialGradientBrush x:Key="EscalatedGlow" Center="0.5,0.848" GradientOrigin="0.5,0.818" RadiusX="-1.424" RadiusY="-0.622">
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.848" ScaleX="1" ScaleY="1.8"/>
<SkewTransform AngleX="0" AngleY="0" CenterX="0.5" CenterY="0.848"/>
<RotateTransform Angle="-33.418" CenterX="0.5" CenterY="0.848"/>
<TranslateTransform Y="0.278"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="Aqua" Offset="0.168"/>
<GradientStop Color="#5E1D96FF" Offset="0.474"/>
<GradientStop Color="#1101FFFF" Offset="1"/>
</RadialGradientBrush>
I want to replace them with less code for each colour change, so I created some GradientStopCollection objects in the Resources to replace them with.
<GradientStopCollection x:Key="EscalatedGradient">
<GradientStop Color="Aqua" Offset="0.168"/>
<GradientStop Color="#5E1D96FF" Offset="0.474"/>
<GradientStop Color="#1101FFFF" Offset="1"/>
</GradientStopCollection>
Although I can bind to the Resource gradients, the problem is that I can't access the GlowGradient brush to change its GradientStops property. I could previously access the Glow Rectangle using a DataTrigger with the following.
<DataTrigger Binding="{Binding Path=Status}" Value="Escalated">
<Setter TargetName="Glow" Property="Fill" Value="{StaticResource EscalatedGlow}"/>
</DataTrigger>
When I use the following, I get the 'Cannot find Trigger target' error.
<DataTrigger Binding="{Binding Path=Status}" Value="Escalated">
<Setter TargetName="GlowGradient" Property="GradientStops" Value="{StaticResource EscalatedGradient}"/>
</DataTrigger>
I'm thinking there just has to be a way to save me from replicating the whole RadialGraientBrush each time I want to change the colours. Is there any way to access the Rectangle Fill brush from the DataTrigger? Any tips anyone? Thanks in advance.
In the end, I went with the following code:
<Rectangle Name="Glow" IsHitTestVisible="False" RadiusX="2.5" RadiusY="2.5"
Fill="{StaticResource OrangeGlow}" />
<Storyboard x:Key="GlowColourStoryboard" TargetName="Glow" Duration="0:0:1.5"
AutoReverse="True" BeginTime="0:0:0" RepeatBehavior="Forever">
<ColorAnimation Storyboard.TargetProperty="Fill.GradientStops[0].Color"
To="{StaticResource RedGradient.Colour1}" />
<ColorAnimation Storyboard.TargetProperty="Fill.GradientStops[1].Color"
To="{StaticResource RedGradient.Colour2}" />
<ColorAnimation Storyboard.TargetProperty="Fill.GradientStops[2].Color"
To="{StaticResource RedGradient.Colour3}" />
</Storyboard>
I haven't shown the Brush resources because... well you can make your own. This Storyboard is used in the following way and works as required:
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource GlowColourStoryboard}" />
</DataTrigger.EnterActions>

Resources