简体   繁体   English

在for循环中对WPF控件进行动画处理

[英]Animate wpf control in a for loop

I am trying to implement an animation where I move my control from one row to another using for loop. 我正在尝试实现一个动画,在其中我使用for循环将控件从一行移到另一行。

    private void AnimateStoryBoard(int number)
    {
        Storyboard _currentStoryBoard = new Storyboard();

       //Row Animation
        Int32Animation newrowanimation = new Int32Animation();
        newrowanimation.From = number;
        newrowanimation.To = number+1;
        newrowanimation.Duration = new TimeSpan(0, 0, 0, 0, 500);

        Storyboard.SetTargetProperty(newrowanimation, new PropertyPath("(Grid.Row)"));

        _currentStoryBoard.Children.Add(newrowanimation);

        Storyboard.SetTarget(newrowanimation, myrectangle);

        _currentStoryBoard.Begin();
    }

and I am calling it using 我用它来称呼它

        for (int i = 0; i < 10; i++)
        {
            AnimateStoryBoard(i);
        }

Now when I run this I want the animation to go from 1 to 2 then 2 to 3 then 3 to 4...9-10. 现在,当我运行该动画时,我希望动画从1变到2,然后从2变到3,再从3变到4 ... 9-10。 However the animation directly skips to 9 and then 10. 但是,动画直接跳到9,然后跳到10。

Also how can I do this in XAML?,and please note that the number 10 here is just an example.The number has to come from code-behind and it will keep changing. 另外,如何在XAML中执行此操作?请注意,这里的数字10仅是一个示例。该数字必须来自代码隐藏,并且会不断变化。

As Alexander Clare mentioned in the comments, you have to setup several animations in a storyboard. 正如亚历山大·克莱尔(Alexander Clare)在评论中提到的那样,您必须在情节提要中设置几个动画。 Your solution using a loop does not work because your method won't return while running the loop and thus the UI Thread won't be able to render the changes that the storyboard / animations caused. 您使用循环的解决方案不起作用,因为您的方法在运行循环时不会返回,因此UI线程将无法呈现情节提要/动画引起的更改。

One solution would be a single Storyboard instance with a variable number of animations in it (one animation per row). 一种解决方案是在一个Storyboard实例中包含可变数量的动画(每行一个动画)。 Use the BeginTime property to stagger the animations. 使用BeginTime属性来交错动画。 I would suggest that you use a value from 40ms to 100ms between these animations (I wouldn't go below 20ms). 我建议您在这些动画之间使用40ms到100ms之间的值(我不会低于20ms)。

In code, this would look something like this: 在代码中,这看起来像这样:

private void AnimateStoryboard(int number)
{
    // Create the storyboard that will be played
    var storyboard = new Storyboard();

    // Create the animation objects for each row change and add them to the storyboard
    var currentBeginTime = TimeSpan.Zero;
    for (var i = 0; i < number; i++)
    {
        var animation = new Int32Animation();
        // Set all the properties that you set on your animation objects before, and additionally use BeginTime
        animation.BeginTime = currentBeginTime;
        storyboard.Children.Add(animation);

        // Update the currentBeginTime to achieve the staggering effect
        currentBeginTime += TimeSpan.FromMilliseconds(50);
    }

    // Finally, start the Storyboard to run all animations
    storyboard.Begin();

}

IMHO there is no need to reinvent the wheel: key frame animation are meant also for this purpose. 恕我直言,无需重新发明轮子: 关键帧动画也用于此目的。

So, for creating the animation that you need, you can use something like: 因此,要创建所需的动画,可以使用以下方法:

Storyboard storyBoard = new Storyboard();
int gridRowLimit = 5; // here you can set how many rows your grid has

Int32AnimationUsingKeyFrames intKeyFrame = new Int32AnimationUsingKeyFrames();
intKeyFrame.Duration = new TimeSpan(0, 0, 0, 0, gridRowLimit * 500);

for (int i = 1; i < gridRowLimit; i++)
{
    intKeyFrame.KeyFrames.Add(new DiscreteInt32KeyFrame(i));
}

Storyboard.SetTargetProperty(intKeyFrame, new PropertyPath("(Grid.Row)"));
Storyboard.SetTarget(intKeyFrame, yourControl);

storyBoard.Children.Add(intKeyFrame);
storyBoard.Begin();

I hope it helps. 希望对您有所帮助。

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

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