背水一戰 Windows 10 (67) - 控制項(控制項基類): DependencyObject - CoreDispatcher, 依賴屬性的設置與獲取, 依賴屬性的變化回調

来源:http://www.cnblogs.com/webabcd/archive/2017/10/09/7639572.html
-Advertisement-
Play Games

背水一戰 Windows 10 之 控制項(控制項基類): CoreDispatcher, 依賴屬性的設置與獲取, 依賴屬性的變化回調 ...


[源碼下載]


背水一戰 Windows 10 (67) - 控制項(控制項基類): DependencyObject - CoreDispatcher, 依賴屬性的設置與獲取, 依賴屬性的變化回調



作者:webabcd


介紹
背水一戰 Windows 10 之 控制項(控制項基類)

  • CoreDispatcher
  • 依賴屬性的設置與獲取
  • 依賴屬性的變化回調



示例
1、演示 CoreDispatcher 的應用
Controls/BaseControl/DependencyObjectDemo/CoreDispatcherDemo.xaml

<Page
    x:Class="Windows10.Controls.BaseControl.DependencyObjectDemo.CoreDispatcherDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Controls.BaseControl.DependencyObjectDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <TextBlock Name="lblMsg1" Margin="5" />

            <TextBlock Name="lblMsg2" Margin="5" />

            <TextBlock Name="lblMsg3" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Controls/BaseControl/DependencyObjectDemo/CoreDispatcherDemo.xaml.cs

/*
 * DependencyObject - 依賴對象(可以在 DependencyObject 上定義 DependencyProperty)
 *     Dispatcher - 獲取 CoreDispatcher 對象
 *     
 *     
 * CoreDispatcher - 核心調度器
 *     CurrentPriority - 獲取或設置當前任務的優先順序(CoreDispatcherPriority 枚舉)
 *     HasThreadAccess - 獲取一個值,用於說明當前線程是否可更新此 CoreDispatcher 線程上的 UI
 *     RunAsync(), RunIdleAsync(), TryRunAsync(), TryRunIdleAsync() - 在此 CoreDispatcher 線程上使用指定的優先順序執行指定的方法(一般用於更新 CoreDispatcher 線程上的 UI)
 *     ShouldYield() - 用於獲知當前任務隊列中是否存在更高優先順序的任務,或指定的優先順序及其以上的任務
 *     AcceleratorKeyActivated - 有按鍵操作時觸發的事件(針對 UIElement 的鍵盤事件監聽請參見:/Controls/BaseControl/UIElementDemo/KeyDemo.xaml)
 *     
 * CoreDispatcherPriority - 任務優先順序枚舉(High, Normal, Low, Idle)
 * 
 * 在 UWP 中優先順序從高到低的排序如下
 * 1、本地代碼中的 SendMessage
 * 2、CoreDispatcherPriority.High
 * 3、CoreDispatcherPriority.Normal
 * 4、所有設備輸入消息
 * 5、CoreDispatcherPriority.Low
 * 6、CoreDispatcherPriority.Idle(一般用於後臺任務)
 * 
 * 
 * 本例用於演示 DependencyObject 的 Dispatcher(CoreDispatcher 類型) 的應用
 */

