不修改模板的前提下修改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;
}
  

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

这是一个老问题,在设置附加属性的时候,元素可能并没有加载完,这时候是没有第一个子元素的,所以要用一个内部方法或者内部的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

原文地址:https://www.cnblogs.com/blue-fire/p/10009139.html

时间: 2024-10-11 10:41:55

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

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

在我们平常想要获取字典中value最大或者最小的值的时候,常常使用如下函数: testDict = {"age1":18,"age2":20,"age2":6,"age2":100} v1 = max(testDict.values()) print(v1) #打印结果为100 这样已经达到了获取最大值的目的,但是这样就丢失了key.要如何保留key呢,这就需要用到zip函数 zip函数的作用是将两个序列以顺序对应起来,最后生

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

现在的需求是:下拉框中要是选择加盟商让其继续选择学校,要是选择平台管理员则不需要选择学校.隐藏选择下拉列表. 选择枚举值: /// <summary> /// 平台角色 /// </summary> public enum AdministratorRole { [Display(Name = "平台管理员")] PlatformAdministrator = 1, [Display(Name = "加盟商")] JoiningTrader

如果忘记思科路由器的特权密码,怎样在不损坏配置文件的前提下修改密码

第一步:假设我们忘记了特权模式的密码我们需要对思科路由器断电重启,如图所示: 在重新启动的过程中我们必须在重启完成之前输入ctril+c或者是ctril+break进入ROM模式. 第二步:我们要输入rommon1>confreg 0x2142 忽略NARAM中的配置文件. 第三步:输入rommon2>reset  重启系统. 第四步:Continue with configuration dialog?[yes/no]:no   手工配置系统. 第五步:Router>enable 进入

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

修改的用户都以root为列.一.拥有原来的myql的root的密码: 方法一:在mysql系统外,使用mysqladmin# mysqladmin -u root -p password "test123"Enter password: [输入原来的密码] 方法二:通过登录mysql系统,# mysql -uroot -pEnter password: [输入原来的密码]mysql>use mysql;mysql> update user set password=pass

Jmeter请求响应后的数据截取特定数据并修改特定参数再下一请求中作为入参使用

1.查询用户信息,出参中包含用户id 使用jsonPath提取出用户id 2.获取任务详情,出参信息列表list要在第三步任务处理中做入参使用,但是要要修改list中的数据(如上一步提取的id) 使用beanShell PostProcessor提取获取任务详情参数并修改其中的值 3.处理任务 处理任务的入参为第二步修改后的出参,即"var_data_obj",直接在地散步引用即可: 原文地址:https://www.cnblogs.com/cjy-blog/p/10293718.ht

js下读取input中的value值

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

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

JavaScript获取select下拉框中的第一个值 1.说明 获取select下拉框中的第一个值 2.实现源代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtm

不修改用户密码的前提下,解锁用户

不修改用户密码的前提下,解锁用户 1.0需求:某用户通知,无法登陆,用户被锁定,但是密码不知道 或者 不告诉你 1.1:用户被锁定:几种可能性 A用户使用默认Pfile概要文件,其中参数: -- PASSWORD_LIFE_TIME 180          密码有效保留时间 B用户使用默认Pfile概要文件,其中参数: -- FAILED_LOGIN_ATTEMPTS 10        登录失败后,允许尝试登录的次数 -- PASSWORD_LOCK_TIME   1      登录失败后,

CentOS单用户模式下修改ROOT密码和grub加密

Linux 系统处于正常状态时,服务器主机开机(或重新启动)后,能够由系统引导器程序自动引导 Linux 系统启动到多用户模式,并提供正常的网络服务.如果系统管理员需要进行系统维护或系统出现启动异常时,就需要进入单用户模式或修复模式对系统进行管理了. 使用单用户模式有一个前提,就是您的系统引导器(grub)能正常工作,否则要进行系统维护就要使用修复模式. 特注:进入单用户模式,没有开启网络服务,不支持远程连接 Linux 系统中不同的运行级别(Run Level)代表了系统的不同运行状态,例如