Automatizace uživatelského rozhraní vlastního ovládacího prvku WPF

model UI Automation poskytuje jedno generalizované rozhraní, pomocí kterého můžou klienti automatizace zkoumat nebo provozovat uživatelská rozhraní různých platforem a architektur. model UI Automation umožňuje aplikacím pro kontrolu kvality (testování) i přístupnosti, jako jsou čtečky obrazovky, zkoumat prvky uživatelského rozhraní a simulovat interakci uživatelů s nimi z jiného kódu. Informace o model UI Automation na všech platformách najdete v tématu Přístupnost.

Toto téma popisuje, jak implementovat zprostředkovatele model UI Automation na straně serveru pro vlastní ovládací prvek, který běží v aplikaci WPF. WPF podporuje model UI Automation prostřednictvím stromu objektů automatizace partnerských uzlů, které paralelně paralelují strom prvků uživatelského rozhraní. Testování kódu a aplikací, které poskytují funkce přístupnosti, můžou používat objekty partnerského vztahu automatizace přímo (pro kód v procesu) nebo prostřednictvím zobecněného rozhraní poskytovaného model UI Automation.

Třídy partnerského uzlu automatizace

Ovládací prvky WPF podporují model UI Automation prostřednictvím stromu partnerských tříd, které jsou odvozeny od AutomationPeer. Podle konvence začínají názvy partnerských tříd názvem třídy ovládacího prvku a končí na "AutomationPeer". Je to například ButtonAutomationPeer třída peeru pro Button třídu ovládacího prvku. Partnerské třídy jsou zhruba ekvivalentní typům ovládacích prvků model UI Automation, ale jsou specifické pro prvky WPF. Kód automatizace, který přistupuje k aplikacím WPF prostřednictvím rozhraní model UI Automation nepoužívá partnerské vztahy automatizace přímo, ale kód automatizace ve stejném procesním prostoru může používat partnerské vztahy automatizace přímo.

Předdefinované třídy partnerského vztahu automatizace

Prvky implementují třídu partnerského uzlu automatizace, pokud přijímají aktivitu rozhraní od uživatele nebo obsahují informace potřebné uživateli aplikací čtečky obrazovky. Ne všechny vizuální prvky WPF mají partnerské vztahy automatizace. Příklady tříd, které implementují partnerské vztahy automatizace, jsou Button, TextBoxa Label. Příklady tříd, které neimplementují partnerské vztahy automatizace, jsou třídy odvozené od Decorator, jako Borderjsou , a třídy založené na Panel, jako GridCanvasa .

Základní Control třída nemá odpovídající třídu partnerského vztahu. Pokud potřebujete třídu peeru, která odpovídá vlastnímu ovládacímu prvku odvozeného z Control, měli byste odvodit vlastní třídu peer z FrameworkElementAutomationPeer.

Důležité informace o zabezpečení pro odvozené partnerské vztahy

Partnerské vztahy automatizace musí běžet v prostředí s částečnou důvěryhodností. Kód v sestavení UIAutomationClient není nakonfigurovaný tak, aby běžel v prostředí s částečnou důvěryhodností, a kód partnerského uzlu automatizace by neměl odkazovat na toto sestavení. Místo toho byste měli použít třídy v UIAutomationTypes sestavení. Měli byste například použít AutomationElementIdentifiers třídu ze sestavení UIAutomationTypes, které odpovídá AutomationElement třídě v sestavení UIAutomationClient. V kódu partnerského uzlu automatizace je bezpečné odkazovat na sestavení UIAutomationTypes.

Navigace mezi dvěma účastníky

Po vyhledání partnerského uzlu automatizace může kód v procesu procházet strom partnerského vztahu voláním objektu GetChildren a GetParent metod. Navigace mezi prvky WPF v rámci ovládacího prvku je podporována implementací partnerského GetChildrenCore uzlu metody. Systém model UI Automation tuto metodu volá k vytvoření stromu dílčích prvků obsažených v ovládacím prvku, například položky seznamu v seznamu. Výchozí UIElementAutomationPeer.GetChildrenCore metoda prochází vizuální strom prvků, aby se vytvořil strom partnerských uzlů automatizace. Vlastní ovládací prvky přepíší tuto metodu tak, aby zpřístupňovaly podřízené prvky klientům automatizace a vrátily partnerské vztahy automatizace prvků, které sdělují informace nebo umožňují interakci uživatele.

Vlastní nastavení odvozeného partnerského vztahu

Všechny třídy, které jsou odvozeny a UIElementContentElement obsahují chráněnou virtuální metodu OnCreateAutomationPeer. Volání OnCreateAutomationPeer WPF pro získání objektu partnerského uzlu automatizace pro každý ovládací prvek. Kód automatizace může použít partnerský vztah k získání informací o vlastnostech a funkcích ovládacího prvku a k simulaci interaktivního použití. Vlastní ovládací prvek, který podporuje automatizaci, musí přepsat OnCreateAutomationPeer a vrátit instanci třídy, která je odvozena z AutomationPeer. Například pokud vlastní ovládací prvek je odvozen z ButtonBase třídy, pak by měl objekt vrácený OnCreateAutomationPeer z ButtonBaseAutomationPeer.

