• 背水一战 Windows 10 (67)


    [源码下载]


    背水一战 Windows 10 (67) - 控件(控件基类): DependencyObject - CoreDispatcher, 依赖属性的设置与获取, 依赖属性的变化回调



    作者:webabcd


    介绍
    背水一战 Windows 10 之 控件(控件基类 - DependencyObject)

    • 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}";
            }
        }
    }



    OK
    [源码下载]

  • 相关阅读:
    Python正则表达式指南(转)
    二进制文件与文本文件的区分(转)
    Linux上的下载软件uGet
    Ubuntu 12.04安装Google Chrome(转)
    单元测试中的黑盒测试的重要性(转)
    尾递归(转)
    chrome使用技巧(转)
    LRU算法的Python实现
    MySQL单列索引和组合索引的区别介绍(转)
    Python性能优化(转)
  • 原文地址:https://www.cnblogs.com/webabcd/p/7639572.html
Copyright © 2020-2023  润新知