WPF中的VisualState(视觉状态)

以前在设置控件样式或自定义控件时,都是使用触发器来进行样式更改。触发器可以在属性值发生更改时启动操作。

像这样:

复制代码
<Style TargetType="ListBoxItem">
        <Setter Property="Opacity" Value="0.5" />
        <Setter Property="MaxHeight" Value="75" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Trigger.Setters>
                    <Setter Property="Opacity" Value="1.0" />
                </Trigger.Setters>
            </Trigger>
        </Style.Triggers>
 </Style>

还可以使用VisualState类来进行样式更改

VisualState类实现了可以让控件始终处于特定的状态的功能。例如,当鼠标在控件的表面上移动时,该控件被视为处于MouseOver状态。 没有特定状态的控件被视为处于 Normal 状态。

状态分为多个组,前面提到的MouseMove状态和Normal属于 CommonStates 状态组(VisualStateGroup)。 大多数控件都有两个状态组:CommonStatesFocusStates

在应用于控件的每个状态组中,控件始终处于每个组的一种状态。但是,控件不能处于同一组中的两种不同状态。

完整的状态可以参照下表:

VisualState 名称 VisualStateGroup 名称 描述
Normal CommonStates 默认状态。
MouseOver CommonStates 鼠标指针悬停在控件上方。
Pressed CommonStates 已按下控件。
Disabled CommonStates 已禁用控件。
Focused FocusStates 控件有焦点。
Unfocused FocusStates 控件没有焦点。

注意:

1、VisaulState只适用于状态改变需要过渡动画的情况,如果不想实现过渡效果,推荐使用触发器。

2、如果要查找WPF附带控件可视状态(VisualState)的名称,可参阅控件源码。(https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/controls/control-styles-and-templates)

下面我们使用VisualState类来自定义一个Button样式

1、使用Visual Studio 2019创建一个.Net Core WPF程序

2、在MainWindow中添加两个Button控件,第一个button用于展示状态,第二个button用于模拟控制第一个按钮的状态

复制代码
 1 <Window x:Class="VisualStateDemo.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:VisualStateDemo"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="450" Width="800">   
 9     <StackPanel>
10         <Button Content="button1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="88" Height="26" Name="btn"/>
11         <Button Content="button2(make button 1 to Pressed state)" HorizontalAlignment="Center" VerticalAlignment="Bottom"  Height="26" Name="btn_2" Click="btn_2_Click"/>
12     </StackPanel>
13 </Window>

3、在Windows.Resources下定义样式,如下

复制代码
 1  <Window.Resources>
 2         <Style TargetType="{x:Type Button}">
 3             <Setter Property="BorderBrush" Value="Transparent"/>
 4             <Setter Property="Background" Value="Black"/>
 5             <Setter Property="Foreground" Value="White"/>
 6 
 7             <Setter Property="Template">
 8                 <Setter.Value>
 9                     <ControlTemplate TargetType="{x:Type Button}">
10                         <Border BorderThickness="{TemplateBinding Border.BorderThickness}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="border" SnapsToDevicePixels="True" CornerRadius="5">
11                             <VisualStateManager.VisualStateGroups>
12                                 <VisualStateGroup Name="CommonStates">
13                                     <VisualState Name="Normal">
14                                         <Storyboard>
15                                             <ColorAnimation Storyboard.TargetName="border"
16                                     Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
17                                     To="{TemplateBinding Background}"
18                                     Duration="0:0:0.3"/>
19                                         </Storyboard>
20                                     </VisualState>
21                                     <VisualState Name="MouseOver">
22                                         <Storyboard>
23                                             <ColorAnimation Storyboard.TargetName="border"
24                                     Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
25                                     To="Silver"
26                                     Duration="0:0:0.3"/>
27                                         </Storyboard>
28                                     </VisualState>
29                                     <VisualState Name="Pressed">
30                                         <Storyboard>
31                                             <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="#7b8488" Duration="0:0:0.3"/>
32                                         </Storyboard>
33                                     </VisualState>
34                                 </VisualStateGroup>
35                             </VisualStateManager.VisualStateGroups>
36                             <ContentPresenter RecognizesAccessKey="True" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Name="contentPresenter" Margin="{TemplateBinding Control.Padding}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" Focusable="False" />
37                         </Border>
38                     </ControlTemplate>
39                 </Setter.Value>
40             </Setter>
41         </Style>
42     </Window.Resources>

4、运行效果如下:

5、使用代码控制VisualState

调用System.Windows.VisualStateManager.GoToState函数,可以指定控件的状态。

在按钮2的单击事件中添加以下代码

复制代码
1         private void btn_2_Click(object sender, RoutedEventArgs e)
2         {
3             System.Windows.VisualStateManager.GoToState(btn, "Pressed", false);
4         }

如果是自定义控件,直接将控件名换成this即可

复制代码
1 System.Windows.VisualStateManager.GoToState(this, "Pressed", false);

注意:

如果在ControlTemplate中使用 VisualStateManager,应该调用 GoToState 方法。

如果在ControlTemplate 外使用 VisualStateManager (例如,如果在 UserControl 中或在单个元素中使用 VisualStateManager),应该调用 GoToElementState 方法。

示例代码

相关推荐
SamChan901 天前
Python+PyMuPDF提取PDF表格并翻译:表格结构检测与双语重建实战
windows·python·ai·pdf·wpf
SamChan901 天前
Python+OpenCV检测PDF翻译后排版偏移:像素级格式一致性验证
python·opencv·ai·pdf·wpf
FuckPatience1 天前
WPF 拿到控件的最初样式,修改获得焦点样式
wpf
主宰者1 天前
【WPF】MainWindow前添加加载窗口,发现加载过程中有白色无内容窗口闪烁一下的解决方案
wpf
Vae_Mars2 天前
WPF中的ControlTemplate(控件模板)
wpf
SamChan902 天前
Python+ReportLab自动生成PDF翻译质量审计报告:从数据到可视化的完整方案
开发语言·python·ai·pdf·wpf
circuitsosk2 天前
多智能体协同在能源数据分析中的实践:分配-执行-校验闭环架构设计
python·数据分析·wpf·能源·并行计算·多智能体系统·agent协作
weixin199701080163 天前
《大促护航:电商API限流与降级,双11峰值500万调用的架构复盘》(附Python源码)
python·架构·wpf
hh9504 天前
gent Plan x DeepSeek Harness:多 Agent 协作场景下的中央编排实践
人工智能·wpf·adg·火山引擎·agent plan·adg成都社区
Vae_Mars4 天前
WPF中的Lazy<T>使用方法
wpf