Reputation: 5208
I've recently been developing a WPF in C# and came across the above problem. My original code, which worked, is:
ColorAnimation backgroundfade = ClrAnim(CanvasGS2.Color, Color.FromRgb(5, 3, 13), 1, 0.8, 0.1);
backgroundfade.BeginTime = TimeSpan.FromSeconds(1.3);
CanvasGS2.BeginAnimation(GradientStop.ColorProperty, backgroundfade);
However, when I add it to a storyboard, everything runs fine, but the animation doesn't happen. To provide context, the first animation in the following code happens, but the second one doesn't:
DoubleAnimation labeltotopleft = DblAnim((double)((Label)selectedlabel).GetValue(Canvas.LeftProperty), 50, 1, 0.8, 0.2);
labeltotopleft.BeginTime = TimeSpan.FromSeconds(0.7);
InitialiseInnerMenu.Children.Add(labeltotopleft);
Storyboard.SetTarget(labeltotopleft, (Label)selectedlabel);
Storyboard.SetTargetProperty(labeltotopleft, new PropertyPath(Canvas.LeftProperty));
//((Label)selectedlabel).BeginAnimation(LeftProperty, labeltotopleft);
ColorAnimation backgroundfade = ClrAnim(CanvasGS2.Color, Color.FromRgb(5, 3, 13), 1, 0.8, 0.1);
backgroundfade.BeginTime = TimeSpan.FromSeconds(1.3);
InitialiseInnerMenu.Children.Add(backgroundfade);
Storyboard.SetTarget(backgroundfade, CanvasGS2);
Storyboard.SetTargetProperty(backgroundfade, new PropertyPath(GradientStop.ColorProperty));
//CanvasGS2.BeginAnimation(GradientStop.ColorProperty, backgroundfade);
The original code is commented out - both animations worked when I did it that way (along with the top two lines of each block).
Is it a problem with the property path?
Thanks
Chris
Upvotes: 1
Views: 274
Reputation: 5208
I finally have an answer to this question, which I discovered while researching rotation animations.
One method that works for these more abstract properties is making them “namescoped”, and then using Storyboard.SetTargetName rather than storyboard Storyboard.SetTarget. The above code can be remedied as follows:
Didn’t work:
ColorAnimation backgroundfade = ClrAnim(CanvasGS2.Color, Color.FromRgb(5, 3, 13), 1, 0.8, 0.1);
backgroundfade.BeginTime = TimeSpan.FromSeconds(1.3);
InitialiseInnerMenu.Children.Add(backgroundfade);
Storyboard.SetTarget(backgroundfade, CanvasGS2);
Storyboard.SetTargetProperty(backgroundfade, new PropertyPath(GradientStop.ColorProperty));
Does work:
ColorAnimation backgroundfade = ClrAnim(CanvasGS2.Color, Color.FromRgb(5, 3, 13), 1, 0.8, 0.1);
backgroundfade.BeginTime = TimeSpan.FromSeconds(1.3);
InitialiseInnerMenu.Children.Add(backgroundfade);
try { UnregisterName("CanvasGS2"); }
catch { }
finally { RegisterName("CanvasGS2", CanvasGS2); }
Storyboard.SetTargetName(backgroundfade, "CanvasGS2");
Storyboard.SetTargetProperty(backgroundfade, new PropertyPath(GradientStop.ColorProperty));
Another thing that needs mentioning is that, when it comes to beginning the storyboard, the following will not work:
InitialiseInnerMenu.Begin();
What’s needed is this:
InitialiseInnerMenu.Begin(this);
The object name has been “namescoped” to “this”, which is simply the MainWindow (and the default namescope).
Another way to achieve this is to target the UIElement itself, in this case a Canvas, and use an appropriate property path (for me the only drawback is that these are somewhat challenging to put together, although probably learnable in the long run), given as a string. This saves all the registering of names and having to pass a parameter to Storyboard.Begin().
First the XAML for clarity:
<Canvas x:Name="MainCanvas" >
<Canvas.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop x:Name="CanvasGS2" Color="#FF0E0727" Offset="1"/>
</LinearGradientBrush>
</Canvas.Background>
</Canvas>
And the code-behind:
ColorAnimation backgroundfade = ClrAnim(CanvasGS2.Color, Color.FromRgb(5, 3, 13), 1, 0.8, 0.1);
backgroundfade.BeginTime = TimeSpan.FromSeconds(1.3);
InitialiseInnerMenu.Children.Add(backgroundfade);
Storyboard.SetTarget(backgroundfade, MainCanvas);
Storyboard.SetTargetProperty(backgroundfade, new PropertyPath("Background.(GradientBrush.GradientStops)[1].(GradientStop.Color)"));
CanvasGS2.BeginAnimation(GradientStop.ColorProperty, backgroundfade);
Information sources:
Animate color property with different brushes
Upvotes: 1