Automatyzacja interfejsu użytkownika formantu niestandardowego WPF

automatyzacja interfejsu użytkownika udostępnia jeden, uogólniony interfejs, którego klienci automatyzacji mogą używać do sprawdzania lub obsługi interfejsów użytkownika różnych platform i platform. automatyzacja interfejsu użytkownika umożliwia korzystanie zarówno z kodu kontroli jakości (testu) jak i aplikacji ułatwień dostępu, takich jak czytniki zawartości ekranu w celu zbadania elementów interfejsu użytkownika i symulowania interakcji użytkownika z nimi z innego kodu. Aby uzyskać informacje o automatyzacja interfejsu użytkownika na wszystkich platformach, zobacz Ułatwienia dostępu.

W tym temacie opisano sposób implementowania dostawcy automatyzacja interfejsu użytkownika po stronie serwera dla niestandardowej kontrolki uruchamianej w aplikacji WPF. Platforma WPF obsługuje automatyzacja interfejsu użytkownika za pomocą drzewa obiektów automatyzacji równorzędnej, które są równoległe do drzewa elementów interfejsu użytkownika. Testowanie kodu i aplikacji, które zapewniają funkcje ułatwień dostępu, mogą używać obiektów równorzędnych automatyzacji bezpośrednio (dla kodu w procesie) lub za pośrednictwem uogólnioowanego interfejsu udostępnianego przez automatyzacja interfejsu użytkownika.

Klasy równorzędne automatyzacji

Kontrolki WPF obsługują automatyzacja interfejsu użytkownika za pomocą drzewa klas równorzędnych, które pochodzą z AutomationPeerklasy . Zgodnie z konwencją nazwy klas równorzędnych zaczynają się od nazwy klasy sterującej i kończą się ciągiem "AutomationPeer". Na przykład ButtonAutomationPeer jest klasą równorzędną dla klasy kontrolnej Button . Klasy równorzędne są w przybliżeniu równoważne automatyzacja interfejsu użytkownika typom kontrolek, ale są specyficzne dla elementów WPF. Kod automatyzacji, który uzyskuje dostęp do aplikacji WPF za pośrednictwem interfejsu automatyzacja interfejsu użytkownika, nie korzysta bezpośrednio z elementów równorzędnych automatyzacji, ale kod automatyzacji w tej samej przestrzeni procesowej może korzystać bezpośrednio z elementów równorzędnych automatyzacji.

Wbudowane klasy równorzędne automatyzacji

Elementy implementują klasę równorzędną automatyzacji, jeśli akceptują działanie interfejsu od użytkownika lub zawierają informacje wymagane przez użytkowników aplikacji czytnika zawartości ekranu. Nie wszystkie elementy wizualne WPF mają równorzędne elementy automatyzacji. Przykłady klas implementujących równorzędne automatyzacji to Button, TextBoxi Label. Przykłady klas, które nie implementują elementów równorzędnych automatyzacji, to klasy pochodzące z Decoratorklasy , takich jak , i oparte na Panel, takich jak BorderGrid i Canvas.

Klasa bazowa Control nie ma odpowiedniej klasy równorzędnej. Jeśli potrzebujesz klasy równorzędnej odpowiadającej kontrolce niestandardowej pochodzącej z Controlklasy , należy utworzyć niestandardową klasę równorzędną z FrameworkElementAutomationPeerklasy .

Zagadnienia dotyczące zabezpieczeń dla pochodnych elementów równorzędnych

Równorzędne elementy równorzędne usługi Automation muszą działać w środowisku częściowo zaufanym. Kod w zestawie UIAutomationClient nie jest skonfigurowany do uruchamiania w środowisku częściowo zaufania, a kod elementu równorzędnego automatyzacji nie powinien odwoływać się do tego zestawu. Zamiast tego należy użyć klas w zestawie UIAutomationTypes. Na przykład należy użyć AutomationElementIdentifiers klasy z zestawu UIAutomationTypes, który odpowiada AutomationElement klasie w zestawie UIAutomationClient. Można bezpiecznie odwołać się do zestawu UIAutomationTypes w kodzie równorzędnym automatyzacji.

Nawigacja równorzędna

