每次将依赖项属性设置为true时,我都会想要闪烁一个小椭圆。因为属性可以在几毫秒内非常快速地从true返回到false,所以我需要使用动画而不是简单的样式数据触发器。基本上,我只想要在椭圆上ping动画的真值。
<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>
这个动画似乎有效,但它只在第一次值达到true时触发。我错过了什么吗?
更新: 感谢大家的投入。事实证明,这是一个线程问题。最初,我在控件上有一个DP,它绑定到实现了INotifyPropertyChanged的视图模型。然后我尝试删除控件上的DP并将我的视图模型属性转换为DP。 Boom,就是当我开始收到错误声明另一个线程拥有该对象时。我意识到我需要使用Reactive Extensions合并一些Observable,正如我在应用程序的其他部分所做的那样。我使用PropertyChanged()恢复到视图模型传统属性,并简单地将其绑定到控件的动画。现在一切都完美无瑕。
答案 0 :(得分:4)
我有一个类似的问题,当DP改变时我有一个'in'和'out'动画被触发。第一个周期工作正常,但之后没有任何事情发生。我通过在RemoveStoryboard
操作之前添加BeginStoryboard
EnterActions来解决此问题。
<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>
答案 1 :(得分:1)
<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>
尝试使用Mode = TwoWay
答案 2 :(得分:1)
我也看到类似的问题来解决我的问题,我发现我必须在DataTrigger的ExitActions中添加一个StopStoryboard标记。
答案 3 :(得分:1)
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="AnimateIn" />
<RemoveStoryboard BeginStoryboardName="AnimateOut" />
<BeginStoryboard ...>
</DataTrigger.EnterActions>
有效,但我认为最好使用
<DataTrigger.EnterActions>
<BeginStoryboard Name="FadeIn"...>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="FadeIn" />
</DataTrigger.ExitActions>
答案 4 :(得分:0)
您需要提供IsReceiving属性的定义以确保。假设您有一个属性(IsReceiving)在True和False之间切换,这将触发此动画效果:如果您只看到触发一次的效果:
1)检查属性是DependencyProperty还是正确使用INotifyPropertyChanged来发送视图更新信号。
2)检查属性设置器实际上是从True变为False还是返回。
答案 5 :(得分:0)
我无法重现你的问题。这是我的代码隐藏:
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;
}
}