实现一个自定义控件警报灯,添加一个枚举类型的State类,包含这六个状态:
Warning,(红灯不闪烁)
Running,(绿灯不闪烁)
Init,(黄灯不闪烁)
EnableWarning,(红灯闪烁)
EnableRunning,(绿灯闪烁)
EnableInit,(黄灯闪烁)
要求根据不同的状态呼吸灯颜色效果相应改变,当State值为Warning、EnableWarning,时呼吸灯颜色为Red,当State值为Running、EnableRunning,时呼吸灯颜色为Green,当State值为Init、EnableInit,时呼吸灯颜色为Orange,并且当状态为Enable时触发呼吸灯的闪烁效果,我们使用Trigger来实现颜色的改变,用VisualStateManager的状态切换来实现呼吸灯闪烁效果,具体实现如下:
1.添加一个新建的自定义控件LightControl1(注意不是用户控件!)
2.在Generic.xaml(此文件在添加自定义控件时会自动添加)中设置控件模板,xaml代码如下:
<Style TargetType="local:LightControl1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:LightControl1">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Border x:Name="stateLight"
Background="{TemplateBinding Background}"
BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="50" />
<Border
Background="Transparent"
BorderBrush="Gray" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="50" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="StateEnable">
<VisualState x:Name="Enable">
<Storyboard>
<DoubleAnimation AutoReverse="True" RepeatBehavior="Forever" Storyboard.TargetName="stateLight"
Storyboard.TargetProperty="Opacity" From="0.1" To="1"
Duration="0:0:0.3" />
</Storyboard>
</VisualState>
<VisualState x:Name="UnEnable" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="State" Value="Init">
<Setter Property="Background" Value="Orange" />
</Trigger>
<Trigger Property="State" Value="Warning">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="State" Value="Running">
<Setter Property="Background" Value="Green" />
</Trigger>
<Trigger Property="State" Value="EnableInit">
<Setter Property="Background" Value="Orange" />
</Trigger>
<Trigger Property="State" Value="EnableWarning">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="State" Value="EnableRunning">
<Setter Property="Background" Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
3.后台代码如下:
public class LightControl1 : Control
{
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
"State", typeof(State), typeof(LightControl1), new PropertyMetadata(State.Init, OnStateChanged));
public State State
{
get { return (State)GetValue(StateProperty); }
set { SetValue(StateProperty, value); }
}
static LightControl1()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(LightControl1), new FrameworkPropertyMetadata(typeof(LightControl1)));
}
private void UpdateBreathingLight()
{
if (State == State.EnableWarning || State == State.EnableRunning || State == State.EnableInit)
{
VisualStateManager.GoToState(this, "Enable", true);
}
else
{
VisualStateManager.GoToState(this, "UnEnable", true);
}
}
//OnApplyTemplate方法保证在控件的模板被应用到控件上后会被调用。
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
UpdateBreathingLight();
}
private static void OnStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
LightControl1 control = d as LightControl1;
control.UpdateBreathingLight();
}
}
public enum State
{
Warning,
Running,
Init,
EnableWarning,
EnableRunning,
EnableInit
}
4.在窗口应用该控件
<Window x:Class="StateLightControl.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:MyNamespace="clr-namespace:StateLightControl" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:StateLightControl"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="MainWindow" Width="800"
Height="450" mc:Ignorable="d">
<StackPanel>
<local:LightControl1 State="Warning" Width="50" Height="50" BorderThickness="5"/>
<local:LightControl1 x:Name="lc1" State="Init" Width="20" Height="20" BorderThickness="2"/>
<local:LightControl1 State="Running" Width="20" Height="20" BorderThickness="1"/>
<local:LightControl1 State="EnableWarning" Width="50" Height="50" BorderThickness="5"/>
<local:LightControl1 State="EnableInit" Width="20" Height="20" BorderThickness="2"/>
<local:LightControl1 State="EnableRunning" Width="20" Height="20" BorderThickness="1"/>
<Button x:Name="bt1" Content="Click" Click="bt1_Click" />
</StackPanel>
</Window>
效果如图(非动图,下面三个是闪烁效果):
5. 博主在原有的样式基础上美化按钮
使用画刷给控件边框看起来更仿真,添加一个阴影效果,后台代码不用改,xaml代码如下:
<Style TargetType="local:LightControl1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:LightControl1">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Border x:Name="stateLight"
Background="{TemplateBinding Background}"
BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="50" >
<Border.Effect>
<DropShadowEffect Color="{TemplateBinding Property=Background}" Direction="0" ShadowDepth="0" Opacity="1" BlurRadius="50"/>
</Border.Effect>
</Border>
<Border
Background="Transparent"
BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="50" >
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Gray" Offset="0"/>
<GradientStop Color="FloralWhite" Offset="0.5"/>
<GradientStop Color="Gray" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
</Border>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="StateEnable">
<VisualState x:Name="Enable">
<Storyboard>
<DoubleAnimation AutoReverse="True" RepeatBehavior="Forever" Storyboard.TargetName="stateLight"
Storyboard.TargetProperty="Opacity" From="0.1" To="1"
Duration="0:0:0.5" />
</Storyboard>
</VisualState>
<VisualState x:Name="UnEnable" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="State" Value="Init">
<Setter Property="Background" Value="Orange" />
</Trigger>
<Trigger Property="State" Value="Warning">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="State" Value="Running">
<Setter Property="Background" Value="Green" />
</Trigger>
<Trigger Property="State" Value="EnableInit">
<Setter Property="Background" Value="Orange" />
</Trigger>
<Trigger Property="State" Value="EnableWarning">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="State" Value="EnableRunning">
<Setter Property="Background" Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
具体实现效果如图(非动图,具体效果自己实现看):
关于WPF自定义控件官方参考资料:创建具有可自定义外观的控件 - WPF .NET Framework | Microsoft Learn