using System;
using System.Threading;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Windows10.Controls.BaseControl.DependencyObjectDemo
{
    public sealed partial class CoreDispatcherDemo : Page
    {
        public CoreDispatcherDemo()
        {
            this.InitializeComponent();

            this.Loaded += CoreDispatcherDemo_Loaded;

            // 監聽按鍵事件
            Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated;
        }

        private void CoreDispatcherDemo_Loaded(object sender, RoutedEventArgs e)
        {
            Timer timer =  new Timer((p) => 
            {
                // 當前線程是否可修改 CoreDispatcher 上的 UI
                if (base.Dispatcher.HasThreadAccess)
                {
                    lblMsg1.Text = "相同線程 " + DateTime.Now.ToString("mm:ss");
                }
                else
                {
                    // 非 UI 線程通過 CoreDispatcher 更新 UI
                    var ignored = base.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                    {
                        lblMsg1.Text = "不同線程 " + DateTime.Now.ToString("mm:ss");
                    });
                }
            }, null, TimeSpan.Zero, TimeSpan.FromSeconds(1));


            DispatcherTimer dTimer = new DispatcherTimer();
            dTimer.Interval = TimeSpan.FromSeconds(1);
            dTimer.Tick += (x, y) => 
            {
                // 當前線程是否可修改 Dispatcher 上的 UI
                if (base.Dispatcher.HasThreadAccess)
                {
                    lblMsg2.Text = "相同線程 " + DateTime.Now.ToString("mm:ss");
                }
                else
                {
                    // 非 UI 線程通過 CoreDispatcher 更新 UI
                    var ignored = base.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                    {
                        lblMsg2.Text = "不同線程 " + DateTime.Now.ToString("mm:ss");
                    });
                }
            };
            dTimer.Start();
        }

        private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args)
        {
            /*
             * AcceleratorKeyEventArgs - 按鍵事件參數
             *     EventType - 事件類型(比如 KeyDown, KeyUp 之類的,詳細參見 CoreAcceleratorKeyEventType 枚舉)
             *     VirtualKey - 按鍵枚舉(比如 A, B, C, D, LeftControl 之類的,詳細參見 VirtualKey 枚舉)
             *     KeyStatus - 按鍵的狀態(一個 CorePhysicalKeyStatus 類型的對象,有好多欄位,詳細參見文檔)
             */

            lblMsg3.Text += $"EventType:{args.EventType}, VirtualKey:{args.VirtualKey}, IsExtendedKey:{args.KeyStatus.IsExtendedKey}, IsKeyReleased:{args.KeyStatus.IsKeyReleased}, IsMenuKeyDown:{args.KeyStatus.IsMenuKeyDown}, RepeatCount:{args.KeyStatus.RepeatCount}, ScanCode:{args.KeyStatus.ScanCode}, WasKeyDown:{args.KeyStatus.WasKeyDown}";
            lblMsg3.Text += Environment.NewLine;

            // 屏蔽系統對按鍵的處理
            args.Handled = true;
        }
    }
}


2、演示依賴屬性的設置與獲取
Controls/BaseControl/DependencyObjectDemo/DependencyPropertyDemo.xaml

    <Page
    x:Class="Windows10.Controls.BaseControl.DependencyObjectDemo.DependencyPropertyDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Controls.BaseControl.DependencyObjectDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <Rectangle Name="rect1" Height="50" Fill="Red" HorizontalAlignment="Left" Margin="5" />

            <Rectangle Name="rect2" Height="50" Fill="Red" HorizontalAlignment="Left" Margin="5" />

            <Rectangle Name="rect3" Height="50" Fill="Red" HorizontalAlignment="Left" Margin="5" />

            <Rectangle Name="rect4" Width="400" Height="50" Fill="Red" Margin="5" />

            <Button Name="button" Content="點我" Click="button_Click" Margin="5" />

            <TextBlock Name="lblMsg" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Controls/BaseControl/DependencyObjectDemo/DependencyPropertyDemo.xaml.cs

/*
 * DependencyObject - 依賴對象(可以在 DependencyObject 上定義 DependencyProperty)
 *     SetValue(DependencyProperty dp, object value) - 設置依賴屬性的值
 *     ClearValue(DependencyProperty dp) - 清除依賴屬性的值
 *     GetValue(DependencyProperty dp) - 獲取依賴屬性的當前值
 *     GetAnimationBaseValue(DependencyProperty dp) - 獲取依賴屬性的基值
 *     ReadLocalValue(DependencyProperty dp) - 獲取依賴屬性的本地值
 *     
 *     
 * 本例用於演示 DependencyObject 的依賴屬性的設置與獲取
 */

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Shapes;

namespace Windows10.Controls.BaseControl.DependencyObjectDemo
{
    public sealed partial class DependencyPropertyDemo : Page
    {
        public DependencyPropertyDemo()
        {
            this.InitializeComponent();

            this.Loaded += DependencyPropertyDemo_Loaded;
        }

