不修改模板的前提下修改VisualState中的某些值

来源:https://www.cnblogs.com/blue-fire/archive/2018/11/23/10009139.html
-Advertisement-
Play Games

UWP里有一件非常令人不爽的事,大部分控制項只提供了Normal狀態下的Background,Foreground,BorderBrush,而控制項一般至少具有Normal、PointerOver、Pressed、Disabled,ItemContainerStyle還有Selected、Pointer ...


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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、什麼是中間件 請求和響應之間的一道屏障 作用:控制請求和響應 Django預設的中間件 :(在django項目的setting模塊中,有一個 MIDDLEWARE_CLASS變數,其中每一個元素就是一個中間件 ) 每一個中間件都有具體的功能 二 、自定義中間件 中間件主要有幾個方法: 中間件執行 ...
  • 安裝依賴環境 下載python3 centos系統下安裝 安裝python3 報錯處理 ...
  • 第一階段 (J2SE java基礎部分 ) 1. java開發前奏 a.Java語言發展簡史以及開發環境的搭建,體驗Java程式的開發,環境變數的設置,程式的執行過程,b. 相關反編譯工具介紹,java開發工具Eclipse的安裝和使用,javadoc的說明。2.Java基礎語法 a.ava語法格式 ...
  • 一、快速準備 SSM 框架即 Spring 框架、SpringMVC 框架、MyBatis 框架,關於這幾個框架的基礎和入門程式,我前面已經寫過幾篇文章作為基礎和入門介紹了。這裡再簡單的介紹一下: 1.Spring Spring 框架是 Java 應用最廣的框架,它的成功來源於理念,而不是技術本身, ...
  • 安裝pip3: 這個簡單啊,到網上下載get-pip.py的腳本,然後scp到你的阿裡雲伺服器上,python3 get-pip.py即可。 如果不會scp,哈哈,按照下麵的幾步: ...
  • Infi-chu: http://www.cnblogs.com/Infi-chu/ ...
  • [外包]!採用asp.net core 快速構建小型創業公司後臺管理系統(四.Log4Net的簡單配置) ...
  • ASP.NET Core使用Elasticsearch記錄NLog日誌 1、新建一個 ASP.NET Core項目 2、安裝Nuge包 運行:Install-Package NLog.Web.AspNetCore 運行:Install-Package NLog 運行:Install-package ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...