我正在尝试从我的视图模型开始一个故事板动画。这个想法是,以后每次我的应用程序从服务器接收到位置更新时都会有一个动画,但现在有一个概念证明,我可以更新位置并通过按下按钮来启动动画。
我的第一种方法是使用 Microsoft.Expression.Interactivity ControlStoryboardAction(请随时告诉我是否有更好的方法来实现我想要实现的目标)。我将触发器绑定到 CanAnimate 属性,该属性默认设置为 true,因此动画应该在加载后立即开始 - 但事实并非如此。当我使用 Eventtrigger 时情节提要有效,但这不是我想要的:
<Window x:Class="AnimationExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AnimationExample"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Canvas Name="CanvasWrapper" Width="525" Height="350">
<Ellipse Fill="Red" Width="60" Height="60" Canvas.Left="60" Canvas.Top="60">
<Ellipse.Resources>
<Storyboard x:Key="Movement">
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Left)"
Duration="0:0:0.1" To="{Binding NextPosX}" />
<DoubleAnimation
Storyboard.TargetProperty="(Canvas.Top)"
Duration="0:0:0.1" To="{Binding NextPosY}" />
</Storyboard>
</Ellipse.Resources>
<!-- This trigger is just for testing and works fine! -->
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Ellipse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource Movement}"/>
</EventTrigger.Actions>
</EventTrigger>
</Ellipse.Triggers>
<!-- This trigger doesn't works -->
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding CanAnimate}" Value="True" Comparison="Equal">
<ei:ControlStoryboardAction Storyboard="{StaticResource Movement}" ControlStoryboardOption="Play" />
</ei:DataTrigger>
</i:Interaction.Triggers>
</Ellipse>
</Canvas>
</Window>
到目前为止,这是我的视图模型。显然缺少对 ActionCommand 的 Binding,并且 ActionCommand 也应该更改 CanAnimate 以便再次触发 Animation,但由于 CanAnimate 为 true,它仍应设置一次动画:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace AnimationExample
{
class MainWindowViewModel : INotifyPropertyChanged
{
int _nextPosX = 120;
public int NextPosX
{
get { return _nextPosX; }
set
{
if (value != _nextPosX)
{
_nextPosX = value;
OnPropertyChanged("NextPosX");
}
}
}
int _nextPosY = 120;
public int NextPosY
{
get { return _nextPosY; }
set
{
if (value != _nextPosY)
{
_nextPosY = value;
OnPropertyChanged("NextPosY");
}
}
}
bool _canAnimate = true;
public bool CanAnimate
{
get { return _canAnimate; }
set
{
if (value != _canAnimate)
{
_canAnimate = value;
OnPropertyChanged("CanAnimate");
}
}
}
ICommand _calculate;
public ICommand CalculateNextPos
{
get
{
if(_calculate == null)
{
_calculate = new ActionCommand(dummy =>
{
NextPosX = 500;
NextPosY = 500;
}, dummy => true);
}
return _calculate;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
提前致谢!