tghoang
tghoang

Reputation: 2065

How to programmatically click a button in WPF?

Since there's no button.PerformClick() method in WPF, is there a way to click a WPF button programmatically?

Upvotes: 167

Views: 165755

Answers (10)

Murad
Murad

Reputation: 60

 # Create extension method and use always button #
 public static class UIExtension
 {
    public static void PerformClick(this Button button)
    {
        button.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent));
    }
 }
 public partial class MyForm : Window
 {
    InitializeComponent();
    myButton.PerformClick();
 }
 

Upvotes: 0

Ivo Petrov
Ivo Petrov

Reputation: 31

You can also call the method for the button getting clicked Button_Click(new object(), new RoutedEventArgs(ButtonBase.ClickEvent)); Anther way is ButtonName.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent)); Both ways need using System.Windows.Controls.Primitives;

  • Button_Click(new object(), new RoutedEventArgs(ButtonBase.ClickEvent));
  • ButtonName.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent));

Upvotes: 3

rittergig
rittergig

Reputation: 755

The problem with the Automation API solution is, that it required a reference to the Framework assembly UIAutomationProvider as project/package dependency.

An alternative is to emulate the behaviour. In the following there is my extended solution which also condiders the MVVM-pattern with its bound commands - implemented as extension method:

public static class ButtonExtensions
{
    /// <summary>
    /// Performs a click on the button.<br/>
    /// This is the WPF-equivalent of the Windows Forms method "<see cref="M:System.Windows.Forms.Button.PerformClick" />".
    /// <para>This simulates the same behaviours as the button was clicked by the user by keyboard or mouse:<br />
    /// 1. The raising the ClickEvent.<br />
    /// 2.1. Checking that the bound command can be executed, calling <see cref="ICommand.CanExecute" />, if a command is bound.<br />
    /// 2.2. If command can be executed, then the <see cref="ICommand.Execute(object)" /> will be called and the optional bound parameter is p
    /// </para>
    /// </summary>
    /// <param name="sourceButton">The source button.</param>
    /// <exception cref="ArgumentNullException">sourceButton</exception>
    public static void PerformClick(this Button sourceButton)
    {
        // Check parameters
        if (sourceButton == null)
            throw new ArgumentNullException(nameof(sourceButton));

        // 1.) Raise the Click-event
        sourceButton.RaiseEvent(new RoutedEventArgs(System.Windows.Controls.Primitives.ButtonBase.ClickEvent));

        // 2.) Execute the command, if bound and can be executed
        ICommand boundCommand = sourceButton.Command;
        if (boundCommand != null)
        {
            object parameter = sourceButton.CommandParameter;
            if (boundCommand.CanExecute(parameter) == true)
                boundCommand.Execute(parameter);
        }
    }
}

Upvotes: 1

KVKConsultancy
KVKConsultancy

Reputation: 205

When using the MVVM Command pattern for Button function (recommended practice), a simple way to trigger the effect of the Button is as follows:

someButton.Command.Execute(someButton.CommandParameter);

This will use the Command object which the button triggers and pass the CommandParameter defined by the XAML.

Upvotes: 4

JaredPar
JaredPar

Reputation: 755537

WPF takes a slightly different approach than WinForms here. Instead of having the automation of a object built into the API, they have a separate class for each object that is responsible for automating it. In this case you need the ButtonAutomationPeer to accomplish this task.

ButtonAutomationPeer peer = new ButtonAutomationPeer(someButton);
IInvokeProvider invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
invokeProv.Invoke();

Here is a blog post on the subject.

Note: IInvokeProvider interface is defined in the UIAutomationProvider assembly.

Upvotes: 148

Max
Max

Reputation: 1820

As Greg D said, I think that an alternative to Automation to click a button using the MVVM pattern (click event raised and command executed) is to call the OnClick method using reflection:

typeof(System.Windows.Controls.Primitives.ButtonBase).GetMethod("OnClick", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(button, new object[0]);

Upvotes: 5

Mahdi
Mahdi

Reputation: 261

this.PowerButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));

Upvotes: 26

Denis Vuyka
Denis Vuyka

Reputation: 2865

Like JaredPar said you can refer to Josh Smith's article towards Automation. However if you look through comments to his article you will find more elegant way of raising events against WPF controls

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

I personally prefer the one above instead of automation peers.

Upvotes: 222

Sonorx
Sonorx

Reputation: 1439

if you want to call click event:

SomeButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));

And if you want the button looks like it is pressed:

typeof(Button).GetMethod("set_IsPressed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(SomeButton, new object[] { true });

and unpressed after that:

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

or use the ToggleButton

Upvotes: 43

Greg D
Greg D

Reputation: 44096

One way to programmatically "click" the button, if you have access to the source, is to simply call the button's OnClick event handler (or Execute the ICommand associated with the button, if you're doing things in the more WPF-y manner).

Why are you doing this? Are you doing some sort of automated testing, for example, or trying to perform the same action that the button performs from a different section of code?

Upvotes: 6

Related Questions