Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A Automação de Interface do Usuário fornece uma interface única e generalizada que os clientes de automação podem usar para examinar ou operar as interfaces do usuário de uma variedade de plataformas e estruturas. A Automação de Interface do Usuário permite que o código de garantia de qualidade (teste) e aplicativos de acessibilidade, como leitores de tela, examinem os elementos da interface do usuário e simulem a interação do usuário com eles de outro código. Para obter informações sobre a Automação da Interface do Usuário em todas as plataformas, consulte Acessibilidade.
Este tópico descreve como implementar um provedor de Automação de Interface do Usuário do lado do servidor para um controle personalizado executado em um aplicativo WPF. O WPF dá suporte à Automação de Interface do Usuário por meio de uma árvore de objetos de automação par que faz paralelo com a árvore de elementos da interface do usuário. O código de teste e os aplicativos que fornecem recursos de acessibilidade podem usar objetos pares de automação diretamente (para código em processo) ou por meio da interface generalizada fornecida pela Automação da Interface do Usuário.
Classes de par de automação
Os controles do WPF dão suporte à Automação de Interface do Usuário por meio de uma árvore de classes pares que derivam de AutomationPeer. Por convenção, os nomes de classe par começam com o nome da classe de controle e terminam com "AutomationPeer". Por exemplo, ButtonAutomationPeer é a classe par da Button classe de controle. As classes par são aproximadamente equivalentes aos tipos de controle de Automação da Interface do Usuário, mas são específicas para elementos do WPF. O código de automação que acessa aplicativos WPF por meio da interface de Automação da Interface do Usuário não usa diretamente os pares de automação, mas o código de automação no mesmo espaço de processo pode usar os pares de automação diretamente.
Classes internas de Automation Peer
Os elementos implementam uma classe de par de automação se aceitam a atividade de interface do usuário ou se contêm informações necessárias para os usuários de aplicativos de leitor de tela. Nem todos os elementos visuais do WPF têm pares de automação. Exemplos de classes que implementam pares de automação são Button, TextBoxe Label. Exemplos de classes que não implementam pares de automação são classes que derivam de Decorator, como Border, e classes baseadas em Panel, como Grid e Canvas.
A classe base Control não tem uma classe de par correspondente. Se você precisar de uma classe de par para corresponder a um controle personalizado que deriva de Control, deverá derivar a classe de par personalizada de FrameworkElementAutomationPeer.
Considerações de segurança para pares derivados
Os pares de automação devem ser executados em um ambiente de confiança parcial. O código no assembly UIAutomationClient não está configurado para ser executado em um ambiente de confiança parcial e o código par de automação não deve referenciar esse assembly. Em vez disso, você deve usar as classes no assembly UIAutomationTypes. Por exemplo, você deve usar a AutomationElementIdentifiers classe do assembly UIAutomationTypes, que corresponde à AutomationElement classe no assembly UIAutomationClient. É seguro referenciar o assembly UIAutomationTypes no código par de automação.
Navegação par
Depois de localizar um par de automação, o código em processo pode navegar na árvore de pares chamando os métodos e GetChildren o GetParent objeto. A navegação entre elementos do WPF em um controle é suportada pela implementação do método GetChildrenCore por um dos componentes. O sistema de Automação da Interface do Usuário chama esse método para criar uma árvore de subelementos contidos em um controle; por exemplo, listar itens em uma caixa de listagem. O método padrão UIElementAutomationPeer.GetChildrenCore percorre a árvore visual de elementos para criar a árvore de pares de automação. Os controles personalizados substituem esse método para expor elementos filhos de forma que clientes de automação possam acessá-los, retornando os pares de automação dos elementos que transmitem informações ou permitem a interação do usuário.
Personalizações em um par derivado
Todas as classes que derivam de UIElement e ContentElement contêm o método protegido virtual OnCreateAutomationPeer. O WPF chama OnCreateAutomationPeer para obter o objeto peer de automação para cada controle. O código de automação pode usar o homólogo para obter informações sobre as características e recursos de um controle e simular a utilização interativa. Um controle personalizado que dá suporte à automação deve substituir OnCreateAutomationPeer e retornar uma instância de uma classe que deriva de AutomationPeer. Por exemplo, se um controle personalizado derivar da classe ButtonBase, então o objeto retornado por OnCreateAutomationPeer deve derivar de ButtonBaseAutomationPeer.
Ao implementar um controle personalizado, você deve sobrescrever os métodos "Core" da classe par de automação base que descrevem o comportamento exclusivo e específico ao seu controle personalizado.
Sobrescrever OnCreateAutomationPeer
Sobrescreva o método do controle personalizado OnCreateAutomationPeer para retornar o objeto do provedor, que deve ser derivado direta ou indiretamente de AutomationPeer.
Sobrescrever GetPattern
Os pares de automação simplificam alguns aspectos de implementação dos provedores de Automação de Interface do Usuário do lado do servidor, mas os pares de automação de controle personalizado ainda devem lidar com interfaces de padrão. Como provedores não WPF, os pares dão suporte a padrões de controle fornecendo implementações de interfaces no System.Windows.Automation.Provider namespace, como IInvokeProvider. As interfaces de padrão de controle podem ser implementadas pelo par em si ou por outro objeto. A implementação do GetPattern par retorna o objeto que dá suporte ao padrão especificado. O código de Automação da Interface do Usuário chama o GetPattern método e especifica um PatternInterface valor de enumeração. Sua substituição GetPattern deve retornar o objeto que implementa o padrão especificado. Se o controle não tiver uma implementação personalizada de um padrão, você poderá chamar a implementação do tipo base de GetPattern para recuperar sua implementação, ou null, caso o padrão não seja suportado por esse tipo de controle. Por exemplo, um controle NumericUpDown personalizado pode ser definido como um valor dentro de um determinado intervalo, de modo que seu par de Automação de Interface do Usuário implementa a IRangeValueProvider interface. O exemplo a seguir mostra como o método do GetPattern par é substituído para responder a um valor PatternInterface.RangeValue.
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
Um GetPattern método também pode especificar um subelemento como um provedor padrão. O código a seguir mostra como ItemsControl transfere o tratamento de padrões de rolagem para o par de seu controle interno 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
Para especificar um subelemento para tratamento de padrões, esse código obtém o objeto de subelemento, cria um par usando o CreatePeerForElement método, define a EventsSource propriedade do novo par para o par atual e retorna o novo par. A configuração EventsSource em um subelemento impede que o subelemento apareça na árvore de pares de automação e designa todos os eventos gerados pelo subelemento como originários do controle especificado em EventsSource. O ScrollViewer controle não aparece na árvore de automação e os eventos de rolagem gerados por ele parecem ter origem no ItemsControl objeto.
Substituir métodos "Core"
O código de automação obtém informações sobre seu controle chamando métodos públicos de uma classe correspondente. Para fornecer informações sobre seu controle, substitua cada método cujo nome termina com "Core" quando a implementação do controle for diferente daquela fornecida pela classe par de automação base. No mínimo, seu controle deve implementar os métodos GetClassNameCore e GetAutomationControlTypeCore, conforme mostrado no exemplo a seguir.
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
A implementação de GetAutomationControlTypeCore descreve seu controle ao retornar um valor ControlType. Embora você possa retornar ControlType.Custom, você deverá retornar um dos tipos de controle mais específicos se ele descrever com precisão seu controle. Um valor retornado de ControlType.Custom requer um trabalho extra para o provedor implementar a Automação da IU, e os produtos cliente da Automação da IU não conseguem antecipar a estrutura de controle, a interação do teclado e os possíveis padrões de controle.
Implemente os IsContentElementCore métodos e IsControlElementCore para indicar se o controle contém conteúdo de dados ou atende a 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 de ferramentas de automação, como leitores de tela, que podem usar esses métodos para filtrar a árvore de automação. Se o método GetPattern transferir o tratamento de padrões para um ponto de subelemento, o método do ponto de subelemento IsControlElementCore poderá retornar false para ocultar o ponto de subelemento da árvore de automação. Por exemplo, rolar em um ListBox é tratado por um ScrollViewer, e o par de automação para PatternInterface.Scroll é retornado pelo método GetPattern do ScrollViewerAutomationPeer associado ao ListBoxAutomationPeer. Portanto, o método IsControlElementCore do ScrollViewerAutomationPeer retorna false, garantindo que o ScrollViewerAutomationPeer não apareça na árvore de automação.
Seu par de automação deve fornecer valores padrão apropriados para seu controle. Observe que o XAML que faz referência ao seu controle pode substituir as implementações de métodos principais pelos pares ao incluir atributos AutomationProperties. Por exemplo, o XAML a seguir cria um botão que tem duas propriedades personalizadas da Automação de Interface do Usuário.
<Button AutomationProperties.Name="Special"
AutomationProperties.HelpText="This is a special button."/>
Implementar provedores de padrões
As interfaces implementadas por um provedor personalizado são declaradas explicitamente se o elemento proprietário deriva diretamente de Control. Por exemplo, o código a seguir declara um parceiro para um Control que implementa um valor de intervalo.
public class RangePeer1 : FrameworkElementAutomationPeer, IRangeValueProvider { }
Public Class RangePeer1
Inherits FrameworkElementAutomationPeer
Implements IRangeValueProvider
End Class
Se o controle proprietário derivar de um tipo específico de controle, como RangeBase, o par pode ser derivado de uma classe de par derivada equivalente. Nesse caso, o par originaria-se de RangeBaseAutomationPeer, que fornece uma implementação base de IRangeValueProvider. O código a seguir mostra a declaração desse par.
public class RangePeer2 : RangeBaseAutomationPeer { }
Public Class RangePeer2
Inherits RangeBaseAutomationPeer
End Class
Para obter uma implementação de exemplo, consulte o código-fonte C# ou Visual Basic que implementa e consome um controle personalizado NumericUpDown.
Gerar eventos
Os clientes de automação podem assinar eventos de automação. Os controles personalizados devem relatar alterações no estado de controle chamando o RaiseAutomationEvent método. Da mesma forma, quando um valor de propriedade é alterado, chame o RaisePropertyChangedEvent método. O código a seguir mostra como obter o objeto par de dentro do código de controle e chamar um método para gerar um evento. Como otimização, o código determina se há ouvintes para esse tipo de evento. Elevar o evento somente quando houver ouvintes evita sobrecarga desnecessária e ajuda o controle a permanecer responsivo.
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
Consulte também
- Visão geral da automação da interface do usuário
- Implementação do provedor de automação da interface do usuárioServer-Side
- Controle personalizado NumericUpDown (C#) no GitHub
- Controle personalizado NumericUpDown (Visual Basic) no GitHub
.NET Desktop feedback