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)。 大多数控件都有两个状态组:CommonStates和 FocusStates。
在应用于控件的每个状态组中,控件始终处于每个组的一种状态。但是,控件不能处于同一组中的两种不同状态。
完整的状态可以参照下表:
| 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 方法。
示例代码
相关文章:
WPF中的VisualState(视觉状态)
以前在设置控件样式或自定义控件时,都是使用触发器来进行样式更改。触发器可以在属性值发生更改时启动操作。 像这样: <Style TargetType"ListBoxItem"><Setter Property"Opacity" Value"0.5" /><Setter …...
C#设计模式--状态模式(State Pattern)
状态模式是一种行为设计模式,它允许对象在其内部状态发生变化时改变其行为。这种模式的核心思想是将状态封装在独立的对象中,而不是将状态逻辑散布在整个程序中。 用途 简化复杂的条件逻辑:通过将不同的状态封装在不同的类中,可…...
〔 MySQL 〕索引
目录 1. 没有索引,可能会有什么问题 2. 认识磁盘 MySQL与存储 先来研究一下磁盘: 在看看磁盘中一个盘片编辑 扇区 定位扇区编辑 结论 磁盘随机访问(Random Access)与连续访问(Sequential Access) 3. MySQL 与磁盘交互基本单位 4. 建立共识…...
计算机网络研究实训室建设方案
一、概述 本方案旨在规划并实施一个先进的计算机网络研究实训室,旨在为学生提供一个深入学习、实践和研究网络技术的平台。实训室将集教学、实验、研究于一体,覆盖网络基础、网络架构、网络安全、网络管理等多个领域,以培养具备扎实理论基础…...
韩企研学团造访图为科技:共探人工智能创新前沿
今日,一支由韩国知名企业研学专家组成的代表团莅临图为科技深圳总部,展开了一场深度技术交流与研讨活动。 此次访问旨在通过实地探访中国领先的科技企业,促进中韩两国在科技创新领域的深入合作与交流。 韩国游学团合影 图为科技作为一家在人…...
html button 按钮单选且 高亮
<DIV class"middle"> <div class"containerTarget"> <span class"hover-target1" οnclick"btn(1);">韵达 </span> <span class"hover-target2" οnclick"btn(2);">中通 </span…...
图片上传HTML
alioss sky:jwt:# 设置jwt签名加密时使用的秘钥admin-secret-key: itcast# 设置jwt过期时间admin-ttl: 7200000# 设置前端传递过来的令牌名称admin-token-name: tokenalioss:endpoint: ${sky.alioss.endpoint}access-key-id: ${sky.alioss.access-key-id}access-key-secret: $…...
C++学习-函数
C 函数 目录 函数默认参数引用传参函数重载 数量不同类型不同 内联函数 函数默认参数 #include<iostream>using std::cout; using std::endl;int power(int n, int x2); // x2 是默认参数int main() {cout << power(5) << endl; // 没有传 x 的值&#x…...
spring boot 测试 mybatis mapper类
spring boot 测试 mybatis mapper类 针对 mybatis plus不启动 webserver指定加载 xml 【过滤 “classpath*:/mapper/**/*.xml” 下的xml】, mapper xml文件名和mapper java文件名称要一样,是根据文件名称过滤的。默认情况加载和解析所有mapper.xml 自定义 MapperT…...
远程游戏新体验!
在这个数字化的时代,游戏已经不仅限于家里的电视或书房的电脑了。远程游戏,也就是通过远程控制软件在不同地点操作游戏设备,给玩家带来了前所未有的自由和灵活性。RayLink远程控制软件,凭借其出色的性能和专为游戏设计的功能&…...
Let up bring up a linux.part2 [十一]
之前的篇幅中我们已经将 Linux 内核 bringup 起来了,不知道大家有没有去尝试将根文件系统运行起来,今天我就带领大家完成这个事情,可以跟着下面的步骤一步步来完成: 在这里我们使用 busybox 构建 rootfs: 下载 busyb…...
调用大模型api 批量处理图像 保存到excel
最近需要调用大模型,并将结果保存到excel中,效果如下: 代码: import base64 from zhipuai import ZhipuAI import os import pandas as pd from openpyxl import Workbook from openpyxl.drawing.image import Image from io i…...
使用 Flownex 模拟热环境对原油运输的影响
石油和天然气行业经常使用管道仿真来模拟原油的流动。为了准确估计管道容量,必须考虑环境对管道的热影响以及环境温度如何影响油品特性。本博客介绍了如何通过将传热元件集成到管道流网中,以及使用新的工作液材料 Flownex 来模拟各种传热机制。 使用 Fl…...
【WRF-Urban】WPS中有关Urban的变量设置
【WRF-Urban】WPS中有关Urban的变量设置 地理数据源的配置WRF-Urban所需静态地理数据1、LANDUSE:包含城市地表分类的土地利用数据。2、URB_PARAM:城市参数数据集。3、FRC_URB2D:城市覆盖度数据集WRF默认设置(美国)数据集1-National urban dataset in China NUDC(中国)数…...
Socket编程-tcp
1. 前言 在tcp套接字编程这里,我们将完成两份代码,一份是基于tcp实现普通的对话,另一份加上业务,client输入要执行的命令,server将执行结果返回给client 2. tcp_echo_server 与udp类似,前两步࿱…...
Redis 之持久化
目录 介绍 RDB RDB生成方式 自动触发 手动触发 AOF(append-only file) Redis 4.0 混合持久化 Redis主从工作原理 总结 介绍 Redis提供了两个持久化数据的能力,RDB Snapshot 和 AOF(Append Only FIle)…...
视频监控汇聚平台:Liveweb安防监控平台实现接入监控视频集中管理方案
随着各行业数字化转型的不断推进,视频监控技术在行业内的安防应用及管理支撑日益增多。然而,由于前期规划不清晰、管理不到位等问题,视频监管系统普遍存在以下问题: 1. 各部门单位在视频平台建设中以所属领域为单位,导…...
ABAP - 系统集成之SAP的数据同步到OA(泛微E9)服务器数据库
需求背景 项目经理说每次OA下单都需要调用一次SAP的接口获取数据,导致效率太慢了,能否把SAP的数据保存到OA的数据库表里,这样OA可以直接从数据库表里获取数据效率快很多。思来想去,提供了两个方案。 在集群SAP节点下增加一个SQL S…...
uniapp使用ucharts修改Y、X轴标题超出换行
找到ucharts里面的u-charts.js。 Y轴的话找到drawYAxis方法。然后找到方法里面绘制文字的context.fillText方法。先把这个代码注释掉,然后加上下面代码 let labelLines item.split(\n); let currentY pos yAxisFontSize / 2 - 3 * opts.pix; labelLines.forEac…...
三分钟详细解读什么是Ecovadis认证?
Ecovadis认证,这一源自法国的全球性企业可持续性评估体系,宛如一面明镜,映照出企业在环境、社会和治理(ESG)领域的真实面貌。它不仅仅是一项简单的认证,更是一个推动全球企业和供应链向更加绿色、公正、透明…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