        private void DependencyPropertyDemo_Loaded(object sender, RoutedEventArgs e)
        {
            // 直接設置依賴屬性(rect1.Width = 400; 其實調用的就是這個)
            rect1.SetValue(FrameworkElement.WidthProperty, 400);


            // 直接設置依賴屬性
            rect2.SetValue(FrameworkElement.WidthProperty, 200);
            // 通過動畫的方式修改依賴屬性的值
            SetRectWidth(rect2);


            // 通過 Style 的方式設置依賴屬性
            Style style = new Style();
            style.TargetType = typeof(Rectangle);
            Setter setter = new Setter();
            setter.Property = Rectangle.WidthProperty;
            setter.Value = 200;
            style.Setters.Add(setter);
            rect3.Style = style;
            // 通過動畫的方式修改依賴屬性的值
            SetRectWidth(rect3);


            // 清除依賴屬性的值
            rect4.ClearValue(FrameworkElement.WidthProperty);
        }
        
        private void button_Click(object sender, RoutedEventArgs e)
        {
            DependencyProperty dp = FrameworkElement.WidthProperty;

            // 通過 SetValue 設置依賴屬性後,再通過 GetValue, GetAnimationBaseValue, ReadLocalValue 取出的值和設置的值都是一樣的
            lblMsg.Text = $"rect1 GetValue:{rect1.GetValue(dp)}, GetAnimationBaseValue:{rect1.GetAnimationBaseValue(dp)}, ReadLocalValue:{rect1.ReadLocalValue(dp)}";
            lblMsg.Text += Environment.NewLine;

            // 通過 SetValue 設置依賴屬性後,再通過動畫的方式修改其值
            // GetValue - 獲取當前值
            // GetAnimationBaseValue - 獲取基值,也就是動畫之前的值
            // ReadLocalValue - 獲取本地值,即通過 SetValue 或者資源或者綁定設置的值
            lblMsg.Text += $"rect2 GetValue:{rect2.GetValue(dp)}, GetAnimationBaseValue:{rect2.GetAnimationBaseValue(dp)}, ReadLocalValue:{rect2.ReadLocalValue(dp)}";
            lblMsg.Text += Environment.NewLine;

            // 通過 Style 設置依賴屬性後,再通過動畫的方式修改其值
            // GetValue - 獲取當前值
            // GetAnimationBaseValue - 獲取基值,也就是動畫之前的值
            // ReadLocalValue - 獲取本地值,即通過 SetValue 或者資源或者綁定設置的值(如果是通過其他方式,比如 Style 方式設置的值,則無本地值)
            lblMsg.Text += $"rect3 GetValue:{rect3.GetValue(dp)}, GetAnimationBaseValue:{rect3.GetAnimationBaseValue(dp)}, ReadLocalValue:{rect3.ReadLocalValue(dp)}";
            lblMsg.Text += Environment.NewLine;

            // 通過 ClearValue 清除了依賴屬性的值,則再通過 GetValue, GetAnimationBaseValue, ReadLocalValue 均無法獲取到值
            lblMsg.Text += $"rect4 GetValue:{rect4.GetValue(dp)}, GetAnimationBaseValue:{rect4.GetAnimationBaseValue(dp)}, ReadLocalValue:{rect4.ReadLocalValue(dp)}, ActualWidth:{rect4.ActualWidth}";
        }


        private void SetRectWidth(Rectangle rect)
        {
            DoubleAnimation da = new DoubleAnimation();
            da.EnableDependentAnimation = true;
            da.BeginTime = TimeSpan.Zero;
            da.To = 400;
            da.Duration = TimeSpan.FromSeconds(5);
            Storyboard.SetTarget(da, rect);
            Storyboard.SetTargetProperty(da, nameof(rect.Width));

            Storyboard sb = new Storyboard();
            sb.Children.Add(da);
            sb.Begin();
        }
    }
}


3、演示如何監聽依賴屬性的變化
Controls/BaseControl/DependencyObjectDemo/RegisterPropertyChangedCallbackDemo.xaml

<Page
    x:Class="Windows10.Controls.BaseControl.DependencyObjectDemo.RegisterPropertyChangedCallbackDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Controls.BaseControl.DependencyObjectDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <Grid.Resources>
            <BeginStoryboard x:Name="sb">
                <Storyboard>
                    <DoubleAnimation 
                        EnableDependentAnimation="True"
                        Storyboard.TargetName="rect1" 
                        Storyboard.TargetProperty="Width" 
                        From="0" 
                        To="200" 
                        Duration="0:0:3">
                    </DoubleAnimation>
                </Storyboard>
            </BeginStoryboard>
        </Grid.Resources>
        
        <StackPanel Margin="10 0 10 10">

            <Rectangle Name="rect1" Height="50" Fill="Red" HorizontalAlignment="Left" Margin="5" />

            <TextBlock Name="lblMsg" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Controls/BaseControl/DependencyObjectDemo/RegisterPropertyChangedCallbackDemo.xaml.cs

