简体   繁体   English

从代码隐藏动态访问 Storyboard?

[英]Access Storyboard dynamically from code-behind?

I'm working on a Windows Phone app, but I believe this applies to Silverlight as well.我正在开发 Windows Phone 应用程序,但我相信这也适用于Silverlight 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.我想创建一个Storyboard (现在我将它创建为我的代码隐藏页面中的全局变量以进行测试),它将RectangleFill属性从透明更改为红色,然后再返回透明。 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.我将在多个矩形中重新使用这个Storyboard ,所以我希望能够从代码隐藏中访问它和Begin()它。 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:然后,在任何时候,如果我有一个Rectangle实例,它将从上面的Canvas上,我想启动故事板 - 这将使Rectangle变成红色,然后变回透明:

// 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:但是,它会在sb.Begin()行上抛出以下异常:

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 InvalidOperationException was unhandled by user code System.Windows.ni.dll 中发生类型为“System.InvalidOperationException”的异常,但未在用户代码中处理

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.我遵循了@Josh Mackey 提供的示例,并将我的Storyboard移到了XAML页面,我认为无论如何它都会更清晰。 What I didn't notice before was the exception details stating that "ColorAnimation cannot be used to animate property Fill due to incompatible type."我之前没有注意到的是异常详细信息,指出“由于类型不兼容ColorAnimation 不能用于为 Fill 属性设置动画”。 I was able to use @Josh Mackey's solution by changing my ColorAnimation to ColorAnimationUsingKeyFrames .通过将我的ColorAnimation更改为ColorAnimationUsingKeyFrames我能够使用@Josh Mackey 的解决方案。 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:我只能使用一个动画,因为我能够将AutoReverse设置为True ,我发现这篇文章描述了如何在我的代码隐藏中访问Storyboard ,如下所示:

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

And now it works as expected!现在它按预期工作了!

Any particular reason you can't define your storyboard in the XAML file?您无法在 XAML 文件中定义故事板的任何特殊原因?

The following example is from a WP7 project of mine.以下示例来自我的 WP7 项目。 Its a usercontrol but but same process applies, just replace UserControl with whatever you're using.它是一个用户控件,但适用相同的过程,只需将 UserControl 替换为您正在使用的任何内容。

<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) (我会发表评论,但显然我的代表不够高,所以我会发布一个带有样本的答案以使其有效。:P)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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