Při implementaci vlastního ovládacího prvku je nutné přepsat "Základní" metody z třídy partnerského vztahu základní automatizace, které popisují chování jedinečné a specifické pro váš vlastní ovládací prvek.

Přepsání OnCreateAutomationPeer

Přepište metodu OnCreateAutomationPeer vlastního ovládacího prvku tak, aby vrátil objekt zprostředkovatele, který musí být odvozen přímo nebo nepřímo z AutomationPeer.

Přepsat GetPattern

Partnerské vztahy automatizace zjednodušují některé aspekty implementace poskytovatelů model UI Automation na straně serveru, ale vlastní ovládací prvky musí stále zpracovávat vzorová rozhraní. Podobně jako nezprostředkovatelé WPF podporují partnerské vztahy vzory kontroly tím, že poskytují implementace rozhraní v System.Windows.Automation.Provider oboru názvů, například IInvokeProvider. Rozhraní řídicího vzoru lze implementovat vlastním partnerským vztahem nebo jiným objektem. Implementace partnerského GetPattern uzlu vrátí objekt, který podporuje zadaný vzor. model UI Automation kód volá metodu GetPattern a určuje hodnotu výčtuPatternInterface. Přepsání GetPattern by mělo vrátit objekt, který implementuje zadaný vzor. Pokud ovládací prvek nemá vlastní implementaci vzoru, můžete volat implementaci základního GetPattern typu a načíst její implementaci nebo hodnotu null, pokud tento model není pro tento typ ovládacího prvku podporován. Například vlastní ovládací prvek NumericUpDown lze nastavit na hodnotu v rozsahu, takže jeho model UI Automation peer by implementoval IRangeValueProvider rozhraní. Následující příklad ukazuje, jak je metoda partnerského uzlu GetPattern přepsána tak, aby reagovala na PatternInterface.RangeValue hodnotu.

public override object GetPattern(PatternInterface patternInterface)
{
    if (patternInterface == PatternInterface.RangeValue)
    {
        return this;
    }
    return base.GetPattern(patternInterface);
}
Public Overrides Function GetPattern(ByVal patternInterface As PatternInterface) As Object
    If patternInterface = PatternInterface.RangeValue Then
        Return Me
    End If
    Return MyBase.GetPattern(patternInterface)
End Function

Metoda GetPattern může také zadat dílčí prvek jako zprostředkovatele vzoru. Následující kód ukazuje, jak ItemsControl přenese zpracování vzorů posouvání na partnerský vztah jeho interního ScrollViewer řízení.

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);  
}  
Public Class Class1  
    Public Overrides Function GetPattern(ByVal patternInterface__1 As PatternInterface) As Object  
        If patternInterface1 = PatternInterface.Scroll Then  
            Dim owner As ItemsControl = DirectCast(MyBase.Owner, ItemsControl)  
  
            ' ScrollHost is internal to the ItemsControl class  
            If owner.ScrollHost IsNot Nothing Then  
                Dim peer As AutomationPeer = UIElementAutomationPeer.CreatePeerForElement(owner.ScrollHost)  
                If (peer IsNot Nothing) AndAlso (TypeOf peer Is IScrollProvider) Then  
                    peer.EventsSource = Me  
                    Return DirectCast(peer, IScrollProvider)  
                End If  
            End If  
        End If  
        Return MyBase.GetPattern(patternInterface1)  
    End Function  
End Class  

Chcete-li zadat dílčí prvek pro zpracování vzorů, tento kód získá objekt subelementu, vytvoří peer pomocí CreatePeerForElement metody, nastaví EventsSource vlastnost nového partnerského uzlu na aktuální partnerský vztah a vrátí nový partnerský vztah. Nastavení EventsSource dílčího prvku brání v zobrazení dílčího prvku ve stromu partnerského vztahu automatizace a označí všechny události vyvolané dílčím prvkem, které pocházejí z ovládacího prvku zadaného v EventsSource. Ovládací ScrollViewer prvek se nezobrazuje ve stromu automatizace a posouvání událostí, které generuje, se zdá, že pocházejí z objektu ItemsControl .

Přepsání "základních" metod

Kód automatizace získá informace o vašem řízení voláním veřejných metod partnerské třídy. Pokud chcete poskytnout informace o vašem ovládacím prvku, přepište každou metodu, jejíž název končí na "Core", když se implementace řízení liší od toho, co poskytuje třída partnerského vztahu základní automatizace. Ovládací prvek musí alespoň implementovat a GetClassNameCoreGetAutomationControlTypeCore metody, jak je znázorněno v následujícím příkladu.

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

