WPF 控制动画开关

第一种方案:靠代码查找动画资源进行控制

第一步:

首先定义一个静态类,提供依赖属性,进而方便在xaml中实现绑定:

public static class AnimationBehavior { // 定义附加属性 public static readonly DependencyProperty IsAnimatingProperty = DependencyProperty.RegisterAttached( "IsAnimating", typeof(bool), typeof(AnimationBehavior), new PropertyMetadata(false, OnIsAnimatingChanged)); public static bool GetIsAnimating(DependencyObject obj) => (bool)obj.GetValue(IsAnimatingProperty); public static void SetIsAnimating(DependencyObject obj, bool value) => obj.SetValue(IsAnimatingProperty, value); private static void OnIsAnimatingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is FrameworkElement element) { // 通过 VisualTreeHelper 查找模板中的 Storyboard if (element.FindResource("ShadowAnimation") is Storyboard storyboard) { if ((bool)e.NewValue) storyboard.Begin(element, true); // 启动动画 else storyboard.Stop(element); // 停止动画 } } } }

其中实现了依赖属性IsAnimating。

第二步:

在前端中定义动画:

<Page.Resources> <!-- 将 Storyboard 定义在全局资源中 --> <Storyboard x:Key="ShadowAnimation"> <DoubleAnimation AutoReverse="True" RepeatBehavior="Forever" Storyboard.TargetName="ShadowEffect" Storyboard.TargetProperty="Opacity" From="0.0" To="1" Duration="0:0:3" /> <DoubleAnimation AutoReverse="True" RepeatBehavior="Forever" Storyboard.TargetName="myBorder" Storyboard.TargetProperty="Opacity" From="0.3" To="1" Duration="0:0:3" /> <!--<ThicknessAnimation AutoReverse="True" RepeatBehavior="Forever" Storyboard.TargetName="myBorder" Storyboard.TargetProperty="Margin" From="15" To="12" Duration="0:0:1.5" />--> </Storyboard> </Page.Resources>

其中每一个DoubleAnimation定义中的TargetName是当前界面的其他对象名称:

<Border x:Name="myBorder" Grid.ColumnSpan="1" Margin="4" localVM:AnimationBehavior.IsAnimating="{Binding CurrentActionHandle.ExecutionState, Converter={StaticResource SingleFlowExecutionStateToBoolJustRunnimg}}" Background="{Binding CurrentActionHandle.ExecutionState, Converter={StaticResource SingleFlowExecutionStateToBrushColor}}" CornerRadius="10"> <Border.Effect> <DropShadowEffect x:Name="ShadowEffect" BlurRadius="10" Direction="12" Opacity="80" ShadowDepth="0" Color="{Binding CurrentActionHandle.ExecutionState, Converter={StaticResource SingleFlowExecutionStateToColor}}" /> </Border.Effect> </Border>

比如myBorder 和 ShadowEffect;

第三步:

创建绑定关系:

比如上方代码中:

localVM:AnimationBehavior.IsAnimating="{Binding CurrentActionHandle.ExecutionState, Converter={StaticResource SingleFlowExecutionStateToBoolJustRunnimg}}"

给新手解释一下,其中localVM是自己定义的命名空间:

可我这里使用了转换器,可以理解为就是把执行动画的开关绑定到了我后端ViewModel的属性上。

第二种实现方案,使用 Style + DataTrigger

这种方法比较简单。

写好样式和触发器:

<TextBlock Grid.Row="1" VerticalAlignment="Center" FontSize="26" Text="{Binding Message}" TextWrapping="Wrap"> <TextBlock.Style> <Style TargetType="TextBlock"> <!-- 默认不闪烁 --> <Setter Property="Opacity" Value="1" /> <Style.Triggers> <!-- 当 IsBlinking 为 true 时启动闪烁动画 --> <DataTrigger Binding="{Binding IsMessageBlinking}" Value="True"> <DataTrigger.EnterActions> <BeginStoryboard> <Storyboard> <DoubleAnimation AutoReverse="True" RepeatBehavior="Forever" Storyboard.TargetProperty="Opacity" From="1.0" To="0.0" Duration="0:0:0.5" /> </Storyboard> </BeginStoryboard> </DataTrigger.EnterActions> <DataTrigger.ExitActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1.0" Duration="0:0:0.1" /> </Storyboard> </BeginStoryboard> </DataTrigger.ExitActions> </DataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock>

然后通过绑定的后端bool变量进行控制。

<DataTrigger Binding="{Binding IsMessageBlinking}" Value="True">