UWP开发砸手机系列(二)—— “讲述人”识别自定义控件Command

简介: 原文:UWP开发砸手机系列(二)—— “讲述人”识别自定义控件Command  上一篇我们提到如何让“讲述人”读出自定义的CanReadGrid,但“讲述人”仍然无法识别CanReadGrid上绑定的Command。
原文: UWP开发砸手机系列(二)—— “讲述人”识别自定义控件Command

  上一篇我们提到如何让“讲述人”读出自定义的CanReadGrid,但“讲述人”仍然无法识别CanReadGrid上绑定的CommandXAML代码如下:

    <StackPanel>
        <TextBlock Text="{x:Bind Title,Mode=OneWay}" Foreground="White"></TextBlock>
        <local:CanReadGrid Background="Red" AutomationProperties.Name="Can read gird" Height="100">
            <Interactivity:Interaction.Behaviors>
                <Core:EventTriggerBehavior EventName="Tapped">
                    <Core:InvokeCommandAction Command="{x:Bind ChangeTitleCommand}"/>
                </Core:EventTriggerBehavior>
            </Interactivity:Interaction.Behaviors>
        </local:CanReadGrid>
    </StackPanel>

  我们可以看到通过Behaviors绑定了Command,在Tapped事件发生时触发ChangeTitleCommand

  我们再来对比一下系统控件Button的写法:

        <Button Command="{x:Bind ChangeTitleCommand}">I am Button</Button>

  在“讲述人”模式下,点击上面这个Button按钮,“讲述人”除了会念出“I am Button Button.”这句话以外,还会补充一句“Double tap to activate.”这时双击Button将会触发ChangeTitleCommand

  其中不一样的地方无非就是Button自带有名为“Command”的,类型为ICommand的依赖属性(Dependency Property):

public System.Windows.Input.ICommand Command { get; set; }
    Member of Windows.UI.Xaml.Controls.Primitives.ButtonBase

  而我们自定义的CanReadGrid,则是通过附加属性(Attached Property)来获得绑定Command的能力。

  附件属性也是一种特殊的依赖属性,二者殊归同路。既然Button通过依赖属性可以做到的事情,附加属性一样可以完成。

  想要弄明白ButtonCommand是如何被调用的,最简单的办法就是去查看源码呗:

    public class ButtonAutomationPeer : ButtonBaseAutomationPeer, IInvokeProvider
    {
        /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Automation.Peers.ButtonAutomationPeer" /> class.</summary>
        /// <param name="owner">The element associated with this automation peer.</param>
        public ButtonAutomationPeer(Button owner) : base(owner)
        {
        }

        /// <summary>Gets the name of the control that is associated with this UI Automation peer.</summary>
        /// <returns>A string that contains "Button".</returns>
        protected override string GetClassNameCore()
        {
            return "Button";
        }

        /// <summary>Gets the control type of the element that is associated with the UI Automation peer.</summary>
        /// <returns>
        ///   <see cref="F:System.Windows.Automation.Peers.AutomationControlType.Button" />.</returns>
        protected override AutomationControlType GetAutomationControlTypeCore()
        {
            return AutomationControlType.Button;
        }

        /// <summary>Gets the object that supports the specified control pattern of the element that is associated with this automation peer.</summary>
        /// <returns>If <paramref name="patternInterface" /> is <see cref="F:System.Windows.Automation.Peers.PatternInterface.Invoke" />, this method returns a this pointer, otherwise this method returns null.</returns>
        /// <param name="patternInterface">A value in the enumeration.</param>
        public override object GetPattern(PatternInterface patternInterface)
        {
            if (patternInterface == PatternInterface.Invoke)
            {
                return this;
            }
            return base.GetPattern(patternInterface);
        }

        /// <summary>This type or member supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used directly from your code.</summary>
        void IInvokeProvider.Invoke()
        {
            if (!base.IsEnabled())
            {
                throw new ElementNotEnabledException();
            }
            base.Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(delegate(object param)
            {
                ((Button)base.Owner).AutomationButtonBaseClick();
                return null;
            }), null);
        }
    }

  果不其然发现了上一篇我们提到的GetClassNameCoreGetAutomationControlTypeCoreGetPattern三个方法。另外还有一个奇怪的void IInvokeProvider.Invoke()这货看名字也能猜出来是干啥的啦,这货竟然去了Button里的Click方法……

  知道真相的我眼泪流出来……搞啥呢,那我这里调一下Command.Execute不就成了!

  首先我们给CanReadGrid添加ExecuteCommand方法,该方法通过DependencyObjectGetValue方法一层层拿到Command,然后执行Execute

    public class CanReadGrid : Grid
    {
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new GridAutomationPeer((this));
        }

        public void ExecuteCommand()
        {
            var behaviors = Interaction.GetBehaviors(this);
            var actions = behaviors[0].GetValue(EventTriggerBehavior.ActionsProperty) as ActionCollection;
            var command = actions[0].GetValue(InvokeCommandAction.CommandProperty) as ICommand;
            command.Execute(null);
        }
    }

  第二步就是完善GridAutomatioPeer,这里需要注意的是IInvokeProvider这个接口,通过Button的源码推测具有Action的控件需要实现这个接口的Invoke方法来执行操作。我们也是在Invoke方法里来调用CanReadGrid类里的ExecuteCommand方法。

    public class GridAutomationPeer : FrameworkElementAutomationPeer, IInvokeProvider
    {
        public GridAutomationPeer(Grid owner)
                : base(owner)
        {
            
        }

        public async void Invoke()
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                () =>
                {
                    ((CanReadGrid)base.Owner).ExecuteCommand();
                });
        }

        protected override object GetPatternCore(PatternInterface patternInterface)
        {
            if (patternInterface == PatternInterface.Invoke)
            {
                return this;
            }

            return null;
        }
    }

  大功告成!开启“讲述人”模式来验证成果吧!

  结尾插播个广告,本篇内容100%原创,当时俺翻烂了Google的搜索页面、中英文各种blog也木有讲如何让“讲述人”调用Command,逼的俺自由发挥啊。特地写了这篇造福全人类,各位不要吝啬点个推荐哦,虽然“讲述人”并没有什么卵用……

 

 

 

 

 

 

 

 