protected override AutomationControlType GetAutomationControlTypeCore()
{
    return AutomationControlType.Spinner;
}
Protected Overrides Function GetClassNameCore() As String
    Return "NumericUpDown"
End Function

Protected Overrides Function GetAutomationControlTypeCore() As AutomationControlType
    Return AutomationControlType.Spinner
End Function

GetAutomationControlTypeCore Implementace popisuje řízení vrácením ControlType hodnoty. I když se můžete vrátit ControlType.Custom, měli byste vrátit jeden z konkrétnějších typů ovládacích prvků, pokud přesně popisuje váš ovládací prvek. Návratová ControlType.Custom hodnota vyžaduje pro poskytovatele další práci, která implementuje model UI Automation, a model UI Automation klientské produkty nemohou předvídat řídicí strukturu, interakci s klávesnicí a možné vzory ovládacích prvků.

Implementujte a IsContentElementCoreIsControlElementCore metody, které označují, zda váš ovládací prvek obsahuje datový obsah nebo splňuje interaktivní roli v uživatelském rozhraní (nebo obojím). Ve výchozím nastavení vrátí obě metody true. Tato nastavení zlepšují použitelnost automatizačních nástrojů, jako jsou čtečky obrazovky, které můžou tyto metody použít k filtrování stromu automatizace. Pokud vaše GetPattern metoda přenese zpracování vzorů do partnerského uzlu subelementu, může metoda dílčího uzlu IsControlElementCore vrátit hodnotu false a skrýt partnerský vztah dílčího prvku ze stromu automatizace. Například posouvání v sadě ListBox je zpracováno pomocí ScrollViewer, a automatizace peer pro PatternInterface.Scroll je vrácena GetPattern metodou ScrollViewerAutomationPeer , která je přidružena k ListBoxAutomationPeer. IsControlElementCore Proto metoda návratu ScrollViewerAutomationPeerfalse, aby ScrollViewerAutomationPeer se nezobrazí ve stromu automatizace.

Váš partner automatizace by měl poskytovat odpovídající výchozí hodnoty pro váš ovládací prvek. Mějte na paměti, že XAML, který odkazuje na váš ovládací prvek, může přepsat implementace partnerských implementací základních metod zahrnutím AutomationProperties atributů. Například následující XAML vytvoří tlačítko, které má dvě přizpůsobené model UI Automation vlastnosti.

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

Implementace zprostředkovatelů vzorů

Rozhraní implementovaná vlastním poskytovatelem jsou explicitně deklarována, pokud vlastní prvek odvozen přímo z Control. Například následující kód deklaruje partnerský vztah pro ten Control , který implementuje hodnotu rozsahu.

public class RangePeer1 : FrameworkElementAutomationPeer, IRangeValueProvider { }  
Public Class RangePeer1  
    Inherits FrameworkElementAutomationPeer  
    Implements IRangeValueProvider  
End Class  

Pokud vlastnící ovládací prvek pochází z konkrétního typu ovládacího prvku, jako RangeBaseje například , peer může být odvozen z ekvivalentní odvozené třídy peeru. V tomto případě by partnerský vztah byl odvozen od RangeBaseAutomationPeer, který poskytuje základní implementaci IRangeValueProvider. Následující kód ukazuje deklaraci takového partnerského vztahu.

public class RangePeer2 : RangeBaseAutomationPeer { }  
Public Class RangePeer2  
    Inherits RangeBaseAutomationPeer  
End Class  

Příklad implementace najdete ve zdrojovém kódu jazyka C# nebo Visual Basic , který implementuje a využívá vlastní ovládací prvek NumericUpDown.

Vyvolávání událostí

Klienti automation se můžou přihlásit k odběru událostí automatizace. Vlastní ovládací prvky musí hlásit změny stavu řízení voláním RaiseAutomationEvent metody. Podobně, když se změní hodnota vlastnosti, zavolejte metodu RaisePropertyChangedEvent . Následující kód ukazuje, jak získat peer objekt z řídicího kódu a volat metodu pro vyvolání události. Při optimalizaci kód určuje, jestli pro tento typ události existují nějaké naslouchací procesy. Vyvolání události pouze v případě, že naslouchací procesy zabrání zbytečné režii a pomáhá ovládacímu prvku zůstat responzivní.

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

    if (peer != null)
    {
        peer.RaisePropertyChangedEvent(
            RangeValuePatternIdentifiers.ValueProperty,
            (double)oldValue,
            (double)newValue);
    }
}
If AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged) Then
    Dim peer As NumericUpDownAutomationPeer = TryCast(UIElementAutomationPeer.FromElement(nudCtrl), NumericUpDownAutomationPeer)

    If peer IsNot Nothing Then
        peer.RaisePropertyChangedEvent(RangeValuePatternIdentifiers.ValueProperty, CDbl(oldValue), CDbl(newValue))
    End If
End If

Viz také