Partilhar via


Automação da interface do usuário de um controle personalizado do WPF

Atualização: December 2010

Microsoft UI AutomationFornece uma interface única e generalizada que os clientes podem usar para examinar ou operar as interfaces de usuário de uma variedade de plataformas e estruturas de automação. UI Automationpermite que o código de controle de qualidade (teste) e de aplicativos de acessibilidade, como leitores de tela para examinar os elementos de interface de usuário e simular a interação do usuário com eles de outro código. Para obter informações sobre UI Automation em todas as plataformas, consulte Acessibilidade.

Este tópico descreve como implementar um servidor provedor de automação da interface do usuário para um controle personalizado que é executado em um aplicativo WPF. Oferece suporte a WPF UI Automation por meio de uma árvore de objetos de automação de mesmo nível que iguala a árvore de elementos de interface do usuário. Testar o código e aplicativos que fornecem recursos de acessibilidade podem usar objetos de mesmo nível de automação diretamente (para código de em processo) ou por meio da interface generalizada fornecida pelo UI Automation.

Este tópico contém as seguintes seções.

  • Classes de mesmo nível de automação
  • Classes internas de mesmo nível de automação
  • Considerações de segurança para os Peers derivadas
  • Peer Navigation
  • Personalizações de um Peer derivada
  • Tópicos relacionados

Classes de mesmo nível de automação

Suporte de controles do WPF UI Automation por meio de uma árvore de classes de mesmo nível que derivam de AutomationPeer. Por convenção, os nomes de classe de mesmo nível começam com o nome de classe de controle e terminam com "automationpeer". Por exemplo, ButtonAutomationPeer é a classe de mesmo nível para o Button classe de controle. As classes de mesmo nível são basicamente equivalentes ao UI Automation tipos de controle, mas que são específicas para WPF elementos. O código de automação que acessa os aplicativos WPF por meio de UI Automation interface não usar diretamente os peers de automação, mas o código de automação no mesmo espaço de processo pode usar diretamente os peers de automação.

Classes internas de mesmo nível de automação

Elementos de implementam uma classe de mesmo nível de automação, se eles aceitam a atividade de interface do usuário, ou se elas contiverem informações necessárias aos usuários de aplicativos do leitor de tela. Nem todos os elementos visuais do WPF tem pares de automação. São exemplos de classes que implementam os peers de automação Button, TextBox, e Label. Exemplos de classes que implementam os peers de automação são classes que derivam de Decorator, como Bordere classes com base em Panel, como Grid e Canvas.

Base da Control classe não tem uma classe de mesmo nível correspondente. Se você precisar de uma classe de mesmo nível para corresponder a um controle personalizado que deriva do Control, você deve derivar a classe personalizada de ponto de FrameworkElementAutomationPeer.

Considerações de segurança para os Peers derivadas

Peers de automação devem ser executado em um ambiente de confiança parcial. O código no assembly UIAutomationClient não está configurado para executar em um ambiente de confiança parcial e código de automação de mesmo nível não deve referenciar o assembly. Em vez disso, você deve usar as classes no assembly UIAutomationTypes. Por exemplo, você deve usar o AutomationElementIdentifiers a classe do assembly UIAutomationTypes, que corresponde do AutomationElement classe no assembly UIAutomationClient. É seguro referenciar o assembly UIAutomationTypes no código de mesmo nível de automação.

Peer Navigation

Após localizar um ponto de automação, código de processo pode navegar na árvore de peer chamando o objeto GetChildren e GetParent métodos. Navegação entre WPF elementos dentro de um controle é suportado pela implementação do ponto de GetChildrenCore método. O sistema de automação da interface do usuário chama esse método para criar uma árvore de subelementos contido em um controle; Por exemplo, lista de itens em uma caixa de listagem. O padrão UIElementAutomationPeer.GetChildrenCore método percorre a árvore visual de elementos para criar a árvore de peers de automação. Controles personalizados substituem esse método para expor elementos de filhos para clientes de automação, retornando os peers de automação de elementos que transmitem informações ou permitem a interação do usuário.

Personalizações de um Peer derivada

Todas as classes que derivam de UIElement e ContentElement contém o método virtual protegido OnCreateAutomationPeer. Chamadas WPF OnCreateAutomationPeer para obter o objeto de mesmo nível de automação para cada controle. O código de automação pode usar o peer para obter informações sobre recursos e características de um controle e simular o uso interativo. Um controle personalizado que oferece suporte à automação deve substituir OnCreateAutomationPeer e retornar uma instância de uma classe que deriva de AutomationPeer. Por exemplo, se um controle personalizado deriva do ButtonBase classe, em seguida, o objeto retornado por OnCreateAutomationPeer deve derivar de ButtonBaseAutomationPeer.

Ao implementar um controle personalizado, você deve substituir o "núcleo" métodos da classe base automação ponto que descrevem o comportamento exclusivo e específico de seu controle personalizado.

Substituir OnCreateAutomationPeer

Substituir o OnCreateAutomationPeer método para seu controle personalizado, de modo que ele retorna o objeto de provedor, que deve derivar direta ou indiretamente de AutomationPeer.

Substituir GetPattern

