原文链接:不修改模板的前提下修改VisualState中的某些值 - 超威蓝火

UWP里有一件非常令人不爽的事,大部分控件只提供了Normal状态下的Background,Foreground,BorderBrush,而控件一般至少具有Normal、PointerOver、Pressed、Disabled,ItemContainerStyle还有Selected、PointerOverSelected、PressedSelected这几种。那么常规方法怎么修改这几个状态内的值呢?

当然是贴一遍又臭又长的Style。

那如果有很多不是很一样的控件,除了修改模板或者自定义一个控件之外,有没有办法修改状态内的值呢?

答案是肯定的。我们可以通过某些方法拿到VisualStateGroup对象,然后操作里面的Storyboard。

首先我们需要一个获取VisualStateGroup的方法,这玩意儿藏在Style中的Template中的第一个子元素里,而这个子元素会在需要的元素ApplyTemplate后,通过当猴子(爬树)得到:

public static Task<VisualStateGroup> GetCommonStates(this FrameworkElement element)
{
var vGroup = VisualStateManager.GetVisualStateGroups(element)?.FirstOrDefault(x => x.Name == "CommonStates");
var resultSource = new TaskCompletionSource<VisualStateGroup>(); if (vGroup == null)
{
if (element.GetFirstChild() is FrameworkElement ele)
{
element = ele;
vGroup = VisualStateManager.GetVisualStateGroups(element)?.FirstOrDefault(x => x.Name == "CommonStates");
}
else if (!element.IsLoaded())
{
void Element_Loaded(object sender, RoutedEventArgs e)
{
element.Loaded -= Element_Loaded;
vGroup = VisualStateManager.GetVisualStateGroups(element)?.FirstOrDefault(x => x.Name == "CommonStates");
if (vGroup == null)
{
if (element.GetFirstChild() is FrameworkElement ele2)
{
element = ele2;
vGroup = VisualStateManager.GetVisualStateGroups(element)?.FirstOrDefault(x => x.Name == "CommonStates");
}
}
resultSource.SetResult(vGroup);
}
element.Loaded += Element_Loaded;
}
else
{
return null;
}
}
else
{
resultSource.SetResult(vGroup);
}
return resultSource.Task;
}

这是一个老问题,在设置附加属性的时候,元素可能并没有加载完,这时候是没有第一个子元素的,所以要用一个内部方法或者内部的RouteEventHandler挂到Loaded上去获取。内部是因为要共享变量,而且要在进入Loaded事件之后卸载掉这个方法。

接下来我们要从CommonStates中获取Pressed和PointerOver这两个State:

 var commonStates = await ele.GetCommonStates();

 if (commonStates != null)
{
var storyboard = commonStates.States.FirstOrDefault(x => x.Name == "PointerOver")?.Storyboard;
if (storyboard != null)
{
var list = storyboard.Children.Where(x => BackgroundNames.Contains(Storyboard.GetTargetName(x).ToLowerInvariant()) && Storyboard.GetTargetProperty(x) == "Background"); foreach (var item in list)
{
item.SetAnimationValue(a.NewValue);
}
}
}

这样就大功告成了。

使用方法如下:

xmlns:helper="using:PointerStateHelper.Helpers"

<Button HorizontalAlignment="Center" VerticalAlignment="Center"
helper:PointerOverHelper.Background="Red" helper:PointerOverHelper.Foreground="Blue" helper:PointerOverHelper.BorderBrush="Transparent"
helper:PressedHelper.Background="Green" helper:PressedHelper.Foreground="Gray" helper:PressedHelper.BorderBrush="Transparent"
Content="哈哈哈" Padding="20,10" />

github:https://github.com/cnbluefire/PointerStateHelper

