You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中如何创建自定义RoutedEvent实现灯光告警闪烁?

WPF 告警灯光闪烁实现方案

一、自定义RoutedEvent实现方式

如果坚持用路由事件触发,可以通过自定义控件封装告警相关的路由事件,步骤如下:

  1. 自定义告警灯光控件
    继承自基础控件(比如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));
    }
}
  1. 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>
  1. 数据变化时触发事件
    在后台代码或ViewModel中监听数据变化,根据阈值判断调用对应的触发方法:
private void CheckAlarmStatus(double currentData, double threshold)
{
    if (currentData > threshold)
    {
        alarmLight.RaiseAlarmTriggered();
    }
    else
    {
        alarmLight.RaiseAlarmCleared();
    }
}

二、无需路由事件的更优方案(DataTrigger+MVVM)

路由事件属于控件层面的交互逻辑,对于数据驱动的告警场景,更推荐用数据绑定+DataTrigger,完全贴合MVVM模式,代码更简洁耦合度更低:

  1. 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));
    }
}
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 07:39:55