プログラムでWPFのボタンをクリックする方法は?


144

button.PerformClick()WPFにはメソッドがないため、プログラムでWPFボタンをクリックする方法はありますか?

回答:


128

ここでは、WPFはWinFormsとは少し異なるアプローチを取ります。オブジェクトの自動化をAPIに組み込む代わりに、オブジェクトの自動化を担当するオブジェクトごとに個別のクラスがあります。この場合、ButtonAutomationPeerこのタスクを実行するにはが必要です。

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

これはこの件に関するブログ投稿です。

注:IInvokeProviderインターフェースはUIAutomationProviderアセンブリーで定義されます。


2
スリック、私はこれに気づいていませんでした。自動テストに非常に役立ちます。そのリンクには、自分で作成するのではなく、提供されたファクトリを使用してオートメーションピアを取得することを提案するコメントがあることに注意してください。
Greg D

7
これをありがとう。への参照を追加するまで、アプリで正しい名前空間を見つけるのに苦労しましたUIAutomationProvider。その後、追加する必要がありましたusing System.Windows.Automation.Peers; using System.Windows.Automation.Provider;
sergeantKK

5
傾向のある人のためのワンライナー:((IInvokeProvider) (new ButtonAutomationPeer(someButton).GetPattern(PatternInterface.Invoke)).Invoke();
ダニー・ベケット2015年

3
注意すべきことの1つは、Invoke呼び出しが非同期であることです。つまり、単体テストでそれを使用していて、次の行がボタンをクリックしたときに予期される結果を確認することである場合は、待機する必要がある場合があります。
デンバー

3
参考までに、IInvokeProviderインターフェースはUIAutomationProviderアセンブリで定義されています。
Steven Rands 2017年

188

JaredParが言ったように、オートメーションに関するJosh Smithの記事を参照できます。ただし、彼の記事へのコメントを見ると、WPFコントロールに対してイベントを発生させるよりエレガントな方法が見つかります。

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

私は個人的には、自動化ピアよりも上記のものを好みます。


26
RaiseEventソリューションはイベントを発生させるだけです。ボタンに関連付けられたコマンドは実行されません(スカナールが言うように)
エドゥアルドモルテニ2010年

4
XAMLを使用する場合(<Button Name = "X" Click = "X_Click" />など)、イベントは通常どおりクリック時ハンドラーによってキャッチされます。私からの+1!
metao

4
VBを使用しています... VBとC#でコードが異なるかどうかはわかりませんが、うまくいきnew RoutedEventArgs(Button.ClickEvent)ませんでした。私は使用しなければなりませんでしたnew RoutedEventArgs(Primitives.ButtonBase.ClickEvent)。そうでなければ、うまくいきます!
BrianVPS 2012年

3
@EduardoMolteniとSkanaarについて詳しく説明すると、この方法でコマンドによって提供されたIsEnabled機能が失われるため、すべてのイベントでイベントが有効かどうかを確認したくない場合は、AutomationPeerの方が適切に機能します。
ジャスティンピホニー

34

クリックイベントを呼び出す場合:

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 });

またはトグルボタンを使用する



5

ソースにアクセスできる場合、ボタンをプログラムで「クリック」する1つの方法は、ボタンのOnClickイベントハンドラーを呼び出す(または、ボタンに関連付けられたICommandを実行する)ことです。 )。

なぜあなたはこれをやっている?たとえば、ある種の自動テストを行っていますか、それとも、ボタンがコードの別のセクションから実行するのと同じアクションを実行しようとしていますか?


...それは私の問題の唯一の解決策ではないのですが、私はこれを行うにしようとしたとき、私は)それがbutton.PerformClick(限り簡単にはないことがわかったので、少しだけ好奇心:)
tghoang

同じプロジェクトの別のウィンドウのメニューをクリックする必要があり、MyOtherWindow.mnuEntry_Click(Me、New Windows.RoutedEventArgs)がそれを行いました。本当に簡単です。
Andrea Antonangeli 2017年

4

グレッグDが言った、私がする別のことを考えてAutomation(クリックイベントが発生し、コマンドが実行された)MVVMパターンを使用して、ボタンをクリックすることで呼び出すことですOnClick:リフレクションを使用する方法を

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

これは、子要素からのイベントを使用して親でコマンドを実行するのに適した方法です。
クールブルー

2

ボタン機能にMVVMコマンドパターンを使用する場合(推奨される方法)、ボタンの効果をトリガーする簡単な方法は次のとおりです。

someButton.Command.Execute(someButton.CommandParameter);

これは、ボタンがトリガーするCommandオブジェクトを使用し、XAMLで定義されたCommandParameterを渡します。


1つのメモ、これはボタンがクリックされた場合の効果のみをトリガーします。メッセージディスパッチキューにクリックイベントは生成されません。すべての実際的なケースでは、これがあなたが望むものであり、不要なディスパッチャーイベント(たとえば、より高いパフォーマンス)を回避しますが、実際に何らかの方法でディスパッチャーイベントを必要とする場合、上記の他のソリューションがより適切です
KVKConsultancy

0

オートメーションAPIソリューションの問題は、UIAutomationProviderプロジェクト/パッケージの依存関係としてフレームワークアセンブリへの参照が必要なことです。

別の方法は、動作をエミュレートすることです。以下に、拡張メソッドとして実装された、バインドされたコマンドでMVVMパターンを検討する拡張ソリューションがあります。

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);
        }
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.