【问题标题】:WPF Animation Only Firing OnceWPF 动画只触发一次
【发布时间】:2012-08-10 07:38:56
【问题描述】:

我有一个小椭圆,我想在每次依赖属性设置为 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。繁荣,那时我开始收到一个错误,指出另一个线程拥有该对象。我意识到我需要像在应用程序的其他部分中所做的那样,使用响应式扩展来合并一些 Observable。我使用 PropertyChanged() 恢复到视图模型的传统属性,并将其简单地绑定到控件的动画。现在一切正常。

【问题讨论】:

    标签: wpf datatrigger


    【解决方案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>
    

    【讨论】:

      【解决方案2】:

      我还看到了一个类似的问题来解决我的问题,我发现我必须在 DataTrigger 的 ExitActions 中添加一个 StopStoryboard 标记。

      【讨论】:

        【解决方案3】:

        我遇到了类似的问题,当 DP 更改时,我有一个“输入”和“输出”动画要触发。第一个周期运行良好,但之后没有任何反应。我通过在BeginStoryboard 操作之前添加RemoveStoryboard 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>
        

        【讨论】:

        • 奇怪。这背后有解释吗?
        【解决方案4】:

        我无法重现您的问题。这是我的代码隐藏:

        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;
            }
        }
        

        【讨论】:

          【解决方案5】:
           <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

          【讨论】:

          • 你为什么要绑定 TwoWay 那里?
          【解决方案6】:

          您需要提供 IsReceiving 属性的定义才能确定。基于假设您有一个在 True 和 False 之间切换的属性 (IsReceiving) 将触发此动画效果:如果您只看到触发一次的效果:

          1) 检查属性是否为 DependencyProperty 或正确利用 INotifyPropertyChanged 来向视图发出更新信号。
          2) 检查属性设置器是否实际从 True 更改为 False 并返回。

          【讨论】:

            猜你喜欢
            • 2021-11-28
            • 2021-08-14
            • 1970-01-01
            • 1970-01-01
            • 2014-08-20
            • 2011-02-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多