【问题标题】:WPF Fade In / Out only runs onceWPF 淡入/淡出只运行一次
【发布时间】:2013-01-14 11:55:35
【问题描述】:

我有一个带有故事板和触发器的样式。动画效果很好,但只有一次。

我有 2 个故事板 FadeIn 和 FadeOut。在 EnterActions 中我启动 FadeIn 动画,在 ExitActions 中启动 FadeOut 动画。我用代码开始整个动画

TextBlock.StartFade = true;

当我调试上面的代码时,每次点击 StartFade 都是 False(这是正确的)。

那我做错了什么?

这是 XAML 中的样式。 FadingTextBlock 只是一个带有 StartFade 依赖属性的自定义 TextBlock。

<Style TargetType="{x:Type Controls:FadingTextBlock}">
    <Setter Property="Visibility" Value="Collapsed" />
    <Setter Property="StartFade" Value="False" />
    <Setter Property="Opacity" Value="1.0" />

    <Style.Resources>
        <Storyboard x:Key="FadeIn">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.Opacity)" Storyboard.TargetName="{x:Null}">
                <EasingDoubleKeyFrame KeyTime="0:0:0.0" Value="0.0" />
                <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1.0" />
            </DoubleAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.Visibility)" Storyboard.TargetName="{x:Null}">
                <DiscreteObjectKeyFrame KeyTime="0:0:0.0" Value="{x:Static Visibility.Visible}"/>
            </ObjectAnimationUsingKeyFrames>
            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.StartFade)" Storyboard.TargetName="{x:Null}">
                <DiscreteBooleanKeyFrame KeyTime="0:0:1.5" Value="False" />
            </BooleanAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="FadeOut">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.Opacity)" Storyboard.TargetName="{x:Null}">
                <EasingDoubleKeyFrame KeyTime="0:0:0.0" Value="1.0" />
                <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.0" />
            </DoubleAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.Visibility)" Storyboard.TargetName="{x:Null}">
                <DiscreteObjectKeyFrame KeyTime="0:0:1.5" Value="{x:Static Visibility.Collapsed}" />
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </Style.Resources>
    <Style.Triggers>
        <Trigger Property="StartFade" Value="True">
            <Trigger.EnterActions>
                <BeginStoryboard x:Name="In" Storyboard="{StaticResource FadeIn}" />                    
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <BeginStoryboard x:Name="Out" Storyboard="{StaticResource FadeOut}" />                    
            </Trigger.ExitActions>
        </Trigger>
    </Style.Triggers>
</Style>

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    您应该使用&lt;StopStoryboard&gt; 操作来阻止已启动的故事板在退出操作中播放。

        <Trigger Property="StartFade" Value="True">
            <Trigger.EnterActions>
                <StopStoryBoard BeginStoryboardName="Out"/>
                <BeginStoryboard x:Name="In" Storyboard="{StaticResource FadeIn}" />                    
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <StopStoryBoard BeginStoryboardName="In"/>
                <BeginStoryboard x:Name="Out" Storyboard="{StaticResource FadeOut}" />                    
            </Trigger.ExitActions>
        </Trigger>
    

    【讨论】:

    • 我试过了,但是动画在循环播放(进出进出……)。
    • 更正...它只是淡入。淡出动画不起作用。当不透明度达到 1 时,它会再次开始淡入动画。然后再次。又一次......
    • @MystyxMac 这可能是另一个问题,您的故事板正在循环播放。尝试调整这些属性:AutoReverse="True"RepeatBehavior="Forever" 在动画上
    • 感谢您的回答,但我最终在代码中使用了本地动画。
    • @MystyxMac 如果这是您解决问题的方法,请将其作为答案发布并接受。 (供其他用户将来搜索)。
    【解决方案2】:

    我最终在代码中使用了本地动画。

    在 Xaml 中将 TextBlock 不透明度设置为 0。

    // Fading animation for the textblock to show that the settings are updated.
    DoubleAnimation fadingAnimation = new DoubleAnimation();
    fadingAnimation.From = 0;
    fadingAnimation.To = 1;
    fadingAnimation.Duration = new Duration(TimeSpan.FromSeconds(1.5));
    fadingAnimation.AutoReverse = true;
    
    UpdateMessage.BeginAnimation(TextBlock.OpacityProperty, fadingAnimation);
    

    【讨论】:

      【解决方案3】:

      我为此实现了自己的 C# 解决方案,基于 @MystyxMac 将其提取为混合行为,这暴露了一个挑战..

      尝试连续两次显示相同的通知将不起作用,因为不会调用依赖属性更改的回调..

      我通过获取绑定、清除它并重新设置来克服这个问题。

      public class ShowFadingTextBehavior : System.Windows.Interactivity.Behavior<TextBlock>
      {
      
          public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(
            "Duration", typeof(TimeSpan), typeof(ShowFadingTextBehavior), new PropertyMetadata(TimeSpan.FromSeconds(5)));
      
          public TimeSpan Duration
          {
              get { return (TimeSpan)GetValue(DurationProperty); }
              set { SetValue(DurationProperty, value); }
          }
      
          public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
              "Text", typeof (string), typeof (ShowFadingTextBehavior), new PropertyMetadata("",OnTextChanged));
      
          private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
          {
      
              var b = (ShowFadingTextBehavior) d;
              var text = (string) e.NewValue;
      
              if(string.IsNullOrEmpty(text))
                  return;
      
              b.Show(text);
          }
      
          private void Show(string text)
          {
              var textBlock = AssociatedObject;
      
              if(textBlock==null)
                  return;
      
              textBlock.Text = text;
      
              if(textBlock.Visibility==Visibility.Visible)
                  return;
      
              textBlock.Visibility = Visibility.Visible;
      
              var a = new DoubleAnimation
              {
                  From = 1.0,
                  To = 0.0,
                  FillBehavior = FillBehavior.Stop,
                  BeginTime = TimeSpan.FromSeconds(1),
                  Duration = new Duration(Duration)
              };
      
              var storyboard = new Storyboard();
      
              storyboard.Children.Add(a);
              Storyboard.SetTarget(a, textBlock);
              Storyboard.SetTargetProperty(a, new PropertyPath(UIElement.OpacityProperty));
      
              storyboard.Completed += delegate
              {
                  textBlock.Visibility = Visibility.Collapsed;
                  textBlock.Opacity = 1.0;
      
                  var binding = BindingOperations.GetBinding(this, TextProperty);
                  if(binding==null)
                      return;
      
                  ClearValue(TextProperty);
                  BindingOperations.SetBinding(this, TextProperty, binding);
              };
      
              storyboard.Begin();
      
          }
      
          public string Text
          {
              get { return (string) GetValue(TextProperty); }
              set { SetValue(TextProperty, value); }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-06
        • 1970-01-01
        • 1970-01-01
        • 2011-04-15
        • 2011-10-26
        相关资源
        最近更新 更多