Po zlokalizowaniu elementu równorzędnego automatyzacji kod w procesie może nawigować po drzewie równorzędnym, wywołując metody i GetParent obiektuGetChildren. Nawigacja między elementami WPF w kontrolce jest obsługiwana przez implementację metody elementu równorzędnego GetChildrenCore . System automatyzacja interfejsu użytkownika wywołuje tę metodę, aby utworzyć drzewo podelementów zawartych w kontrolce, na przykład elementy listy w polu listy. UIElementAutomationPeer.GetChildrenCore Domyślna metoda przechodzi przez drzewo wizualne elementów w celu utworzenia drzewa elementów równorzędnych automatyzacji. Kontrolki niestandardowe zastępują tę metodę, aby uwidocznić elementy podrzędne klientom automatyzacji, zwracając równorzędne elementy automatyzacji, które przekazują informacje lub umożliwiają interakcję użytkownika.

Dostosowania w pochodnym elemencie równorzędnym

Wszystkie klasy pochodzące z UIElement i ContentElement zawierają chronioną metodę OnCreateAutomationPeerwirtualną . Wywołania OnCreateAutomationPeer WPF w celu pobrania obiektu równorzędnego automatyzacji dla każdej kontrolki. Kod automatyzacji może używać elementu równorzędnego do uzyskiwania informacji o cechach i funkcjach kontrolki oraz symulowaniu interakcyjnego użycia. Kontrolka niestandardowa obsługująca automatyzację musi zastąpić OnCreateAutomationPeer i zwrócić wystąpienie klasy pochodzącej z AutomationPeerklasy . Jeśli na przykład kontrolka niestandardowa pochodzi z ButtonBase klasy, obiekt zwrócony przez OnCreateAutomationPeer powinien pochodzić z klasy ButtonBaseAutomationPeer.

Podczas implementowania kontrolki niestandardowej należy zastąpić metody "Core" z podstawowej klasy równorzędnej automatyzacji, które opisują zachowanie unikatowe i specyficzne dla niestandardowej kontrolki.

Zastąpij metodę OnCreateAutomationPeer

Zastąpij metodę kontrolki niestandardowej OnCreateAutomationPeer , aby zwracała obiekt dostawcy, który musi pochodzić bezpośrednio lub pośrednio z AutomationPeerobiektu .

Zastąp polecenie GetPattern

Równorzędne elementy równorzędne automatyzacji upraszczają niektóre aspekty implementacji dostawców automatyzacja interfejsu użytkownika po stronie serwera, ale niestandardowe elementy równorzędne automatyzacji muszą nadal obsługiwać interfejsy wzorca. Podobnie jak dostawcy innych niż WPF, elementy równorzędne obsługują wzorce sterowania, zapewniając implementacje interfejsów w System.Windows.Automation.Provider przestrzeni nazw, takie jak IInvokeProvider. Interfejsy wzorca sterowania można zaimplementować za pomocą samego elementu równorzędnego lub innego obiektu. Implementacja elementu równorzędnego GetPattern zwraca obiekt, który obsługuje określony wzorzec. automatyzacja interfejsu użytkownika kod wywołuje metodę GetPatternPatternInterface i określa wartość wyliczenia. Zastąpienie GetPattern elementu powinno zwrócić obiekt, który implementuje określony wzorzec. Jeśli kontrolka nie ma niestandardowej implementacji wzorca, możesz wywołać implementację GetPattern typu podstawowego, aby pobrać jego implementację lub wartość null, jeśli wzorzec nie jest obsługiwany dla tego typu kontrolki. Na przykład niestandardową kontrolkę NumericUpDown można ustawić na wartość w zakresie, więc jej element równorzędny automatyzacja interfejsu użytkownika implementuje IRangeValueProvider interfejs. W poniższym przykładzie pokazano, jak metoda elementu równorzędnego GetPattern jest zastępowana w celu reagowania na PatternInterface.RangeValue wartość.

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 może również określać podelement jako dostawcę wzorca. Poniższy kod przedstawia sposób ItemsControl przenoszenia obsługi wzorca przewijania do elementu równorzędnego kontroli wewnętrznej ScrollViewer .

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  

Aby określić podelement obsługi wzorca, ten kod pobiera obiekt podelementu, tworzy element równorzędny przy użyciu CreatePeerForElement metody , ustawia EventsSource właściwość nowego elementu równorzędnego dla bieżącego elementu równorzędnego i zwraca nowy element równorzędny. Ustawienie EventsSource elementu podrzędnego uniemożliwia wyświetlenie podelementu w drzewie elementów równorzędnych automatyzacji i wyznacza wszystkie zdarzenia zgłaszane przez podelement jako pochodzące z kontrolki określonej w EventsSourceelemencie . Kontrolka nie jest wyświetlana ScrollViewer w drzewie automatyzacji i przewijając zdarzenia, które generuje, wydają się pochodzić z ItemsControl obiektu.

Zastępowanie metod "Core"

