Share via


Benutzeroberflächenautomatisierung eines benutzerdefinierten WPF-Steuerelements

Aktualisiert: Juli 2008

Microsoft-UI-Automatisierung stellt eine einzelne, allgemeine Benutzeroberfläche bereit, über die Automatisierungsclients die Benutzeroberflächen einer Vielzahl von Plattformen und Frameworks untersuchen und anwenden können. UI-Automatisierung ermöglicht sowohl Qualitätssicherungs-Testcode als auch Eingabehilfeprogrammen, wie z. B. Bildschirmsprachausgaben, Benutzeroberflächenelemente zu untersuchen und Benutzerinteraktionen mit diesen Elementen über anderen Code zu simulieren. Informationen zu UI-Automatisierung und alle Plattformen finden Sie unter Eingabehilfen.

In diesem Thema wird beschrieben, wie ein serverseitiger Benutzeroberflächenautomatisierungs-Anbieter für ein in einer WPF-Anwendung ausgeführtes benutzerdefiniertes Steuerelement implementiert wird. WPF unterstützt UI-Automatisierung über eine Struktur von Automatisierungspeerobjekten, die der Struktur der Benutzeroberflächenelemente entspricht. Testcode und Anwendungen, die Eingabehilfen bereitstellen, können Automatisierungspeerobjekte direkt (für prozessinternen Code) oder über die von UI-Automatisierung bereitgestellte allgemeine Oberfläche verwenden.

Dieses Thema enthält folgende Abschnitte.

  • Automatisierungspeerklassen
  • Integrierte Automatisierungspeerklassen
  • Sicherheitsüberlegungen für abgeleitete Peers
  • Peernavigation
  • Anpassungen in einem abgeleiteten Peer
  • Verwandte Abschnitte

Automatisierungspeerklassen

WPF-Steuerelemente unterstützen UI-Automatisierung durch eine Struktur von Peerklassen, die von AutomationPeer abgeleitet sind. Peerklassennamen beginnen gemäß der Konvention mit dem Steuerelementklassennamen und enden mit "AutomationPeer". Beispiel: ButtonAutomationPeer ist die Peerklasse für die Steuerelementklasse Button. Die Peerklassen sind weitgehend zu UI-Automatisierung-Steuerelementtypen äquivalent, gelten jedoch spezifisch für WPF-Elemente. Automatisierungscode, der über die UI-Automatisierung-Oberfläche auf WPF-Anwendungen zugreift, verwendet Automatisierungspeers nicht direkt, von Automatisierungscode im selben Prozessbereich können Automatisierungspeers jedoch direkt verwendet werden.

Integrierte Automatisierungspeerklassen

Elemente implementieren eine Automatisierungspeerklasse, wenn sie Benutzeroberflächenaktivitäten akzeptieren, oder wenn sie Informationen enthalten, die für Benutzer von Bildschirmsprachausgaben erforderlich sind. Nicht alle visuellen WPF-Elemente verfügen über Automatisierungspeers. Beispiele für Klassen, die Automatisierungspeers implementieren, sind Button, TextBox, und Label. Beispiele für Klassen, die keine Automatisierungspeers implementieren, sind von Decorator abgeleitete Klassen, wie z. B. Border, und Klassen, die auf Panel basieren, wie z. B. Grid und Canvas.

Die Control-Basisklasse hat keine entsprechende Peerklasse. Wenn Sie eine Peerklasse benötigen, die einem von Control abgeleiteten benutzerdefinierten Steuerelement entspricht, leiten Sie die benutzerdefinierte Peerklasse von FrameworkElementAutomationPeer ab.

Sicherheitsüberlegungen für abgeleitete Peers

Automatisierungspeers müssen in einer teilweise vertrauenswürdigen Umgebung ausgeführt werden. Da Code in der UIAutomationClient-Assembly nicht für die Ausführung in einer teilweise vertrauenswürdigen Umgebung konfiguriert ist, darf der Automatisierungspeercode nicht auf diese Assembly verweisen. Verwenden Sie stattdessen die Klassen in der UIAutomationTypes-Assembly. Verwenden Sie z. B. die AutomationElementIdentifiers-Klasse in der UIAutomationTypes-Assembly, die der AutomationElement-Klasse in der UIAutomationClient-Assembly entspricht. Der Verweis auf die UIAutomationTypes-Assembly in Automatisierungspeercode ist gefahrlos.