/*
 * DependencyObject - 依賴對象(可以在 DependencyObject 上定義 DependencyProperty)
 *     RegisterPropertyChangedCallback() - 為指定的依賴屬性註冊一個變化回調
 *     UnregisterPropertyChangedCallback() - 取消 RegisterPropertyChangedCallback() 的註冊
 *     
 * 
 * 本例用於演示如何監聽 DependencyObject 的依賴屬性的變化
 */

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;

namespace Windows10.Controls.BaseControl.DependencyObjectDemo
{
    public sealed partial class RegisterPropertyChangedCallbackDemo : Page
    {
        private long _token = -1;

        public RegisterPropertyChangedCallbackDemo()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // 為 WidthProperty 註冊一個變化回調(返回值是一個 token 用於取消註冊用)
            _token = rect1.RegisterPropertyChangedCallback(Rectangle.WidthProperty, WidthChanged);
            
            base.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // 為 WidthProperty 取消指定的變化回調(通過 token 來指定取消的是哪個變化回調)
            rect1.UnregisterPropertyChangedCallback(Rectangle.WidthProperty, _token);

            base.OnNavigatedFrom(e);
        }
        
        private void WidthChanged(DependencyObject sender, DependencyProperty prop)
        {
            double width = (double)sender.GetValue(prop);

            lblMsg.Text = $"width: {width}";
        }
    }
}



OK
[源碼下載]


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

-Advertisement-
Play Games
更多相關文章
  • 在數值字元串的格式化中有很多格式化的格式,比如:用"C"表示貨幣格式,用"P"表示百分比格式,FCL中支持多種格式化字元串的方式。有時候我們會把一個數值轉換成string類型,然後再從string類型轉換成數值類型,這時候就要考慮轉換回來後的數值會不會和原來的相等呢? 首先的一種情況: 使用G常規格 ...
  • 基於ffmpeg和虹軟人臉識別庫的C#開源實現,對虹軟人臉識別庫進行了包裝,便於在C#中快速、安全的調用識別函數。同時,開源代碼中,包含完整的實現示例。 ...
  • 本篇作為技術分享系列的第四篇,詳細講一下手繪視頻中 Surface Pen 和 Surface Dial 的使用場景。 先放一張微軟官方商城的圖,Surface 的使用中結合了 Surface Pen 和 Surface Dial。 Surface Pen 的使用場景不難想象,就像 iPad 和 A ...
  • DataRead 和DataSet區別 dataset表示一個數據集,是數據在記憶體中的緩存。 可以包括多個表DatSet 連接資料庫時是非面向連接的。把表全部讀到Sql中的緩衝池,並斷開於資料庫的連接 datareader 連接資料庫時是面向連接的。讀表時,只能向前讀取,讀完數據後有用戶決定是否斷開 ...
  • C# 的集合類型中, 都有Synchronized靜態方法, 和SyncRoot實例方法 對於ArrayList以及Hashtable 集合類來講,當需要做到線程安全的時候,最好利用其自帶的屬性SyncRoot 來做到,儘管也可以使用其Synchronized()方法來實現,但是使用屬性會更好。 線 ...
  • XAML代碼: <local:WorkSpaceContent x:Class="SunCreate.CombatPlatform.Client.NoticeMarquee" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentati ...
  • 1. 引言 對於ASP.NET Core應用程式來說,我們要記住非常重要的一點是:其本質上是一個獨立的控制台應用,它並不是必需在IIS內部托管且並不需要IIS來啟動運行(而這正是ASP.NET Core跨平臺的基石)。ASP.NET Core應用程式擁有一個內置的 Self Hosted(自托管) ...
  • 在我們的很多框架或者項目應用中,緩存在一定程度上可以提高程式的響應速度,以及減輕伺服器的承載壓力,因此在一些地方我們都考慮引入緩存模塊,這篇隨筆介紹使用開源緩存框架CacheManager來實現數據的緩存,在微信開發框架中,我們有一些常用的處理也需要應用到緩存,因此本隨筆以微信框架為例介紹緩存的實際... ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...