Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何以编程方式单击WPF中的按钮?_C#_.net_Wpf_Button - Fatal编程技术网

C# 如何以编程方式单击WPF中的按钮?

C# 如何以编程方式单击WPF中的按钮?,c#,.net,wpf,button,C#,.net,Wpf,Button,由于WPF中没有button.PerformClick方法,有没有办法通过编程方式单击WPF按钮?如果可以访问源代码,可以通过编程方式单击按钮,只需调用按钮的OnClick事件处理程序或执行与按钮关联的ICommand,如果你是以WPF-y的方式做事 你为什么这么做?例如,您是在进行某种自动测试,还是在尝试执行按钮从不同代码段执行的相同操作?WPF采用的方法与WinForms稍有不同。它们没有将对象的自动化内置到API中,而是为负责自动化的每个对象提供了一个单独的类。在这种情况下,您需要Butt

由于WPF中没有button.PerformClick方法,有没有办法通过编程方式单击WPF按钮?

如果可以访问源代码,可以通过编程方式单击按钮,只需调用按钮的OnClick事件处理程序或执行与按钮关联的ICommand,如果你是以WPF-y的方式做事


你为什么这么做?例如,您是在进行某种自动测试,还是在尝试执行按钮从不同代码段执行的相同操作?

WPF采用的方法与WinForms稍有不同。它们没有将对象的自动化内置到API中,而是为负责自动化的每个对象提供了一个单独的类。在这种情况下,您需要ButtonAutomationPeer来完成此任务

ButtonAutomationPeer peer = new ButtonAutomationPeer(someButton);
IInvokeProvider invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
invokeProv.Invoke();
是一篇关于这个主题的博客文章


注意:IInvokeProvider接口是在UIAutomationProvider程序集中定义的。

正如JaredPar所说,您可以参考Josh Smith的文章《走向自动化》。然而,如果您查看他的文章的评论,您将发现针对WPF控件引发事件的更优雅的方式

someButton.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent));

我个人更喜欢上面的一个,而不是自动化同行。

如果您想调用单击事件:

SomeButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
如果您想让按钮看起来像按下了一样:

typeof(Button).GetMethod("set_IsPressed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(SomeButton, new object[] { true });
在那之后没有压力:

typeof(Button).GetMethod("set_IsPressed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(SomeButton, new object[] { false });
或者使用ToggleButton

如前所述,我认为使用MVVM模式单击按钮的自动化替代方法是使用引发的click事件和执行的命令调用OnClick方法,使用反射:

this.PowerButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
typeof(System.Windows.Controls.Primitives.ButtonBase).GetMethod("OnClick", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(button, new object[0]);
当使用MVVM命令模式作为按钮功能推荐实践时,触发按钮效果的简单方法如下:

someButton.Command.Execute(someButton.CommandParameter);

这将使用按钮触发的命令对象并传递XAML定义的CommandParameter。

自动化API解决方案的问题是,它需要引用框架程序集UIAutomationProvider作为项目/包依赖项

另一种方法是模仿这种行为。下面是我的扩展解决方案,它还通过绑定的命令约束MVVM模式-作为扩展方法实现:

公共静态类按钮 { /// ///单击按钮。 ///这是与Windows窗体方法等效的WPF。 ///这模拟了用户通过键盘或鼠标单击按钮时的相同行为: ///1.引发ClickEvent。 ///2.1.检查绑定命令是否可以执行,如果命令被绑定,则调用。 ///2.2.如果可以执行命令,则将调用,可选绑定参数为p /// /// ///“源”按钮。 ///源按钮 公共静态无效性能单击此按钮sourceButton { //检查参数 如果sourceButton==null 抛出新ArgumentNullExceptionnameofsourceButton; //1.引发单击事件 sourceButton.RaiseEventnew RoutedEventTargetSystem.Windows.Controls.Primitives.ButtonBase.ClickEvent; //2.执行命令,如果绑定并且可以执行 ICommand boundCommand=sourceButton.Command; 如果boundCommand!=null { 对象参数=sourceButton.CommandParameter; 如果boundCommand.CanExecuteparameter==true boundCommand.Executeparameter; } } }
这并不是解决我问题的唯一方法,但当我尝试这样做时,我发现它不像button.PerformClick那么简单,所以有点好奇……:我不得不在同一个项目中单击另一个窗口的菜单,然后我的另一个窗口.mnentry\u单击我,New Windows.RoutedEventArgs这样做了。真的很简单,斯里克,我没有意识到这一点。对于自动化测试可能非常有用。请注意,该链接上有一条评论,建议使用提供的工厂获取自动化对等点,而不是自己创建一个。谢谢。我努力在我的应用程序中找到正确的名称空间,直到我添加了对UIAutomationProvider的引用。然后必须使用System.Windows.Automation.Peers添加;使用System.Windows.Automation.Provider;倾斜的一行代码:IInvokeProvider新按钮自动PeerSomeButton.GetPatternPatternInterface.Invoke.Invoke;需要注意的一点是调用是异步的。这意味着,如果在单元测试中使用它,而下一行是检查单击按钮的预期结果,则可能需要等待。仅供参考,IInvokeProvider接口是在UIAutomationProvider程序集中定义的。RaiseEvent解决方案仅引发事件。它不会像Skanaar所说的那样执行与按钮相关联的命令。如果使用XAML eg,事件将按照正常情况由点击处理程序捕获+从我这里得到1分!我正在使用VB…不确定VB和C的代码是否不同,但是新的RoutedEventArgsButton.ClickEvent对我不起作用。我有
要使用新路由EventTargetsPrimitives.ButtonBase.ClickEvent。否则,效果很好!要详细说明@EduardoMolteni和Skanaar,您将失去命令以这种方式提供的IsEnabled功能,因此除非您希望所有事件都检查它们是否已启用,否则AutomationPeer工作得更好。这是使用子元素的事件对父元素触发命令的好方法。注意,这只会触发单击按钮时产生的效果。它不会在消息调度队列中生成任何单击事件。对于所有实际情况,这是您所希望的,并将避免不必要的调度程序事件,例如,更高的性能,但如果您确实以某种方式要求调度程序事件,则上述其他解决方案更合适,这将节省我的时间。