Automação de peers simplificam alguns aspectos de implementação do lado do servidor UI Automation ainda devem lidar com os provedores, mas os peers de automação do controle personalizado padrão de interfaces. Como provedores não WPF, pontos oferecem suporte a padrões de controle, fornecendo implementações de interfaces na System.Windows.Automation.Provider espaço para nome, como IInvokeProvider. As interfaces padrão do controle podem ser implementadas pelo próprio correspondente ou por outro objeto. The peer's implementation of GetPattern returns the object that supports the specified pattern. UI Automationo código chama o GetPattern método e especifica um PatternInterface valor de enumeração. A substituição do GetPattern deve retornar o objeto que implementa o padrão especificado. Se o controle não tem uma implementação personalizada de um padrão, você pode chamar a implementação do tipo base de GetPattern para recuperar a sua implementação ou a null se não há suporte para o padrão para esse tipo de controle. Por exemplo, um controle personalizado do NumericUpDown pode ser definido para um valor em um intervalo, para que seu UI Automation peer implementaria a IRangeValueProvider interface. A exemplo a seguir mostra como o peer GetPattern método é substituído para responder a uma PatternInterface.RangeValue valor.

        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
public override object GetPattern(PatternInterface patternInterface)
{
    if (patternInterface == PatternInterface.RangeValue)
    {
        return this;
    }
    return base.GetPattern(patternInterface);
}

A GetPattern método também pode especificar um subelemento como um provedor padrão. O seguinte código mostra como ItemsControl padrão para o ponto de interna de manipulação de rolar transferências de ScrollViewer de controle.

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

Para especificar um subelemento para tratamento de padrão, esse código obtém o objeto subelemento, cria um peer usando o CreatePeerForElement método, define o EventsSource propriedade do novo ponto a ponto atual e retorna o novo ponto. Definindo EventsSource em um subelemento impede o subelemento que aparecem na árvore de mesmo nível de automação e designa todos os eventos gerados pelo subelemento como originado do controle especificado em EventsSource. O ScrollViewer controle não aparece na árvore de automação e eventos de rolagem que ele gera pareçam originadas do ItemsControl objeto.

Substituir o "Núcleo" Métodos

Código de automação obtém informações sobre o seu controle chamando métodos públicos da classe correspondente. Para fornecer informações sobre o seu controle, substituir cada método cujo nome termina com "Núcleo" Quando a implementação do controle difere do fornecido pela classe base automação ponto a ponto. No mínimo, seu controle deve implementar a GetClassNameCore e GetAutomationControlTypeCore métodos, conforme mostrado no exemplo a seguir.

        Protected Overrides Function GetClassNameCore() As String
            Return "NumericUpDown"
        End Function

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

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

A implementação do GetAutomationControlTypeCore descreve o seu controle, retornando um ControlType valor. Embora você possa retornar ControlType.Custom, você deve retornar um dos tipos de controle mais específicos se ele descreve precisamente seu controle. Um valor de retorno de ControlType.Custom requer trabalho extra para o provedor de implementar UI Automation, e UI Automation produtos de cliente não conseguem antecipar a estrutura de controle, a interação do teclado e padrões de controle possíveis.

Implementar a IsContentElementCore e IsControlElementCore métodos para indicar se o seu controle contém conteúdo de dados ou preenche uma função interativa na interface do usuário (ou ambos). Por padrão, ambos os métodos retornam true. Essas configurações melhoram a usabilidade das ferramentas de automação, como leitores de tela, que podem usar esses métodos para filtrar a árvore de automação. Se sua GetPattern método padrão de transferências tratamento a um peer subelemento, o peer de subelemento IsControlElementCore método pode retornar false para ocultar a subelemento ponto a ponto da árvore de automação. Por exemplo, a rolagem em um ListBox é tratado por um ScrollViewere o ponto de automação para PatternInterface.Scroll retornado pelo GetPattern método o ScrollViewerAutomationPeer que está associado a ListBoxAutomationPeer.Portanto, o IsControlElementCore método o ScrollViewerAutomationPeer retorna false, de modo que o ScrollViewerAutomationPeer não aparece na árvore de automação.

O ponto de automação deve fornecer valores padrão apropriado para seu controle. Observação XAML que faz referência a seu controle pode substituir o suas implementações de mesmo nível dos métodos de núcleo, incluindo AutomationProperties atributos. Por exemplo, o seguinte XAML cria um botão que tem dois personalizado UI Automation Propriedades.

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

Implementar provedores de padrão

The interfaces implemented by a custom provider are explicitly declared if the owning element derives directly from Control. For example, the following code declares a peer for a Control that implements a range value.

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

If the owning control derives from a specific type of control such as RangeBase, the peer can be derived from an equivalent derived peer class. In this case, the peer would derive from RangeBaseAutomationPeer, which supplies a base implementation of IRangeValueProvider. The following code shows the declaration of such a peer.

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

Para um exemplo de implementação, consulte NumericUpDown Custom Control com tema e exemplo de suporte de automação da interface do usuário.

Elevar eventos

Clientes de automação podem assinar eventos de automação. Controles personalizados devem informar alterações de estado de controle chamando o RaiseAutomationEvent método. Da mesma forma, quando um valor de propriedade é alterado, chamar o RaisePropertyChangedEvent método. O código a seguir mostra como obter o objeto correspondente a partir de código de controle e chamar um método para elevar um evento. Como uma otimização, o código determina que se houver qualquer ouvintes para esse tipo de evento. Disparar o evento somente quando houver ouvintes evita sobrecarga desnecessária e ajuda o controle permaneça responsivo.

            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
if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged))
{
    NumericUpDownAutomationPeer peer = 
        UIElementAutomationPeer.FromElement(nudCtrl) as NumericUpDownAutomationPeer;

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

Consulte também

Conceitos

UI Automation Overview

Implementação de Provedor de Automação de IU no Servidor

Outros recursos

Controle de NumericUpDown personalizado com tema e exemplo de suporte de automação da interface do usuário

Histórico de alterações

Date

History

Motivo

December 2010

Exemplos de Visual Basic ausentes adicionados.

Correção de bug de conteúdo.

Julho de 2008

Tópico adicional.

Aprimoramento de informações.