วิธีการคลิกปุ่มใน 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
ลื่นฉันไม่รู้เรื่องนี้ อาจมีประโยชน์มากสำหรับการทดสอบอัตโนมัติ โปรดทราบว่ามีความคิดเห็นเกี่ยวกับลิงก์ที่แนะนำให้ใช้โรงงานที่จัดไว้เพื่อรับเพียร์ระบบอัตโนมัติแทนที่จะสร้างด้วยตัวคุณเอง
เกร็ก D

7
ขอบคุณสำหรับสิ่งนี้. ฉันพยายามที่จะหาสิ่งที่ namespaces ที่ถูกต้องใน app UIAutomationProviderของฉันจนกว่าฉันจะเพิ่มการอ้างอิงถึง จากนั้นจึงต้องเพิ่มusing System.Windows.Automation.Peers; using System.Windows.Automation.Provider;
sergeantKK

5
หนึ่งซับสำหรับแนวเอียง:((IInvokeProvider) (new ButtonAutomationPeer(someButton).GetPattern(PatternInterface.Invoke)).Invoke();
Danny Beckett

3
สิ่งหนึ่งที่ควรทราบคือการเรียกใช้เรียกไม่ตรงกัน ซึ่งหมายความว่าหากคุณใช้ในการทดสอบหน่วยและบรรทัดถัดไปของคุณคือการตรวจสอบผลลัพธ์ที่คาดหวังจากการคลิกปุ่มคุณอาจต้องรอ
เดนเวอร์

3
สำหรับการอ้างอิงเท่านั้นIInvokeProviderอินเตอร์เฟสถูกกำหนดในUIAutomationProviderชุดประกอบ
Steven Rands

188

เช่นเดียวกับ JaredPar กล่าวว่าคุณสามารถอ้างถึงบทความของ Josh Smith ที่มีต่อระบบอัตโนมัติ อย่างไรก็ตามหากคุณดูความคิดเห็นในบทความของเขาคุณจะพบวิธีที่สง่างามมากขึ้นในการเพิ่มกิจกรรมกับตัวควบคุม WPF

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

โดยส่วนตัวแล้วฉันชอบสิ่งที่กล่าวมาข้างต้นแทนที่จะเป็นเพื่อนร่วมงานอัตโนมัติ


26
โซลูชัน RaiseEvent ทำให้เกิดเหตุการณ์ขึ้นเท่านั้น มันไม่ได้ใช้คำสั่งที่เกี่ยวข้องกับปุ่ม (ดังที่ Skanaar พูด)
Eduardo Molteni

4
หากคุณใช้ XAML เช่น <ชื่อปุ่ม = "X" คลิก = "X_Click" /> เหตุการณ์จะถูกจับโดยตัวจัดการคลิกเมื่อตามปกติ +1 จากฉัน!
metao

4
ฉันใช้ VB ... ไม่แน่ใจว่ารหัสนั้นแตกต่างกันสำหรับ VB ข้อ C # แต่new RoutedEventArgs(Button.ClickEvent)ไม่ได้ผลสำหรับฉัน new RoutedEventArgs(Primitives.ButtonBase.ClickEvent)ผมต้องใช้ มิฉะนั้นใช้งานได้ดี!
BrianVPS

3
หากต้องการอธิบายรายละเอียดเกี่ยวกับ @EduardoMolteni และ Skanaar คุณจะสูญเสียฟังก์ชัน IsEnabled ที่กำหนดโดยคำสั่งด้วยวิธีนี้ดังนั้นหากคุณไม่ต้องการให้กิจกรรมทั้งหมดของคุณตรวจสอบว่าเปิดใช้งานหรือไม่ AutomationPeer จะทำงานได้ดีขึ้น
Justin Pihony

34

หากคุณต้องการโทรคลิกเหตุการณ์:

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

และหากคุณต้องการให้ปุ่มดูเหมือนกด:

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

และ unpressed หลังจากนั้น:

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

หรือใช้ ToggleButton



5

วิธีหนึ่งในการ "คลิก" ปุ่มโดยทางโปรแกรมหากคุณมีสิทธิ์เข้าถึงแหล่งคือเพียงเรียกใช้ตัวจัดการเหตุการณ์ OnClick ของปุ่ม (หรือเรียกใช้งาน ICommand ที่เกี่ยวข้องกับปุ่มถ้าคุณทำสิ่งต่าง ๆ ในลักษณะ WPF-y )

ทำไมคุณทำเช่นนี้? คุณกำลังทำการทดสอบแบบอัตโนมัติเช่นหรือพยายามดำเนินการแบบเดียวกันกับที่ปุ่มทำงานจากรหัสส่วนอื่นหรือไม่?


มันไม่ได้เป็นเพียงการแก้ปัญหาในการแก้ไขปัญหาของฉัน แต่เมื่อฉันพยายามที่จะทำเช่นนี้ผมพบว่ามันไม่ได้เป็นเรื่องง่ายเหมือน button.PerformClick () ดังนั้นเพียงเล็กน้อยอยากรู้อยากเห็น ... :)
tghoang

ฉันต้องคลิกที่เมนูของหน้าต่างอื่นในโครงการเดียวกันและ MyOtherWindow.mnuEntry_Click (ฉันใหม่ Windows.RoutedEventArgs) ง่ายจริงๆ
Andrea Antonangeli

4

ดังที่Greg Dกล่าวว่าฉันคิดว่าทางเลือกในAutomationการคลิกปุ่มที่ใช้รูปแบบ MVVM (คลิกเหตุการณ์ยกและดำเนินการคำสั่ง) คือการเรียกOnClickวิธีการใช้ภาพสะท้อน:

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

นี่เป็นวิธีที่ดีในการใช้เหตุการณ์จากองค์ประกอบลูกเพื่อเริ่มต้นคำสั่งบนพาเรนต์
Cool Blue

2

เมื่อใช้รูปแบบคำสั่งMVVMสำหรับฟังก์ชั่นปุ่ม (วิธีปฏิบัติที่แนะนำ) วิธีง่ายๆในการทริกเกอร์เอฟเฟกต์ของปุ่มมีดังนี้:

someButton.Command.Execute(someButton.CommandParameter);

นี้จะใช้คำสั่งวัตถุที่ปุ่มทริกเกอร์และผ่านการCommandParameterกำหนดโดยXAML


One note นี่เป็นเพียงการกระตุ้นผลกระทบที่ปุ่มจะมีหากคลิก มันไม่ได้สร้างกิจกรรมการคลิกใด ๆ ในคิวการจัดส่งข้อความ สำหรับกรณีที่ปฏิบัติจริงทั้งหมดนี่คือสิ่งที่คุณต้องการและจะหลีกเลี่ยงเหตุการณ์ผู้มอบหมายที่ไม่จำเป็น (เช่นนักแสดงมากขึ้น) แต่ถ้าจริง ๆ แล้วคุณต้องการกิจกรรมผู้มอบหมายงานโซลูชันอื่น ๆ ด้านบนมีความเหมาะสมมากกว่า
KVKConsultancy

0

ปัญหาเกี่ยวกับโซลูชัน API อัตโนมัติคือต้องมีการอ้างอิงถึงแอสเซมบลี Framework เป็นการอ้างอิง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.