C# 窗口的WPF动画。顶部在不同的值处停止

C# 窗口的WPF动画。顶部在不同的值处停止,c#,.net,wpf,C#,.net,Wpf,我构建了一个类似“Windows8StartMenu”的应用程序。我使用一个动画,将菜单窗口从底部滑入屏幕。动画使用Window.Top设置动画 但每次我运行应用程序时,“Top”的值在 当(仔细阅读!)我在“SizeChanged”行上设置断点时,在~5到~15点之间出现抖动。这意味着在执行“businessLogic.CalculateWindowTopLeft”之前。这意味着,我看到的“顶部”是动画顶部的结束值 他为什么要这么做???这是一个奇怪的W32/WPF/wHandle Bug吗?

我构建了一个类似“Windows8StartMenu”的应用程序。我使用一个动画,将菜单窗口从底部滑入屏幕。动画使用Window.Top设置动画

但每次我运行应用程序时,“Top”的值在

当(仔细阅读!)我在“SizeChanged”行上设置断点时,在~5到~15点之间出现抖动。这意味着在执行“businessLogic.CalculateWindowTopLeft”之前。这意味着,我看到的“顶部”是动画顶部的结束值

他为什么要这么做???这是一个奇怪的W32/WPF/wHandle Bug吗?我不理解这种行为

额外评论:

首先,我用xaml编写了动画代码并对其进行了绑定(就像您通常所做的那样)。为了调试,我已经在代码隐藏中完成了这项工作(见下文)。我还尝试(见下文)在动画发生后设置绑定,这样绑定就不会出错。这种行为在所有情况下都是完全相同的(错误的)

告诉我,如果您仍然需要xaml代码,那么我会发布它

(很抱歉英语不好,我是德国人)

}有趣的

这个非常(!)简单的代码创建了完全相同的行为。开始10次,你就明白我的意思了。我不敢相信……:)

名称空间幻灯片测试
{
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
停用+=(s,e)=>关闭();
}
}
}

我找到了解决办法。不是很好,但是唯一有效的。我永远也不会理解那种“fillbehavior=Stop”的行为。对我来说,这似乎是一个bug(即使我不能相信),或者是“wpf动画的本质”中的一些奇怪的东西

那么,我们开始吧:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Deactivated += (s, e) => Close();

        myAnimation.Completed += (s, e) =>
            {
                this.BeginAnimation(Window.TopProperty, null);

                myStoryboard.Remove();
            };
    }
}

<Window x:Class="SlideTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="400" Width="200" Top="455" Left="700"
    WindowStyle="None" AllowsTransparency="True" Background="Aqua">
<Window.Triggers>
    <EventTrigger RoutedEvent="Window.Loaded">
        <BeginStoryboard>
            <Storyboard Duration="00:00:.30" Name="myStoryboard">
                <DoubleAnimation Duration="00:00:.30" AccelerationRatio="0.1" Storyboard.TargetProperty="Top" From="1400" To="455" FillBehavior="HoldEnd" Name="myAnimation"></DoubleAnimation>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</Window.Triggers>
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
停用+=(s,e)=>关闭();
myAnimation.Completed+=(s,e)=>
{
this.BeginAnimation(Window.TopProperty,null);
myStoryboard.Remove();
};
}
}


希望这能为其他人节省很多时间…

我检测到wAnimation.FillBehavior=FillBehavior.HoldEnd有效。但我需要更改顶部值,因此我不能使用“HoldEnd”,问题也是一样的:当我使用FillBehavior“Stop”时,为什么会这样做?当然,您必须将高度等设置为适当的屏幕尺寸。在上述情况下,我使用1440x900屏幕。
public MainWindow()
    {
        Visibility = Visibility.Hidden;

        InitializeComponent();

        businessLogic = new BusinessLogic(new DataModel(), new DataPersister());

        var vm = new MainWindowViewModel(businessLogic, new DialogService());

        DataContext = vm;

        businessLogic.Load();

        Width = businessLogic.DataModel.MenuWidth;
        Height = businessLogic.DataModel.MenuHeight;
        Opacity = 0;

        windowPosition = businessLogic.CalculateWindowTopLeft(Width, Height);

        Top = SystemParameters.PrimaryScreenHeight - (Height * 0.50);
        //Top = windowPosition.Y;
        Left = windowPosition.X;

        Background = businessLogic.GetTaskBarPreviewSolidColorBrush(1);

        vm.CloseRequested += (s) => Hide();
        Deactivated += (s, e) => { if (!vm.SettingsOpened) Close(); };

        Loaded += (s, e) =>
        {
            var wAnimation = new System.Windows.Media.Animation.DoubleAnimation(windowPosition.Y, new Duration(new TimeSpan(0, 0, 0, 0, 300)));
            wAnimation.FillBehavior = System.Windows.Media.Animation.FillBehavior.Stop;
            wAnimation.AccelerationRatio = 0.1;
            wAnimation.From = Top;

            wAnimation.Completed += (s1, e1) =>
                {
                    SizeChanged += (s2, e2) => { if (e2.HeightChanged) Top = businessLogic.CalculateWindowTopLeft(Width, Height).Y; };
                };

            var oAnimation = new System.Windows.Media.Animation.DoubleAnimation(businessLogic.DataModel.MenuOpacity, new Duration(new TimeSpan(0, 0, 0, 0, 600)));
            oAnimation.FillBehavior = System.Windows.Media.Animation.FillBehavior.Stop;
            oAnimation.AccelerationRatio = 0.1;
            oAnimation.From = 0;

            oAnimation.Completed += (s3, e3) =>
            {
                Binding myBinding = new Binding();
                myBinding.Source = DataContext;
                myBinding.Path = new PropertyPath("DataModel.MenuOpacity");
                myBinding.Mode = BindingMode.TwoWay;
                myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                BindingOperations.SetBinding(this, Window.OpacityProperty, myBinding);
            };

            BeginAnimation(Window.TopProperty, wAnimation);
            BeginAnimation(Window.OpacityProperty, oAnimation);
        };

        Visibility = Visibility.Visible;
    }
}
namespace SlideTest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Deactivated += (s, e) => Close();
        }
    }
}

<Window x:Class="SlideTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="400" Width="200" Top="500" Left="700"
    WindowStyle="None" AllowsTransparency="True" Background="Aqua">
<Window.Triggers>
    <EventTrigger RoutedEvent="Window.Loaded">
        <BeginStoryboard>
            <Storyboard Duration="00:00:.30">
                <DoubleAnimation Duration="00:00:.30" AccelerationRatio="0.1" Storyboard.TargetProperty="Top" From="1400" To="455" FillBehavior="Stop"></DoubleAnimation>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</Window.Triggers>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Deactivated += (s, e) => Close();

        myAnimation.Completed += (s, e) =>
            {
                this.BeginAnimation(Window.TopProperty, null);

                myStoryboard.Remove();
            };
    }
}

<Window x:Class="SlideTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="400" Width="200" Top="455" Left="700"
    WindowStyle="None" AllowsTransparency="True" Background="Aqua">
<Window.Triggers>
    <EventTrigger RoutedEvent="Window.Loaded">
        <BeginStoryboard>
            <Storyboard Duration="00:00:.30" Name="myStoryboard">
                <DoubleAnimation Duration="00:00:.30" AccelerationRatio="0.1" Storyboard.TargetProperty="Top" From="1400" To="455" FillBehavior="HoldEnd" Name="myAnimation"></DoubleAnimation>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</Window.Triggers>