WPF'de bir düğmeyi programlı olarak nasıl tıklatırsınız?


144

Hiçbir olmadığına göre button.PerformClick()WPF yöntem programlı bir WPF butonuna tıklayarak bir yol var?

Yanıtlar:


128

WPF, WinForms'dan biraz farklı bir yaklaşım benimser. API'da bir nesnenin otomasyonunun yerleşik hale getirilmesi yerine, nesnenin otomatikleştirilmesinden sorumlu her nesne için ayrı bir sınıfı vardır. Bu durumda, ButtonAutomationPeerbu görevi gerçekleştirmek için.

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

İşte konuyla ilgili bir blog yazısı.

Not: IInvokeProviderarayüz UIAutomationProvidermontajda tanımlanmıştır .


2
Slick, bunun farkında değildim. Otomatik test için çok yararlı olabilir. Bu bağlantıda, kendiniz oluşturmak yerine otomasyon emsalini almak için sağlanan bir fabrikayı kullanmanızı öneren bir yorum olduğunu unutmayın.
Greg D

7
Bunun için teşekkürler. Bir referans ekleyene kadar uygulamamda doğru ad alanlarını bulmak için mücadele ettim UIAutomationProvider. Sonra eklemek zorundausing System.Windows.Automation.Peers; using System.Windows.Automation.Provider;
sergeantKK

5
Eğimli için bir astar:((IInvokeProvider) (new ButtonAutomationPeer(someButton).GetPattern(PatternInterface.Invoke)).Invoke();
Danny Beckett

3
Dikkat edilmesi gereken bir şey, Çağrıyı çağır çağrısının eşzamansız olmasıdır. Bu, bir birim testinde kullanıyorsanız ve bir sonraki satırınız düğmenin tıklanmasının beklenen sonucunu kontrol etmekse, beklemeniz gerekebilir.
denver

3
Sadece referans olarak, IInvokeProviderarayüz UIAutomationProvidermontajda tanımlanır .
Steven Rands

188

JaredPar'ın dediği gibi Josh Smith'in Otomasyon hakkındaki makalesine başvurabilirsiniz. Ancak makalesinin yorumlarına bakarsanız, WPF kontrollerine karşı olayları yükseltmenin daha zarif bir yolunu bulacaksınız

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

Ben şahsen otomasyon akranları yerine yukarıdaki olanı tercih ederim.


26
RaiseEvent çözümü yalnızca etkinliği artırır. Düğme ile ilişkili Komutu yürütmez (Skanaar'ın dediği gibi)
Eduardo Molteni

4
XAML kullanıyorsanız, örneğin <Button Name = "X" Click = "X_Click" />, olay normalde olduğu gibi tıklama işleyicisi tarafından yakalanır. Benden +1!
metao

4
VB kullanıyorum ... kod VB ayetleri C # için farklı olup olmadığından emin değilim, ama new RoutedEventArgs(Button.ClickEvent)benim için çalışmadı. Kullanmak zorunda kaldım new RoutedEventArgs(Primitives.ButtonBase.ClickEvent). Aksi takdirde, harika çalışıyor!
BrianVPS

3
@EduardoMolteni ve Skanaar üzerinde ayrıntılı olarak durmak için Komutlar tarafından verilen IsEnabled işlevselliğini bu şekilde kaybedersiniz, bu nedenle tüm etkinliklerinizin etkin olup olmadığını kontrol etmelerini istemiyorsanız AutomationPeer daha iyi çalışır.
Justin Pihony

34

tıklama etkinliğini aramak istiyorsanız:

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

Ve düğmenin basılı gibi görünmesini istiyorsanız:

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

ve bundan sonra bastırılmamış:

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

veya ToggleButton'u kullanın


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

5

Kaynağa erişiminiz varsa, düğmeyi programlı olarak "tıklatmanın" bir yolu, düğmelerin OnClick olay işleyicisini aramak (veya daha WPF-y tarzında bir şeyler yapıyorsanız düğmeyle ilişkili ICommand'ı yürütmektir) ).

Bunu neden yapıyorsun? Örneğin, bir tür otomatik test mi yapıyorsunuz veya düğmenin farklı bir kod bölümünden gerçekleştirdiği işlemi gerçekleştirmeye mi çalışıyorsunuz?


Benim sorunum için tek çözüm değil, ama bunu yapmaya çalıştığımda, button.PerformClick () kadar kolay olmadığını buldum, bu yüzden biraz meraklıyım ... :)
tghoang

Aynı projede başka bir pencerenin menüsüne tıklamak zorunda kaldım ve MyOtherWindow.mnuEntry_Click (Me, New Windows.RoutedEventArgs) yaptı. Gerçekten basit.
Andrea Antonangeli

4

As Greg D söyledi, ben bir alternatiftir düşünüyorum Automationçağırmak için MVVM desen (tıklama etkinlik kaldırdı ve komut çalıştırılır) kullanılarak bir düğmesini tıklayın OnClickyansıma kullanarak yöntemi:

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

Bu, üst öğeye komut vermek için alt öğeden bir olayı kullanmanın iyi bir yoludur.
Cool Blue

2

Düğme işlevi için MVVM Komut kalıbını kullanırken (önerilen uygulama), Düğmenin etkisini tetiklemenin basit bir yolu aşağıdaki gibidir:

someButton.Command.Execute(someButton.CommandParameter);

Bu , düğmenin tetiklediği Command nesnesini kullanır ve XAML tarafından tanımlanan CommandParameter'ı iletir .


Bir not, bu sadece düğmenin tıklandığında sahip olacağı etkiyi tetikler . İleti gönderme sırasında herhangi bir tıklama olayı oluşturmaz. Tüm pratik durumlar için bu isteyeceğiniz şeydir ve gereksiz dağıtıcı olaylarından (örneğin daha fazla performanstan) kaçınacaktır, ancak aslında bir şekilde dağıtıcı olaylarını gerektiriyorsa yukarıdaki diğer çözümler daha uygundur
KVKConsultancy

0

Otomasyon API çözümüyle ilgili sorun, UIAutomationProviderproje / paket bağımlılığı olarak Framework derlemesine başvuru gerektirmesidir .

Bir alternatif, davranışı taklit etmektir. Aşağıda, genişletilmiş çözümüm de MVVM desenini bağlı komutları ile yoğunlaştırıyor - uzatma yöntemi olarak uygulandı :

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);
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.