博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UWP开发砸手机系列(二)—— “讲述人”识别自定义控件Command
阅读量:5924 次
发布时间:2019-06-19

本文共 4636 字,大约阅读时间需要 15 分钟。

原文:

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

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

  我们再来对比一下系统控件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通过依赖属性可以做到的事情,附加属性一样可以完成。

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

    public class ButtonAutomationPeer : ButtonBaseAutomationPeer, IInvokeProvider    {        /// Initializes a new instance of the 
class.
        /// The element associated with this automation peer.        public ButtonAutomationPeer(Button owner) : base(owner)        {        }        /// Gets the name of the control that is associated with this UI Automation peer.        ///
A string that contains "Button".
        protected override string GetClassNameCore()        {            return "Button";        }        /// Gets the control type of the element that is associated with the UI Automation peer.        ///
        ///   
.
        protected override AutomationControlType GetAutomationControlTypeCore()        {            return AutomationControlType.Button;        }        /// Gets the object that supports the specified control pattern of the element that is associated with this automation peer.        ///
If
is
, this method returns a this pointer, otherwise this method returns null.
        /// A value in the enumeration.        public override object GetPattern(PatternInterface patternInterface)        {            if (patternInterface == PatternInterface.Invoke)            {                return this;            }            return base.GetPattern(patternInterface);        }        /// This type or member supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used directly from your code.        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);        }    }

  果不其然发现了上一篇我们提到的GetClassNameCore,GetAutomationControlTypeCore,GetPattern三个方法。另外还有一个奇怪的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,逼的俺自由发挥啊。特地写了这篇造福全人类,各位不要吝啬点个推荐哦,虽然“讲述人”并没有什么卵用……

 

 

 

 

 

 

 

 

转载地址:http://evovx.baihongyu.com/

你可能感兴趣的文章
web项目小总结
查看>>
你有没有聪明到利用云给你带来回报?
查看>>
我的友情链接
查看>>
分享有用的 Linux 命令行网络监控工具
查看>>
《.NET 编程结构》专题汇总
查看>>
MapReduce和spark的shuffle过程详解
查看>>
oracle修改MAX_STRING_SIZE,突然断电处理
查看>>
java hibernate关联查询返回一个集合,转换成json报json死循环处理
查看>>
C# 删除Collections中的重复数据
查看>>
NFS 网络系统配置及自动挂载
查看>>
corosync(openais)+drbd+pacemaker实现mysql服务器的高可用性群集
查看>>
centos 6.2 硬盘安装(双系统)
查看>>
RHEL6.2 64位系统Virtualbox虚拟机下安装过程
查看>>
Linux中文件查找——find命令
查看>>
How to Install Apache Kafka on CentOS 7
查看>>
Exchange 2016 将邮箱数据库排除
查看>>
正式学习React(四) 前序篇
查看>>
yum安装mysql
查看>>
如何在fedora 16下配置×××连接
查看>>
linux下cache和buffer的使用情况
查看>>