目录
相关文章
|
7月前
|
机器学习/深度学习 存储 人工智能
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
MNN-LLM App 是阿里巴巴基于 MNN-LLM 框架开发的 Android 应用,支持多模态交互、多种主流模型选择、离线运行及性能优化。
5285 80
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
|
7月前
|
存储 算法 API
【01】整体试验思路,如何在有UID的情况下获得用户手机号信息,python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
【01】整体试验思路,如何在有UID的情况下获得用户手机号信息,python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
1137 82
|
7月前
|
存储 人工智能 编译器
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
311 10
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
7月前
|
存储 API 数据安全/隐私保护
【02】整体试验思路,在这之前我们发现sec_uid,sec_uid是什么和uid的关系又是什么?相互如何转换?python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
【02】整体试验思路,在这之前我们发现sec_uid,sec_uid是什么和uid的关系又是什么?相互如何转换?python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
537 6
|
8月前
|
缓存 前端开发 IDE
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
173 0
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
移动开发 Android开发 数据安全/隐私保护
移动应用与系统的技术演进:从开发到操作系统的全景解析随着智能手机和平板电脑的普及,移动应用(App)已成为人们日常生活中不可或缺的一部分。无论是社交、娱乐、购物还是办公,移动应用都扮演着重要的角色。而支撑这些应用运行的,正是功能强大且复杂的移动操作系统。本文将深入探讨移动应用的开发过程及其背后的操作系统机制,揭示这一领域的技术演进。
本文旨在提供关于移动应用与系统技术的全面概述,涵盖移动应用的开发生命周期、主要移动操作系统的特点以及它们之间的竞争关系。我们将探讨如何高效地开发移动应用,并分析iOS和Android两大主流操作系统的技术优势与局限。同时,本文还将讨论跨平台解决方案的兴起及其对移动开发领域的影响。通过这篇技术性文章,读者将获得对移动应用开发及操作系统深层理解的钥匙。
369 12
|
11月前
|
小程序 JavaScript API
微信小程序开发之:保存图片到手机,使用uni-app 开发小程序;还有微信原生保存图片到手机
这篇文章介绍了如何在uni-app和微信小程序中实现将图片保存到用户手机相册的功能。
2887 0
微信小程序开发之:保存图片到手机,使用uni-app 开发小程序;还有微信原生保存图片到手机
|
网络协议 Android开发 数据安全/隐私保护
Android手机上使用Socks5全局代理-教程+软件
Android手机上使用Socks5全局代理-教程+软件
8582 2
|
监控 安全 Android开发
【新手必读】Airtest测试Android手机常见的设置问题
【新手必读】Airtest测试Android手机常见的设置问题
419 0
|
Web App开发 前端开发 网络安全
前端分析工具之 Charles 录制 Android/IOS 手机的 https 应用
【2月更文挑战第21天】前端分析工具之 Charles 录制 Android/IOS 手机的 https 应用
227 1
前端分析工具之 Charles 录制 Android/IOS 手机的 https 应用

热门文章

最新文章