简体   繁体   中英

C# WPF: GradientStop.ColorProperty Animation Doesn't Work In Storyboard

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

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:

Storyboard doesn't work

Animate color property with different brushes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM