WPF窗口动画.顶部停在不同的值
本文关键字:窗口 动画 顶部 WPF | 更新日期: 2023-09-27 18:08:10
我构建了一个类似"windows 8开始菜单"的应用程序。我使用动画将菜单窗口从底部滑动到屏幕上。动画使用窗口。
但是每次我运行应用程序时,
中Top的值wAnimation.Completed += (s1, e1) =>
{
SizeChanged += (s2, e2) => { if (e2.HeightChanged) Top = businessLogic.CalculateWindowTopLeft(Width, Height).Y; };
};
当(仔细阅读!)我在"SizeChanged"-Line上设置了断点时,在~5到~15点之间抖动。这意味着在"商业逻辑"之前。CalculateWindowTopLeft"被执行。这意味着,我看到的"Top"是动画顶部的最终值。
他到底为什么要这么做?这是一个奇怪的W32/WPF/wHandle bug吗?我不理解这种行为。Extra-Comment:
首先,我有动画代码在xaml和绑定它(像你通常做的)。为了调试,我已经在代码后面这样做了(见下文)。我也尝试(见下文)设置动画发生后的绑定,使绑定不能做错误的事情。这些行为在所有情况下都是完全相同的(错误的)。
告诉我,如果你还需要xaml代码,那么我就把它贴出来。
(对不起,我的英语不好,我是一个德国人)。
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;
}
}
}
有趣的…
这个非常(!)简单的代码创建了完全相同的行为。开始10次,你就明白我的意思了。我不敢相信……:)
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>
我找到了一个解决方案。不是很好,但这是唯一有效的方法。我永远不会理解"填充行为=停止"的行为。对我来说,这似乎是一个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>