Я пытаюсь создать шаблон данных 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 работал, но, похоже, это необходимо.)
Другой попыткой было использование ванильного DataTrigger:
<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
сначала показалось многообещающим, но, похоже, он не содержит никакой контекстной информации о том, к какому экземпляру он был вызван и, следовательно, какой ViewModel необходимо обновить. (Похоже, StoryboardCompletedTrigger
использует это внутренне, но полагается на наличие локальных экземпляров раскадровки, а не глобальных ресурсов. Я еще не тестировал это с несколькими экземплярами шаблона, но будет важно, чтобы раскадровка, завершающая один, не влияла на другой. )
Я попытался объединить оба из них (запуск раскадровки в ванильном DataTrigger и ожидание завершения в триггере взаимодействия), но это вынуждает StoryboardCompletedTrigger.Storyboard
выдавать ошибку синтаксического анализа "При раскадровке для IsFrozen должно быть установлено значение false, чтобы изменить" при попытке присоединить к обработчику события Completed; предположительно потому что ванильные триггеры применяются как стиль.