Access Storyboard dynamically from code-behind?

风流意气都作罢 提交于 2019-12-11 11:58:18

问题


I'm working on a Windows Phone app, but I believe this applies to Silverlight as well. I want to create a Storyboard (right now I'm creating it as a global variable in my code-behind page for testing) that changes a Rectangle's Fill property from transparent to red, and then back to transparent. I'm going to be re-using this Storyboard among multiple rectangles so I'd like to be able to access it and Begin() it from the code-behind. I couldn't find any examples like this, so I gave it a shot with what I thought might work.

Initial setup:

sb = new Storyboard();

turnOn= new ColorAnimation();
turnOn.From = Colors.Transparent;
turnOn.To = Colors.Red;
turnOn.Duration = new TimeSpan(0, 0, 0, 0, 500); //half second

turnOff= new ColorAnimation();
turnOff.From = Colors.Red;
turnOff.To = Colors.Transparent;
turnOff.Duration = new TimeSpan(0, 0, 0, 0, 500); //half second

Storyboard.SetTargetProperty(turnOn, new PropertyPath("(Rectangle.Fill)"));
Storyboard.SetTargetProperty(turnOff, new PropertyPath("(Rectangle.Fill)"));

sb.Children.Add(turnOn);
sb.Children.Add(turnOff);

canvas.Resources.Add("sb", sb); // this is the canvas where the rectangles will be

Then, at any time, if I have a Rectangle instance, which will be on the Canvas from above, I'd like to initiate the storyboard - which will turn the Rectangle red, and then back to transparent:

// Set the target to my current rectangle, and begin:
Storyboard.SetTarget(turnOn, myRectangle);
Storyboard.SetTarget(turnOn, myRectangle);
sb.Begin();

But, it throws the following exception on the sb.Begin() line:

InvalidOperationException was unhandled by user code An exception of type 'System.InvalidOperationException' occurred in System.Windows.ni.dll but was not handled in user code

I'm hoping I'm not too far off here in my thinking, but maybe there is an easier way? If not, can anyone see what I'm doing wrong?

UPDATE (SOLUTION):

I followed the example provided by @Josh Mackey and moved my Storyboard into the XAML page which I think will be cleaner anyway. What I didn't notice before was the exception details stating that "ColorAnimation cannot be used to animate property Fill due to incompatible type." I was able to use @Josh Mackey's solution by changing my ColorAnimation to ColorAnimationUsingKeyFrames. New code:

<Canvas.Resources>
  <Storyboard x:Name="sb">
    <ColorAnimationUsingKeyFrames 
      Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
         AutoReverse="True">
            <EasingColorKeyFrame KeyTime="00:00:0" Value="Black" />
            <EasingColorKeyFrame KeyTime="00:00:0.25" Value="Red" />
    </ColorAnimationUsingKeyFrames>
  </Storyboard>
</Canvas.Resources>

I was able to only use one animation because I was able to set AutoReverse to True and I found this article which describes how I can access the Storyboard in my code-behind like this:

sb.Stop();
sb.SetValue(Storyboard.TargetNameProperty, myRectangle.Name);
sb.Begin();

And now it works as expected!


回答1:


Any particular reason you can't define your storyboard in the XAML file?

The following example is from a WP7 project of mine. Its a usercontrol but but same process applies, just replace UserControl with whatever you're using.

<UserControl.Resources>
    <Storyboard x:Key="aniFlipToBack">
        <DoubleAnimation Storyboard.TargetName="LayoutRoot" 
                         Completed="DoubleAnimation_Completed"
                         Storyboard.TargetProperty="(Grid.Projection).(PlaneProjection.RotationY)" 
                         From="0" To="180" Duration="0:0:0.5" RepeatBehavior="1x" />
        <ObjectAnimationUsingKeyFrames 
            Duration="0:0:0.5"
            Storyboard.TargetName="gridFront" Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0:0:0.25" Value="Collapsed" />
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames 
            Duration="0:0:0.5"
            Storyboard.TargetName="gridBack" Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0:0:0.25" Value="Visible" />
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>     
</UserControl.Resources>

And to use it:

Storyboard storyBoard = (Storyboard)this.Resources["aniFlipToBack"];
storyBoard.Begin();

(I would have commented but apparently my rep isn't high enough, so I'll post an answer with a sample to make it valid. :P)



来源:https://stackoverflow.com/questions/13318727/access-storyboard-dynamically-from-code-behind

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!