WPF中如何创建自定义RoutedEvent实现灯光告警闪烁?
WPF 告警灯光闪烁实现方案
一、自定义RoutedEvent实现方式
如果坚持用路由事件触发,可以通过自定义控件封装告警相关的路由事件,步骤如下:
- 自定义告警灯光控件
继承自基础控件(比如Border),注册两个路由事件:AlarmTriggered(触发闪烁)和AlarmCleared(停止闪烁),并提供触发事件的方法:
public class AlarmLight : Border { // 告警触发路由事件 public static readonly RoutedEvent AlarmTriggeredEvent = EventManager.RegisterRoutedEvent( "AlarmTriggered", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AlarmLight)); public event RoutedEventHandler AlarmTriggered { add => AddHandler(AlarmTriggeredEvent, value); remove => RemoveHandler(AlarmTriggeredEvent, value); } public void RaiseAlarmTriggered() { RaiseEvent(new RoutedEventArgs(AlarmTriggeredEvent)); } // 告警解除路由事件 public static readonly RoutedEvent AlarmClearedEvent = EventManager.RegisterRoutedEvent( "AlarmCleared", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AlarmLight)); public event RoutedEventHandler AlarmCleared { add => AddHandler(AlarmClearedEvent, value); remove => RemoveHandler(AlarmClearedEvent, value); } public void RaiseAlarmCleared() { RaiseEvent(new RoutedEventArgs(AlarmClearedEvent)); } }
- XAML中绑定事件与Storyboard
在XAML里使用EventTrigger关联自定义路由事件,控制Storyboard的启停:
<local:AlarmLight x:Name="alarmLight" Background="Green"> <local:AlarmLight.Triggers> <EventTrigger RoutedEvent="local:AlarmLight.AlarmTriggered"> <BeginStoryboard> <Storyboard x:Name="FlashStoryboard"> <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Green" To="Red" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="Forever"/> </Storyboard> </BeginStoryboard> </EventTrigger> <EventTrigger RoutedEvent="local:AlarmLight.AlarmCleared"> <StopStoryboard BeginStoryboardName="FlashStoryboard"/> <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Green" Duration="0:0:0.1"/> </EventTrigger> </local:AlarmLight.Triggers> </local:AlarmLight>
- 数据变化时触发事件
在后台代码或ViewModel中监听数据变化,根据阈值判断调用对应的触发方法:
private void CheckAlarmStatus(double currentData, double threshold) { if (currentData > threshold) { alarmLight.RaiseAlarmTriggered(); } else { alarmLight.RaiseAlarmCleared(); } }
二、无需路由事件的更优方案(DataTrigger+MVVM)
路由事件属于控件层面的交互逻辑,对于数据驱动的告警场景,更推荐用数据绑定+DataTrigger,完全贴合MVVM模式,代码更简洁耦合度更低:
- ViewModel中定义告警状态属性
实现INotifyPropertyChanged,通过数据变化自动更新告警状态:
public class MainViewModel : INotifyPropertyChanged { private bool _isAlarmActive; public bool IsAlarmActive { get => _isAlarmActive; set { _isAlarmActive = value; OnPropertyChanged(); } } private double _currentData; public double CurrentData { get => _currentData; set { _currentData = value; OnPropertyChanged(); // 根据阈值切换告警状态(示例阈值为100) IsAlarmActive = _currentData > 100; } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); } }
- XAML中用DataTrigger控制动画
直接绑定ViewModel的IsAlarmActive属性,通过DataTrigger的EnterActions和ExitActions控制Storyboard的启停:
<!-- 先在资源中声明ViewModel实例 --> <Window.Resources> <local:MainViewModel x:Key="MainViewModel"/> </Window.Resources> <Border Background="Green" DataContext="{StaticResource MainViewModel}"> <Border.Style> <Style TargetType="Border"> <Style.Triggers> <DataTrigger Binding="{Binding IsAlarmActive}" Value="True"> <DataTrigger.EnterActions> <BeginStoryboard> <Storyboard x:Name="FlashStoryboard"> <ColorAnimation Storyboard.TargetProperty="Background.Color" From="Green" To="Red" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="Forever"/> </Storyboard> </BeginStoryboard> </DataTrigger.EnterActions> <DataTrigger.ExitActions> <StopStoryboard BeginStoryboardName="FlashStoryboard"/> <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Green" Duration="0:0:0.1"/> </DataTrigger.ExitActions> </DataTrigger> </Style.Triggers> </Style> </Border.Style> </Border>
这个方案不需要自定义路由事件,完全由数据状态驱动UI变化,符合WPF的设计理念,后期维护和扩展也更方便。
内容的提问来源于stack exchange,提问作者CSTK6667
相关产品推荐
相关产品推荐

