我正在尝试创建一个WPF(4.6.2)数据模板,该模板将在特定的ViewModel属性设置为true时执行动画,然后在动画完成后(不仅仅是在启动时)将该属性设置为false。
这是一次尝试:
<DataTemplate DataType="...">
<Border x:Name="Bd" ...>
<Border.Resources>
<Storyboard x:Key="Animate" FillBehavior="Stop">
<DoubleAnimation Storyboard.TargetName="Bd"
Storyboard.TargetProperty="Opacity"
From="0" To="1" Duration="0:0:3" />
</Storyboard>
</Border.Resources>
...
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding ShouldAnimate}" Value="true">
<ei:ControlStoryboardAction Storyboard="{StaticResource Animate}"
ControlStoryboardOption="Play" />
</ei:DataTrigger>
<ei:StoryboardCompletedTrigger Storyboard="{StaticResource Animate}">
<ei:ChangePropertyAction TargetObject="{Binding}"
PropertyName="ShouldAnimate"
Value="false" />
</ei:StoryboardCompletedTrigger>
</i:Interaction.Triggers>
</Border>
</DataTemplate>
这很管用…前提是我只将属性设置为true
之后
它已经创建了用户界面。如果属性已经为true,则不会发生任何事情(情节提要未启动,属性未重置)。
(我也不太高兴必须将故事板声明为本地资源,以便targetname可以工作,但这似乎是必需的。)
另一个尝试是使用普通的数据触发器:
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding ShouldAnimate}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Animate}" />
</DataTrigger.EnterActions>
</DataTrigger>
</DataTemplate.Triggers>
这可以成功地设置动画,即使属性是预先设置的(尽管奇怪的是,这个属性
Storyboard.TargetName
必须是
不
指定,并且故事板本身必须完全声明在
DataTemplate
或嵌入到
BeginStoryboard
而不是使用资源)。但在动画完成时,我找不到任何好的方法来重置属性。
Storyboard.Completed
一开始看起来很有希望,但是它似乎不包含任何上下文信息,比如它调用了哪个实例,因此需要更新哪个视图模型。(看起来像
StoryboardCompletedTrigger
在内部使用它,但依赖于本地故事板实例而不是全局资源。我还没有用多个模板实例测试过这个,但重要的是,在一个模板上完成的故事板不会影响另一个模板。)
我尝试结合这两种方法(在普通的数据触发器中启动故事板,在交互触发器中等待完成),但这会导致
StoryboardCompletedTrigger.Storyboard
若要引发分析错误,在尝试附加到已完成的事件处理程序时,“Storyboard must have isfrozed set to false to modify”;可能是因为将普通触发器作为样式应用。