原文链接:不修改模板的前提下修改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. 子页面调整父亲页面的iframe元素

    $('iframe', parent.document).attr('scrolling','no');

  2. python 爬虫启航2.0

    文章解析: 1.正则表达式解析 2.beautifulsoup,BeautifulSoup是一个复杂的树形结构,她的每一个节点都是一个python对象,获取网页的内容就是一个提取对象内容的过程,它的提 ...

  3. YAML基本语法

    正如YAML所表示的YAML Ain’t Markup Language,YAML /ˈjæməl/ 是一种简洁的非标记语言.YAML以数据为中心,使用空白,缩进,分行组织数据,从而使得表示更加简洁易 ...

  4. spring mvc返回json格式和json字符串

    首先有必要说一下,json和json字符串是不一样的,后者是一个字符串.而json是一个对象 当然如果调用位置是后台程序这几乎没有区别,因为在后台,无论什么格式数据,都是从响应流中读取字符串. 但是在 ...

  5. [Ting's笔记Day5]在部署到Heroku之前,将Rails项目从SQLite设定为PostgreSQL

    前情提要: Paas(平台及服务)公司Heroku是个可以把我们写好的App部署到网际网络的好地方.而本篇是我从自己的上一篇文章:将Ruby on Rails项目部署到Heroku遇到的问题,当时困扰 ...

  6. H5学习的例子

    https://github.com/NalvyBoo/HTML5   https://github.com/yujinjin/fans   github看到这里 https://github.com ...

  7. django mysql 数据库配置

    在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用sqlite数据库. DATABASES = { 'default': { 'ENGINE': 'django.db. ...

  8. 用<pre>预格式化的文本

    被包围在 <pre> 标签 元素中的文本通常会保留空格和换行符.而文本也会呈现为等宽字体. 提示: <pre> 标签的一个常见应用就是用来表示计算机的源代码.

  9. js的一些总结

    函数 函数是一等公民 函数可以有属性,并且能连接到它的构造方法 函数可以像一个变量一样存在内存中 函数可以当做参数传给其他函数 函数可以返回其他函数 加法操作表 Number + Number -&g ...

  10. Linq的执行效率及优化

    描述:项目中使用了linq,发现写的顺序不一样最后的结果也不一样,效率也不一样. Linq的执行效率对比 List<int> source = new List<int>(); ...