Peernavigation

Nach der Lokalisierung eines Automatisierungspeers kann prozessinterner Code durch Aufrufen der GetChildren-Methode und der GetParent-Methode des Objekts durch die Peerstruktur navigieren. Die Navigation zwischen WPF-Elementen innerhalb eines Steuerelements wird von der Peerimplementierung der GetChildrenCore-Methode unterstützt. Das Benutzerflächenautomatisierungs-System ruft diese Methode auf, um eine Struktur aus den in einem Steuerelement enthaltenen Unterelementen zu erstellen, z. B. den Listeneinträgen in einem Listenfeld. Die UIElementAutomationPeer.GetChildrenCore-Standardmethode durchläuft die visuelle Struktur von Elementen, um die Struktur von Automatisierungspeers zu erstellen. Diese Methode wird von benutzerdefinierten Steuerelementen überschrieben, um die Unterelemente den Automatisierungsclients zur Verfügung zu stellen, wobei die Automatisierungspeers von Elementen zurückgegeben werden, die Informationen enthalten oder Benutzerinteraktionen ermöglichen.

Anpassungen in einem abgeleiteten Peer

Alle Klassen, die von UIElement und ContentElement abgeleitet werden, enthalten die geschützte virtuelle Methode OnCreateAutomationPeer. WPF ruft OnCreateAutomationPeer auf, um das Automatisierungspeerobjekt für jedes Steuerelement abzurufen. Automatisierungscode kann das Peerobjekt verwenden, um Informationen über die Eigenschaften und Funktionen eines Steuerelements abzurufen und die Benutzerinteraktion damit zu simulieren. Ein benutzerdefiniertes Steuerelement, das die Automatisierung unterstützt, muss OnCreateAutomationPeer überschreiben und eine Instanz einer Klasse zurückgeben, die von AutomationPeer abgeleitet wird. Beispiel: Wenn ein benutzerdefiniertes Steuerelement von der ButtonBase-Klasse abgeleitet wird, muss das von OnCreateAutomationPeer zurückgegebene Objekt von ButtonBaseAutomationPeer abgeleitet werden.

Bei der Implementierung eines benutzerdefinierten Steuerelements müssen Sie die "Core"-Methoden der Basis-Automatisierungspeerklasse überschreiben, die das eindeutige und spezifische Verhalten dieses benutzerdefinierten Steuerelements definieren.

Überschreiben von OnCreateAutomationPeer

Überschreiben Sie für das benutzerdefinierte Steuerelement die OnCreateAutomationPeer-Methode, sodass Ihr Anbieterobjekt, das direkt oder indirekt von AutomationPeer abgeleitet werden muss, zurückgegeben wird.

Überschreiben von GetPattern

Durch Automatisierungspeers werden einige Implementierungsaspekte serverseitiger UI-Automatisierung-Anbieter vereinfacht, Automatisierungspeers für benutzerdefinierte Steuerelemente müssen jedoch nach wie vor Steuerelementmuster-Schnittstellen behandeln. Wie Nicht-WPF-Anbieter unterstützen Peers Steuerelementmuster, indem sie Implementierungen von Schnittstellen im System.Windows.Automation.Provider-Namespace bereitstellen, z. B. IInvokeProvider. Die Steuerelementmuster-Schnittstellen können vom Peer selbst oder von einem anderen Objekt implementiert werden. Die Peerimplementierung von GetPattern gibt das Objekt zurück, von dem das angegebene Muster unterstützt wird. UI-Automatisierung-Code ruft die GetPattern-Methode auf und gibt einen PatternInterface-Enumerationswert an. Die Überschreibung von GetPattern muss das Objekt zurückgeben, das das angegebene Muster implementiert. Wenn das Steuerelement nicht über eine benutzerdefinierte Implementierung eines Musters verfügt, können Sie die Implementierung des Basistyps von GetPattern aufrufen, um entweder dessen Implementierung oder, sofern das Muster nicht für diesen Steuerelementtyp unterstützt wird, einen NULL-Verweis zu erhalten. Beispiel: Sie können ein benutzerdefiniertes NumericUpDown-Steuerelement auf einen Wert innerhalb eines Bereichs festlegen, sodass das zugehörige UI-Automatisierung-Peerobjekt die IRangeValueProvider-Schnittstelle implementiert. Das folgende Beispiel zeigt, wie die GetPattern-Methode des Peers als Reaktion auf einen PatternInterface.RangeValue-Wert überschrieben wird.