Kod automatyzacji pobiera informacje o kontrolce, wywołując publiczne metody klasy równorzędnej. Aby podać informacje o kontrolce, zastąpij każdą metodę, której nazwa kończy się ciągiem "Core", gdy implementacja kontrolki różni się od tej udostępnionej przez klasę równorzędną automatyzacji podstawowej. Co najmniej kontrolka musi implementować GetClassNameCore metody i GetAutomationControlTypeCore , jak pokazano w poniższym przykładzie.

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

Implementacja kontrolki GetAutomationControlTypeCore opisuje twoją kontrolkę ControlType , zwracając wartość. Mimo że można zwrócić element , należy zwrócić ControlType.Customjeden z bardziej szczegółowych typów kontrolek, jeśli dokładnie opisuje kontrolkę. Wartość zwracana wymaga dodatkowej ControlType.Custom pracy dla dostawcy w celu zaimplementowania automatyzacja interfejsu użytkownika, a automatyzacja interfejsu użytkownika produkty klienckie nie mogą przewidzieć struktury sterowania, interakcji klawiatury i możliwych wzorców sterowania.

Zaimplementuj IsContentElementCore metody i IsControlElementCore , aby wskazać, czy kontrolka zawiera zawartość danych, czy spełnia interaktywną rolę w interfejsie użytkownika (lub obu tych). Domyślnie obie metody zwracają wartość true. Te ustawienia zwiększają użyteczność narzędzi automatyzacji, takich jak czytniki zawartości ekranu, które mogą używać tych metod do filtrowania drzewa automatyzacji. GetPattern Jeśli metoda przenosi obsługę wzorca do elementu równorzędnego podelementów, metoda elementu równorzędnego IsControlElementCore podelementów może zwrócić wartość false, aby ukryć element równorzędny podelementów z drzewa automatyzacji. Na przykład przewijanie elementu ListBox jest obsługiwane przez ScrollViewerelement , a element równorzędny PatternInterface.Scroll automatyzacji dla elementu jest zwracany przez GetPattern metodę ScrollViewerAutomationPeer , która jest skojarzona z elementem ListBoxAutomationPeer. IsControlElementCore W związku z ScrollViewerAutomationPeer tym metoda zwraca falsewartość , tak aby ScrollViewerAutomationPeer element nie był wyświetlany w drzewie automatyzacji.

Element równorzędny automatyzacji powinien podać odpowiednie wartości domyślne dla kontrolki. Należy pamiętać, że język XAML, który odwołuje się do kontrolki, może zastąpić implementacje równorzędne metod podstawowych przez dołączenie AutomationProperties atrybutów. Na przykład poniższy kod XAML tworzy przycisk z dwoma dostosowanymi właściwościami automatyzacja interfejsu użytkownika.

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

Implementowanie dostawców wzorców

Interfejsy implementowane przez dostawcę niestandardowego są jawnie deklarowane, jeśli element będący właścicielem pochodzi bezpośrednio z Controlelementu . Na przykład poniższy kod deklaruje element równorzędny elementu równorzędnego Control , który implementuje wartość zakresu.

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

Jeśli kontrolka będąca właścicielem pochodzi z określonego typu kontrolki, takiego jak RangeBase, element równorzędny może pochodzić z równoważnej klasy równorzędnej pochodnej. W tym przypadku element równorzędny pochodzi z RangeBaseAutomationPeerklasy , która dostarcza podstawową implementację IRangeValueProviderklasy . Poniższy kod przedstawia deklarację takiego elementu równorzędnego.

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

Aby zapoznać się z przykładową implementacją, zobacz kod źródłowy języka C# lub Visual Basic , który implementuje i używa niestandardowej kontrolki NumericUpDown.

Wywoływanie zdarzeń

Klienci usługi Automation mogą subskrybować zdarzenia automatyzacji. Kontrolki niestandardowe muszą zgłaszać zmiany stanu sterowania przez wywołanie RaiseAutomationEvent metody . Podobnie, gdy wartość właściwości ulegnie zmianie, wywołaj metodę RaisePropertyChangedEvent . Poniższy kod pokazuje, jak uzyskać obiekt elementu równorzędnego z poziomu kodu sterującego i wywołać metodę w celu wywołania zdarzenia. W ramach optymalizacji kod określa, czy istnieją odbiorniki dla tego typu zdarzenia. Podnoszenie zdarzenia tylko wtedy, gdy istnieją odbiorniki unika niepotrzebnych obciążeń i pomaga w utrzymaniu reakcji kontrolki.

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

Zobacz też