问题
I have a small ellipse that I want to flash every time a dependency property gets set to true. Because the property can very quickly go from true back to false in a matter of milliseconds, I need to do this with an animation and not a simple style datatrigger. Basically, I just want the true value to ping an animation on the ellipse.
<Ellipse Height="10" Width="10" Stroke="#FFFFFFFF" Margin="5,3,0,0">
<Ellipse.Fill>
<SolidColorBrush />
</Ellipse.Fill>
<Ellipse.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsReceiving}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="Fill.Color">
<ColorAnimationUsingKeyFrames.KeyFrames>
<DiscreteColorKeyFrame KeyTime="0:0:0" Value="Red"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.25" Value="Transparent"/>
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
This animation seems to work, but it only fires the first time the value reaches true. Am I missing something?
UPDATE: Thanks for the input everybody. It turns out, it was a threading issue. Originally, I had a DP on the control that was bound to a view model that implemented INotifyPropertyChanged. I then tried removing the DP on the control and turning my view model property into a DP. Boom, that's when I started getting an error stating that a different thread owned the object. I realized I needed to incorporate some Observables using Reactive Extensions as I had done in other parts of the app. I reverted back to the view model traditional property with PropertyChanged() and simply bound that to the control's animation. Everything is working flawlessly now.
回答1:
I had a similar problem where I had an 'in' and 'out' animation to be fired when a DP changed. The first cycle worked fine but after that nothing happened. I solved it by adding RemoveStoryboard
EnterActions before the BeginStoryboard
actions.
<Border Name="Zyzzyx" Grid.Row="1" Background="DarkRed" Height="0" VerticalAlignment="Bottom">
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SelectionState, ElementName=ControlRoot, Mode=OneWay}" Value="Selecting">
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="AnimateIn" />
<RemoveStoryboard BeginStoryboardName="AnimateOut" />
<BeginStoryboard Name="AnimateIn" HandoffBehavior="SnapshotAndReplace">
<Storyboard FillBehavior="HoldEnd" Duration="0:0:5">
<DoubleAnimation To="30" Duration="0:0:5" Storyboard.TargetProperty="Height" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Path=SelectionState, ElementName=ControlRoot, Mode=OneWay}" Value="Deselecting">
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="AnimateIn" />
<RemoveStoryboard BeginStoryboardName="AnimateOut" />
<BeginStoryboard Name="AnimateOut" HandoffBehavior="SnapshotAndReplace">
<Storyboard FillBehavior="HoldEnd" Duration="0:0:5">
<DoubleAnimation To="0" Duration="0:0:5" Storyboard.TargetProperty="Height" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<!-- Border content -->
</Border>
回答2:
<Ellipse Height="10" Width="10" Stroke="#FFFFFFFF" Margin="5,3,0,0">
<Ellipse.Fill>
<SolidColorBrush />
</Ellipse.Fill>
<Ellipse.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsReceiving,Mode=TwoWay}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="Fill.Color">
<ColorAnimationUsingKeyFrames.KeyFrames>
<DiscreteColorKeyFrame KeyTime="0:0:0" Value="Red"/>
<DiscreteColorKeyFrame KeyTime="0:0:0.25" Value="Transparent"/>
</ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
Try to use Mode=TwoWay
回答3:
I also saw a similar issue to fix my issue I found I had to add a StopStoryboard tag in the ExitActions of the DataTrigger.
回答4:
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="AnimateIn" />
<RemoveStoryboard BeginStoryboardName="AnimateOut" />
<BeginStoryboard ...>
</DataTrigger.EnterActions>
works but i think it is better to use
<DataTrigger.EnterActions>
<BeginStoryboard Name="FadeIn"...>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="FadeIn" />
</DataTrigger.ExitActions>
回答5:
You'll need to supply the definition for the IsReceiving property to be sure. Based on the assumption that you've got a property (IsReceiving) that toggles between True and False which will trigger this animation effect: If you're only seeing the effect triggered once then:
1) Check that the property is either a DependencyProperty or utilizing INotifyPropertyChanged correctly to signal updates to the View.
2) Check that the property setter is actually changing from True to False and back.
回答6:
I can't reproduce your problem. Here's my codebehind :
public partial class MainWindow : Window
{
public static readonly DependencyProperty IsReceivingProperty =
DependencyProperty.Register("IsReceiving",
typeof(bool), typeof(MainWindow));
public bool IsReceiving
{
get { return (bool)GetValue(IsReceivingProperty); }
set { SetValue(IsReceivingProperty, value); }
}
public MainWindow()
{
InitializeComponent();
myEllipse.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.IsReceiving = true;
this.IsReceiving = false;
}
}
来源:https://stackoverflow.com/questions/11945084/wpf-animation-only-firing-once