WPF MVVM:属性变更触发Storyboard仅生效一次的问题咨询
看起来你遇到的问题是DataTrigger绑定的属性变更后,Storyboard只执行一次,没法重复触发对吧?这是因为默认情况下,当你的ViewEventTrigger保持True状态时,DataTrigger不会再次触发,而且Storyboard默认会保持动画结束后的状态,导致后续的属性变更无法驱动动画重新执行。下面给你几个关键的修复步骤:
1. 让ViewModel的属性来回切换状态
你的定时器触发时,不能只把ViewEventTrigger设为True就完事了,需要在触发后立刻(或者延迟一点)把它改回False,这样下一次定时器触发时,属性会从False变为True,才能再次触发DataTrigger。
假设你的ViewModel实现了INotifyPropertyChanged,可以这样修改定时器的逻辑:
private bool _viewEventTrigger; public bool ViewEventTrigger { get => _viewEventTrigger; set { _viewEventTrigger = value; OnPropertyChanged(nameof(ViewEventTrigger)); } } // 定时器触发的方法 private void OnTimerElapsed(object sender, ElapsedEventArgs e) { // 切换为True触发动画 ViewEventTrigger = true; // 延迟一点(比如动画时长)再切回False,确保动画执行完成 Application.Current.Dispatcher.InvokeAsync(() => { Task.Delay(500).ContinueWith(_ => { Application.Current.Dispatcher.Invoke(() => ViewEventTrigger = false); }); }); }
注意:这里用了Dispatcher是因为定时器线程不是UI线程,必须回到UI线程更新属性。延迟时间可以根据你的动画时长调整,比如如果动画是500毫秒,就延迟500毫秒再切回False。
2. 调整XAML中的Storyboard和DataTrigger
确保你的Storyboard设置FillBehavior="Stop",这样动画结束后,Border会回到原来的背景状态,而不是停留在动画最后的状态。同时,把Storyboard放在DataTrigger的EnterActions里:
<Border Name="btnBorder" Grid.Row="0" Grid.Column="0" Opacity="1" CornerRadius="10,10,0,0"> <Border.Style> <Style TargetType="Border"> <Setter Property="Background" Value="#e2e2e2"></Setter> <Style.Triggers> <DataTrigger Binding="{Binding ViewEventTrigger}" Value="True"> <DataTrigger.EnterActions> <BeginStoryboard> <Storyboard FillBehavior="Stop"> <!-- 这里写你的闪烁动画,比如背景色从#e2e2e2变到红色再变回来 --> <ColorAnimation Storyboard.TargetProperty="Background.Color" From="#e2e2e2" To="#ff0000" Duration="0:0:0.2" AutoReverse="True" RepeatBehavior="2x"/> </Storyboard> </BeginStoryboard> </DataTrigger.EnterActions> </DataTrigger> </Style.Triggers> </Style> </Border.Style> </Border>
这里的AutoReverse="True"和RepeatBehavior="2x"是让动画来回闪烁两次,你可以根据需求调整。FillBehavior="Stop"是关键,它会让动画结束后Border的背景回到Style里设置的默认值。
3. 额外注意点
- 确保你的ViewModel正确实现了
INotifyPropertyChanged,否则属性变更不会通知到视图。 - 定时器要记得在ViewModel销毁时停止,避免内存泄漏。
- 如果你的动画时长比较长,延迟切回False的时间要大于等于动画时长,确保动画完整执行后再切换属性状态。
这样修改后,每5分钟定时器触发时,ViewEventTrigger会从False变为True,触发一次闪烁动画,然后自动切回False,下一次定时器触发时就能再次触发动画了。
内容的提问来源于stack exchange,提问作者Niksen