不修改模板的前提下修改VisualState中的某些值的更多相关文章

  1. 保留键的情况下取字典中最大的值(max\zip函数的联合使用)

    在我们平常想要获取字典中value最大或者最小的值的时候,常常使用如下函数: testDict = {"age1":18,"age2":20,"age ...

  2. MVC下 把数据库中的byte[]值保存成图片,并显示在view页面

    MVC下 把数据库中的byte[]值转成图片,并显示在view页面 controller中的action方法 //显示图片[AllowAnonymous]public ActionResult Sho ...

  3. 利用js取到下拉框中选择的值

    现在的需求是:下拉框中要是选择加盟商让其继续选择学校,要是选择平台管理员则不需要选择学校.隐藏选择下拉列表. 选择枚举值: /// <summary> /// 平台角色 /// </ ...

  4. 【修改密码】Linux下修改Mysql的用户(root)的密码

    修改的用户都以root为列.一.拥有原来的myql的root的密码: 方法一:在mysql系统外,使用mysqladmin# mysqladmin -u root -p password " ...

  5. 在无修改权限的情况下修改文件hosts中的内容

    今天遇到了一个问题,本来希望修改hosts中的内容,但保存时被告知无权限,网上搜索有很多方法都无效,最后搜到一个简单的方法:将hosts文件复制到桌面上,修改,然后覆盖原来位置的hosts文件即可!

  6. 如何在某些情况下禁止提交Select下拉框中的默认值或者第一个值(默认选中的就是第一个值啦……)

    群里有个帅哥问了这么个问题,他的下拉框刚进页面时是隐藏起来的,但是是有值的,为啥呢?因为下拉框默认选中了第一个值呗,,, 所以提交数据的时候就尴尬啦,明明没有选,但是还是有值滴.怎么办呢? 一开始看到 ...

  7. js下读取input中的value值

    很多人(包括我),总想像以前操作js一样,读取到input中的值:document.getElementById('').value; 结果事实证明这样读到得是null. eval(document. ...

  8. jquery获取下拉框中的循环值

    <select class="test" id="projectno" name="projectno"> <option ...

  9. JavaScript获取select下拉框中的第一个值

    JavaScript获取select下拉框中的第一个值 1.说明 获取select下拉框中的第一个值 2.实现源码 <!DOCTYPE html PUBLIC "-//W3C//DTD ...

随机推荐

  1. RedHat 7.0更新升级openSSH7.4p1

    由于目前服务器上ssh版本较低,存在安全漏洞,需要升级到最新版本. 系统版本:RedHat 7.0 旧openSSH版本:6.4p1 新openSSH版本:7.4p1 升级方式:源码安装 安装操作步骤 ...

  2. vue 时间过滤

    1.过滤13位时间戳(以评论时间为例) filters : { formattime2: function (value) { //value为13位的时间戳 var timestamp = Date ...

  3. 项目(四)DHCP服务配置

    DHCP是由Internet工作任务小组设计开发的,专门用于为TCP/IP网络中的计算机自动分配TCP/IP参数的协议. 使用DHCP可以减少管理员的工作量,避免IP地址冲突,当网络修改IP地址网段时 ...

  4. 云笔记项目-笔记列表弹出"分享移动删除"子菜单

    业务需求: 笔记列表里还有一个按钮可以弹出子菜单,要求做到以下几点: (1)点击选中的笔记行的弹出按钮后,弹出子菜单,再次点击,子菜单收回. (2)选中其他笔记后,子菜单消失.效果如下图所示: 业务分 ...

  5. vue.js核心最基本的功能

    Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统: , text: , text: , text: '随便其它什么人吃的东西' } ] }}) 蔬菜 奶酪 随便其 ...

  6. Python SMTP发送邮件

    import smtplibfrom email.mime.text import MIMEText  # 引入smtplib和MIMEText host = 'smtp.163.com'  # 设置 ...

  7. mybatis中查询使用#{}和${}的区别

    ${}中的变量什么值,就会简单的替代变量,不会做处理 比如delete * from tb_label where name=${labelname} 如果labelname的值是 something ...

  8. Java中CountDownLatch和CyclicBarrier

    Java编程思想中的例子import javax.validation.constraints.Size; import java.util.Random; import java.util.conc ...

  9. java基础 ----- 循环结构

    循环的结构特点 :    循环条件   循环操作 -----     while 循环 来个小例子,实现打印50 份shij 1.确定循环条件和循环操作 2.套用while语法写出代码 3.检查循环能 ...

  10. 153. Find Minimum in Rotated Sorted Array找其中的最小值

    [抄题]: [暴力解法]: 时间分析: 空间分析: [优化后]: 时间分析: 空间分析: [奇葩输出条件]: [奇葩corner case]: [思维问题]: 总算自己写出一道题来了. [英文数据结构 ...