public override object GetPattern(PatternInterface patternInterface)
{
    if (patternInterface == PatternInterface.RangeValue)
    {
        return this;
    }
    return base.GetPattern(patternInterface);
}

Eine GetPattern-Methode kann auch ein Unterelement als Musteranbieter angeben. Anhand des folgenden Codes wird gezeigt, wie ItemsControl die Behandlung des Scroll-Musters an den Peer des internen ScrollViewer-Steuerelements überträgt.

public override object GetPattern(PatternInterface patternInterface)
{
    if (patternInterface == PatternInterface.Scroll)
    {
        ItemsControl owner = (ItemsControl) base.Owner;

        // ScrollHost is internal to the ItemsControl class
        if (owner.ScrollHost != null)
        {
            AutomationPeer peer = UIElementAutomationPeer.CreatePeerForElement(owner.ScrollHost);
            if ((peer != null) && (peer is IScrollProvider))
            {
                peer.EventsSource = this;
                return (IScrollProvider) peer;
            }
        }
    }
    return base.GetPattern(patternInterface);
}

Zur Angabe eines Unterelements für die Musterbehandlung ruft dieser Code das Unterelementobjekt ab, erstellt einen Peer mit der CreatePeerForElement-Methode, legt die EventsSource-Eigenschaft des neuen Peers auf den aktuellen Peer fest und gibt den neuen Peer zurück. Durch das Festlegen von EventsSource für ein Unterelement wird die Anzeige des Unterelements in der Automatisierungspeerstruktur verhindert, und für alle durch das Unterelement ausgelösten Ereignisse wird als Ursprung das in EventsSource angegebene Steuerelement definiert. Das ScrollViewer-Steuerelement wird in der Automatisierungsstruktur nicht angezeigt, und als Ursprung der Bildlaufereignisse, die es generiert, wird das ItemsControl-Objekt angegeben.

Überschreiben von "Core"-Methoden

Automatisierungscode ruft Informationen über das Steuerelement ab, indem öffentliche Methoden der Peerklasse aufgerufen werden. Um Informationen über das Steuerelement bereitzustellen, überschreiben Sie alle Methoden, deren Namen mit "Core" enden, wenn Ihre Steuerelementimplementierung sich von der durch die Basis-Automatisierungspeerklasse bereitgestellten Implementierung unterscheidet. Das Steuerelement muss mindestens die GetClassNameCore-Methode und die GetAutomationControlTypeCore-Methode implementieren, wie im folgenden Beispiel gezeigt.

protected override string GetClassNameCore()
{
    return "NumericUpDown";
}

protected override AutomationControlType GetAutomationControlTypeCore()
{
    return AutomationControlType.Spinner;
}

Die Implementierung von GetAutomationControlTypeCore beschreibt das Steuerelement, indem ein ControlType-Wert zurückgegeben wird. Sie haben zwar die Möglichkeit, ControlType.Custom zurückzugeben, sollten jedoch einen spezifischeren Steuerelementtyp zurückgeben, wenn dieser das Steuerelement genau beschreibt. Bei dem Rückgabewert ControlType.Custom muss der Anbieter zusätzlich UI-Automatisierung implementieren, und UI-Automatisierung-Clientprodukte können Steuerelementstruktur, Tastaturinteraktion und mögliche Steuerelementmuster nicht im Vorfeld definieren.

