在WPF中通过代码创建故事板

26

以下代码运行良好。

<Window.Triggers>
    <EventTrigger RoutedEvent="Window.Loaded">
        <BeginStoryboard>
            <Storyboard>
                <DoubleAnimation Duration="0:0:.8" Storyboard.TargetProperty="Left" From="1920" To="0" AccelerationRatio=".1"/>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</Window.Triggers>

但这里的 FromTo 值是静态的。我需要根据系统分辨率动态传递值。所以我需要在代码后台创建它。这可行吗?

如何将其转换为代码后台?


1
是的,你可以在代码中创建一个Storyboard对象,并应用与XAML中相同的属性。根据输入动态填充所有内容。 - Terry
你尝试过搜索吗?因特网上有很多例子(例如:http://www.codeproject.com/Articles/23257/Beginner-s-WPF-Animation-Tutorial)。 - Terry
是的,我通过了相同的示例。尝试这个:Storyboard sb = new Storyboard(); DoubleAnimation da_AngleAnimation = new DoubleAnimation(); Duration duration = new Duration(TimeSpan.FromSeconds(1)); da_AngleAnimation.Duration = duration; da_AngleAnimation.From = 1920; da_AngleAnimation.To = 100; sb.Duration = duration; sb.BeginAnimation(Window.LeftProperty, da_AngleAnimation);它不起作用。我哪里做错了吗? - Raj
你的故事板没有与任何东西连接,我想那可能是问题所在。此外,如果你只想启动一个动画而不重复,那么你不需要对象故事板,你可以使用动画,这可以在你想要动画的对象上触发(参见我的回答)。 - Terry
3个回答

51

在编写代码时,并不真正需要Storyboard,只需要针对基本事项进行动画处理,就像您在问题中展示的那样。我制作了一个简单的示例来演示它是如何简单运作的。

这是mainwindow的完整背后代码:

namespace WpfCSharpSandbox
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            WidenObject(150, TimeSpan.FromSeconds(1));
        }

        private void WidenObject(int newWidth, TimeSpan duration)
        {
            DoubleAnimation animation = new DoubleAnimation(newWidth, duration);
            rctMovingObject.BeginAnimation(Rectangle.WidthProperty, animation);
        }
    }
}

这是 XAML 的外观:

<Window x:Class="WpfCSharpSandbox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Sandbox" Height="350" Width="525">
    <Grid Background="#333333">
        <Rectangle x:Name="rctMovingObject" Fill="LimeGreen" Width="50" Height="50"/>
    </Grid>
</Window>

将此代码放入 WPF 应用程序中并查看其运行情况,进行实验并尝试其他动画/属性。


1
我尝试了这个而不是矩形 DoubleAnimation animation = new DoubleAnimation(1920, 100, duration); page.BeginAnimation(Window.LeftProperty, animation); 根据我的要求,它运行良好。 - Raj
我猜测你在故事板中挂载的动画没有被正确调用,但是将其放置在窗口上却可以工作。 - Terry
1
我想手动停止动画,因此需要使用Storyboard :( - M.kazem Akhgary
2
这个问题是关于一个故事板的,所以这不是一个答案。 - Luca Ziegler
1
这怎么成为被接受的答案了呢?原帖作者想知道如何在代码后台中制作故事板,而答案是(按照经典的SO方式)“你不需要做‘那个’,改为做‘这个’即可”。很好,但我想学习如何做‘那个’,因此提出了问题,特别是询问‘那个’。 - AsPas

1
添加djerry的评论示例代码将如下所示:

var anim = new DoubleAnimation {
                                From = 1920, 
                                To = 1, 
                               };

wnd.BeginAnimation(Window.LeftProperty, anim); 

你需要将这段代码放在窗口加载事件处理程序中。希望这能帮到你。


1
这个问题是关于一个故事板的,所以这不是一个答案。 - Luca Ziegler
1
OP的问题标题说的是Storyboard,但实际上问题是关于他如何从代码后端动态设置动画的“From”和“To”值。这个答案解决了这个问题。 - Suresh

1
这个问题的示例代码是关于动画化 Window.Left 属性的,我正需要这样精确的情况,但给出的答案仅适用于一次性使用场景。
具体来说:如果执行了动画并且之后通过拖放手动移动了窗口,则相同的动画过程将不能再次按照预期工作。动画将始终使用最近一次动画运行的结束坐标。
因此,如果您移动了窗口,它将在开始新的动画之前跳回去:

https://imgur.com/a/hxRCqm7

为解决这个问题,在动画完成后需要从动画属性中移除任何AnimationClock。可以使用ApplyAnimationClock或者BeginAnimation函数,并将第二个参数设为null来实现此操作。
public partial class MainWindow : Window
{
    // [...]

    private void ButtonMove_Click(object sender, RoutedEventArgs e)
    {
        AnimateWindowLeft(500, TimeSpan.FromSeconds(1));
    }

    private void AnimateWindowLeft(double newLeft, TimeSpan duration)
    {
        DoubleAnimation animation = new DoubleAnimation(newLeft, duration);
        myWindow.Completed += AnimateLeft_Completed;
        myWindow.BeginAnimation(Window.LeftProperty, animation);
    }

    private void AnimateLeft_Completed(object sender, EventArgs e)
    {
        myWindow.BeginAnimation(Window.LeftProperty, null);
        // or
        // myWindow.ApplyAnimationClock(Window.LeftProperty, null);
    }
}

XAML:
<Window x:Class="WpfAppAnimatedWindowMove.MainWindow"
        // [...]
        Name="myWindow">

Result:
https://imgur.com/a/OZEsP6t

另请参阅Microsoft Docs中的Remarks部分 - HandoffBehavior枚举


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接