wpf - WPF MVVM:从值变化触发行进点动画
问题描述
我正在尝试创建一个行进点动画,其中有一系列小圆圈,一个会变长一点并改变颜色,然后下一个会改变颜色,依此类推,这会来回反弹。动画将由 ViewModel 中的布尔值触发。
在决定使用 MVVM 模式之前,我实际上已经完成了这项工作,这很容易:我在 Page.Resources 标记中有故事板,并在按钮单击时从代码后面调用动画。现在我坚持这种解耦,似乎无论我尝试什么,总会出现某种错误。
这是xaml中的点:
<Grid Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="2" Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Ellipse Name="Dot5" Grid.Row="1" Grid.Column="0" Style="{StaticResource ConnectionMeterOff}"/>
<Ellipse Name="Dot4" Grid.Row="1" Grid.Column="1" Style="{StaticResource ConnectionMeterOff}"/>
<Ellipse Name="Dot3" Grid.Row="1" Grid.Column="2" Style="{StaticResource ConnectionMeterOff}"/>
<Ellipse Name="Dot2" Grid.Row="1" Grid.Column="3" Style="{StaticResource ConnectionMeterOff}"/>
<Ellipse Name="Dot1" Grid.Row="1" Grid.Column="4" Style="{StaticResource ConnectionMeterOff}"/>
</Grid>
还有我现在的动画:
<DataTemplate x:Key="MarchingDots">
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsConnecting}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard Name="MarchingDotsAnimation">
<Storyboard RepeatBehavior="Forever" AutoReverse="True">
<DoubleAnimation Storyboard.TargetName="Dot1" BeginTime="0:0:0.1"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot1" BeginTime="0:0:0.1"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="Dot2" BeginTime="0:0:0.2"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot2" BeginTime="0:0:0.2"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="Dot3" BeginTime="0:0:0.3"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot3" BeginTime="0:0:0.3"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="Dot4" BeginTime="0:0:0.4"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot4" BeginTime="0:0:0.4"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="Dot5" BeginTime="0:0:0.5"
Storyboard.TargetProperty="Width" From="10" To="15"
Duration="0:0:0.2" AutoReverse="True"/>
<ColorAnimation Storyboard.TargetName="Dot5" BeginTime="0:0:0.5"
Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)"
From="#FF5B5B5B" To="#FF84161C" Duration="0:0:0.3" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
我很确定我的问题不是绑定,而是动画没有附加到点上,或者我如何尝试包装它以访问触发器。如果我像以前一样保留它只是一个故事板,我没有任何东西可以触发它。如果我尝试一种风格,它会抱怨我可以使用“Storyboard.TargetName”。我也尝试过 EventTriggers。以及大量的谷歌搜索......所有示例似乎都是单个元素(如矩形),故事板可以附加到元素的样式。
我敢肯定这很简单,但我做错了什么?
解决方案
这需要一些清理,但它会让你开始。首先声明你的动画:
<Storyboard x:Key="Storyboard1" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard2" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard3" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard4" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.25" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.75" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.25" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard5" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.25" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.25" Value="1.15"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
我将用椭圆构建它,因此为它们创建一个基本样式:
<Style x:Key="EllipseStyle" TargetType="Ellipse">
<Setter Property="Fill" Value="Black" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
<Setter Property="Margin" Value="10" />
<Setter Property="RenderTransform">
<Setter.Value>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Setter.Value>
</Setter>
</Style>
然后创建五个椭圆,为每个椭圆分配相应的故事板,并使用 DataTrigger 打开和关闭动画:
<UniformGrid Columns="5">
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard1" Storyboard="{StaticResource Storyboard1}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard1" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard2" Storyboard="{StaticResource Storyboard2}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard2" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard3" Storyboard="{StaticResource Storyboard3}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard3" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard4" Storyboard="{StaticResource Storyboard4}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard4" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource EllipseStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Animating}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard5" Storyboard="{StaticResource Storyboard5}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard5" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</UniformGrid>
<CheckBox Content="Animate" IsChecked="{Binding Animating}" HorizontalAlignment="Center"/>
</StackPanel>
我假设您的视图模型中有一个属性,称为Animating
您用来控制它的属性,我还在此代码中添加了一个复选框以进行测试:
编辑:刚刚更新了动画以消除右侧的闪烁。
推荐阅读
- javascript - Promise.all 奇怪的解决问题
- java - 如果 hashCode() & equals() 返回相同的值,UserDefined 类如何成为 hashmap 的键
- javascript - 如何将 daterangepicker 值转换为两个不同的变量?
- command-line - 如何在 Vb6 中的控制台程序的相同实例中运行 2 个命令行?
- php - laravel 查询之间的两个日期
- c++ - 如何处理保存在指针中的内存空间?
- javascript - ./node_modules/axios/lib/helpers/cookies.js 错误:EPERM:不允许操作,读取
- c++ - 使用嵌套循环迭代 m^n 组合
- python - 使用 BS4 提取元素
- c++ - Assimp 更新到 5.0.1 问题与骨骼 mname 和 mnumweights