Implementieren Sie die IsContentElementCore-Methode und die IsControlElementCore-Methode, um anzugeben, ob das Steuerelement Daten enthält oder auf der Benutzeroberfläche zur Interaktion dient (oder beides). Standardmäßig geben beide Methoden true zurück. Durch diese Einstellungen wird die Verwendbarkeit von Automatisierungstools wie Bildschirmsprachausgaben verbessert, die diese Methoden zur Filterung der Automatisierungsstruktur verwenden können. Wenn die GetPattern-Methode die Musterbehandlung an den Peer eines Unterelements überträgt, kann die IsControlElementCore-Methode dieses Peers false zurückgeben, damit der Peer in der Automatisierungsstruktur nicht angezeigt wird. Beispiel: Der Bildlauf in einem ListBox läuft über einen ScrollViewer, und der Automatisierungspeer für PatternInterface.Scroll wird von der GetPattern-Methode von ScrollViewerAutomationPeer zurückgegeben, der mit ListBoxAutomationPeer verknüpft ist. Aus diesem Grund gibt die IsControlElementCore-Methode von ScrollViewerAutomationPeer den Wert false zurück, sodass ScrollViewerAutomationPeer nicht in der Automatisierungsstruktur angezeigt wird.

Der Automatisierungspeer muss entsprechende Standardwerte für das Steuerelement bereitstellen. Beachten Sie, dass der XAML-Code, der auf das Steuerelement verweist, die Peerimplementierungen von Kernmethoden durch Angabe von AutomationProperties-Attributen überschreiben kann. Im folgenden XAML-Code wird beispielsweise eine Schaltfläche erstellt, die über zwei benutzerdefinierte UI-Automatisierung-Eigenschaften verfügt.

<Button AutomationProperties.Name="Special" 
    AutomationProperties.HelpText="This is a special button."/>

Implementieren von Musteranbietern

Die von einem benutzerdefinierten Anbieter implementierten Schnittstellen werden explizit deklariert, wenn sich das besitzende Element direkt von Control ableitet. Im folgenden Code wird beispielsweise ein Peer für ein Control deklariert, der einen Bereichswert implementiert.

public class RangePeer1 : FrameworkElementAutomationPeer, IRangeValueProvider { }

Wenn sich das besitzende Steuerelement von einem bestimmten Steuerelementtyp wie RangeBase ableitet, kann der Peer von einer äquivalenten abgeleiteten Peerklasse abgeleitet werden. In diesem Fall wird der Peer von RangeBaseAutomationPeer abgeleitet, der eine Basisimplementierung von IRangeValueProvider bereitstellt. Der folgende Code veranschaulicht die Deklaration eines solchen Peers.

public class RangePeer2 : RangeBaseAutomationPeer { }

Eine Beispielimplementierung finden Sie unter Beispiel für benutzerdefiniertes NumericUpDown-Steuerelement mit Unterstützung von Designs und Benutzeroberflächenautomatisierung.

Auslösen von Ereignissen

Automatisierungsclients können Automatisierungsereignisse abonnieren. Benutzerdefinierte Steuerelemente müssen Änderungen am Steuerelementzustand melden, indem sie die RaiseAutomationEvent-Methode aufrufen. Änderungen von Eigenschaftenwerten müssen durch Aufrufen der RaisePropertyChangedEvent-Methode gemeldet werden. Das folgende Codebeispiel zeigt, wie Sie das Peerobjekt aus dem Steuerelementcode abrufen und ein Ereignis durch Aufrufen einer Methode auslösen. Zur Optimierung ermittelt der Code, ob Listener für diesen Ereignistyp vorhanden sind. Indem das Ereignis nur dann ausgelöst wird, wenn Listener vorhanden sind, wird unnötige Auslastung vermieden, und das Steuerelement bleibt reaktionsfähig.

if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged))
{
    NumericUpDownAutomationPeer peer = 
        UIElementAutomationPeer.FromElement(nudCtrl) as NumericUpDownAutomationPeer;

    if (peer != null)
    {
        peer.RaisePropertyChangedEvent(
            RangeValuePatternIdentifiers.ValueProperty,
            (double)oldValue,
            (double)newValue);
    }
}

Siehe auch

Aufgaben

Beispiel für benutzerdefiniertes NumericUpDown-Steuerelement mit Unterstützung von Designs und Benutzeroberflächenautomatisierung

Beispiel für das Generieren von Testskripts

Konzepte

Übersicht über die Benutzeroberflächenautomatisierung

Implementierung eines serverseitigen Benutzeroberflächenautomatisierungs-Anbieters

Änderungsprotokoll

Datum

Versionsgeschichte

Grund

Juli 2008

Thema hinzugefügt.

Informationsergänzung.