Поделиться через


Модель автоматизации пользовательского интерфейса пользовательского элемента управления WPF

Обновлен: Июль 2008

Модель автоматизации пользовательского интерфейса Майкрософт предоставляет единый, общий интерфейс, который могут использовать клиенты автоматизации для проверки или работы интерфейсов пользователей различных платформ и структур. Модель автоматизации пользовательского интерфейса обеспечивает проверку качества (тестирование) кода и доступность приложений, таких как средства чтения с экрана, для проверки элементов пользовательского интерфейса и моделирования взаимодействия с ним пользователя из другого кода. Сведения о Модель автоматизации пользовательского интерфейса для всех платформ см. в разделе Специальные возможности.

В этом разделе описывается, как реализовать на стороне сервера поставщик модели автоматизации пользовательского интерфейса для пользовательского элемента управления, работающего в приложении WPF. WPF поддерживает Модель автоматизации пользовательского интерфейса посредством дерева одноранговых объектов автоматизации, которое копирует дерево элементов интерфейса пользователя. Тестовый код и приложения, обеспечивающие средства доступности, могут использовать одноранговые объекты автоматизации напрямую (для внутрипроцессного кода) или через общий интерфейс, предоставляемый Модель автоматизации пользовательского интерфейса.

В этом разделе содержатся следующие подразделы.

  • Одноранговые классы автоматизации
  • Встроенные одноранговые классы автоматизации
  • Вопросы безопасности для производных одноранговых классов
  • Навигация между одноранговыми классами
  • Настройки в производном одноранговом классе
  • Связанные разделы

Одноранговые классы автоматизации

Элементы управления WPF поддерживают Модель автоматизации пользовательского интерфейса через дерево одноранговых классов, производных от класса AutomationPeer. Как правило, имена одноранговых классов начинаются с имени класса элемента управления и заканчиваются "AutomationPeer". Например, ButtonAutomationPeer является одноранговым классом для класса элемента управления Button. Одноранговые классы примерно эквивалентны типам элементов управления Модель автоматизации пользовательского интерфейса, но точно соответствуют элементам WPF. Код автоматизации, обращающийся к приложениям WPF через интерфейс Модель автоматизации пользовательского интерфейса, не использует одноранговые классы автоматизации напрямую, но код автоматизации в том же пространстве процесса может их использовать напрямую.

Встроенные одноранговые классы автоматизации

Элементы реализуют одноранговый класс автоматизации, если они принимают действие интерфейса от пользователя или содержат сведения, требуемые пользователю приложений чтения с экрана. Не все визуальные элементы WPF имеют одноранговые классы автоматизации. Примерами классов, реализующих одноранговые автоматизации, являются Button, TextBox и Label. Примерами классов, не реализующих одноранговые автоматизации, являются классы, производные от Decorator, такие как Border, и классы, основанные на Panel, такие как Grid и Canvas.

Базовый класс Control не имеет соответствующего однорангового класса. Если требуется, чтобы одноранговый класс соответствовал пользовательскому элементу управления, производному от Control, следует производить одноранговый класс от FrameworkElementAutomationPeer.

Вопросы безопасности для производных одноранговых классов

Одноранговые классы автоматизации должны запускаться в среде с частичным доверием. Код в сборке UIAutomationClient не сконфигурирован для запуска в среде с частичным доверием, и код однорангового класса автоматизации не должен ссылаться на эту сборку. Вместо этого следует использовать классы в сборке UIAutomationTypes. Например, следует использовать класс AutomationElementIdentifiers из сборки UIAutomationTypes, который соответствует классу AutomationElement в сборке UIAutomationClient. Ссылка на сборку UIAutomationTypes в коде однорангового класса автоматизации является безопасной.

Навигация между одноранговыми классами

После обнаружения однорангового класса автоматизации внутрипроцессный код может перемещаться по одноранговому дереву с помощью вызова методов GetChildren и GetParent объекта. Навигация между элементами WPF внутри элемента управления поддерживается реализацией метода GetChildrenCore однорангового класса. Система модели автоматизации пользовательского интерфейса вызывает этот метод для построения дерева подэлементов, содержащихся в элементе управления, например — списка элементов в поле со списком. По умолчанию метод UIElementAutomationPeer.GetChildrenCore выполняет обход визуального дерева элементов для построения дерева одноранговых классов автоматизации. Пользовательские элементы управления переопределяют этот метод для предоставления дочерних элементов клиентам автоматизации, возвращая одноранговые классы автоматизации элементов, которые передают сведения или разрешают взаимодействие пользователя.

Настройки в производном одноранговом классе

Все классы, производные от UIElement и ContentElement, содержат защищенный виртуальный метод OnCreateAutomationPeer. WPF вызывает OnCreateAutomationPeer, чтобы вернуть одноранговый объект автоматизации для каждого элемента управления. Код автоматизации может использовать одноранговый объект, чтобы вернуть сведения о характеристиках и возможностях элемента управления и смоделировать интерактивное использование. Настраиваемый элемент управления, поддерживающий автоматизацию, должен переопределить метод OnCreateAutomationPeer и вернуть экземпляр класса, производного от AutomationPeer. Например, если настраиваемый элемент управления производится от класса ButtonBase, тогда объект, возвращенный методом OnCreateAutomationPeer, должен производиться от класса ButtonBaseAutomationPeer.

При реализации настраиваемого элемента управления необходимо переопределить методы "Core" из базового однорангового класса автоматизации, описывающие уникальное и отдельное поведение для настраиваемого элемента управления.

Переопределение метода OnCreateAutomationPeer

Переопределите метод OnCreateAutomationPeer для настраиваемого элемента управления таким образом, чтобы этот метод возвращал объект поставщика, который должен прямо или косвенно наследовать от класса AutomationPeer.

Переопределение метода GetPattern

Одноранговые классы автоматизации упрощают некоторые аспекты реализации поставщиков Модель автоматизации пользовательского интерфейса на стороне сервера, однако одноранговые классы автоматизации элементов управления все еще должны обрабатывать интерфейсы шаблонов. Подобно поставщикам, не входящим в состав WPF, одноранговые классы поддерживают шаблоны элементов управления, предоставляя реализации интерфейсов в пространстве имен System.Windows.Automation.Provider, например IInvokeProvider. Интерфейсы шаблонов элементов управления могут быть реализованы самим одноранговым классом или другим объектом. Реализация метода GetPattern однорангового класса возвращает объект, поддерживающий заданный шаблон. Код Модель автоматизации пользовательского интерфейса вызывает метод GetPattern и указывает значение перечисления PatternInterface. Переопределение метода GetPattern должно вернуть объект, который реализует указанный шаблон. При отсутствии у элемента управления пользовательской реализации шаблона можно вызвать реализацию метода GetPattern базового типа для извлечения его реализации или пустой ссылки, если шаблон не поддерживается для данного типа элемента управления. Например, настраиваемый элемент управления NumericUpDown может иметь значение в каком-либо диапазоне, поэтому его одноранговый класс Модель автоматизации пользовательского интерфейса реализует интерфейс IRangeValueProvider. В следующем примере показано, метод GetPattern однорангового класса переопределяется в ответ на значение PatternInterface.RangeValue.

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

Метод GetPattern может также указывать подэлемент в качестве поставщика шаблона. В следующем коде показано, как ItemsControl передает обработку шаблона прокрутки в одноранговый класс его внутреннего элемента управления 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);
}

Чтобы указать подэлемент для обработки шаблона, этот код возвращает объект подэлемента, создает одноранговый класс с помощью метода CreatePeerForElement, задает свойство EventsSource нового однорангового класса текущему одноранговому классу и возвращает новый одноранговый класс. Задание подэлементу свойства EventsSource запрещает ему отображаться в дереве одноранговых классов автоматизации и определяет в качестве источника всех событий, созданных подэлементом, элемент управления, указанный в свойстве EventsSource. Элемент управления ScrollViewer не отображается в дереве автоматизации, а в качестве источника событий прокрутки, которые он создает, фигурирует объект ItemsControl.

Переопределение методов "Core"

Код автоматизации возвращает сведения об элементе управления посредством вызова открытых методов однорангового класса. Чтобы предоставить сведения об элементе управления, переопределите каждый метод, имя которого оканчивается на "Core", когда реализация элемента управления различается в зависимости от того, что предоставляет базовый одноранговый класс автоматизации. Как минимум, элемент управления должен реализовать методы GetClassNameCore и GetAutomationControlTypeCore, как показано в следующем примере.

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

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

Реализация метода GetAutomationControlTypeCore описывает элемент управления, возвращая значение ControlType. Хотя можно вернуть значение ControlType.Custom, необходимо вернуть один или несколько отдельных типов элементов управления, если это точно описывает элемент управления. Возвращаемое значение ControlType.Custom требует дополнительной работы поставщика, чтобы реализовать Модель автоматизации пользовательского интерфейса, и продукты клиента Модель автоматизации пользовательского интерфейса  не могут предвидеть структуру элемента управления, его возможные шаблоны и события клавиатуры.

Реализуйте методы IsContentElementCore и IsControlElementCore, чтобы указать, содержит ли элемент управления данные или выполняет интерактивную роль в интерфейсе пользователя (или и то, и другое). По умолчанию оба метода возвращают true. Эти параметры делают более удобной работу средств автоматизации, таких как средства чтения с экрана, которые могут использовать эти методы для фильтрации дерева автоматизации. Если метод GetPattern передает обработку шаблона в одноранговый класс подэлемента, метод IsControlElementCore однорангового класса подэлемента может вернуть ошибку, чтобы скрыть этот подэлемент в дереве автоматизации. Например, прокрутка в ListBox обрабатывается объектом ScrollViewer, и одноранговый класс автоматизации для PatternInterface.Scroll возвращается методом GetPattern класса ScrollViewerAutomationPeer, связанном с ListBoxAutomationPeer. Поэтому метод IsControlElementCore класса ScrollViewerAutomationPeer возвращает false, чтобы ScrollViewerAutomationPeer не отображался в дереве автоматизации.

Одноранговый класс автоматизации должен предоставлять соответствующие значения по умолчанию для элемента управления. Обратите внимание, что XAML, ссылающийся на элемент управления, может переопределить реализации одноранговых классов базовых методов, включив атрибуты AutomationProperties. Например, следующий XAML создает кнопку, которая имеет два настраиваемых свойства Модель автоматизации пользовательского интерфейса.

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

Реализация поставщиков шаблонов

Интерфейсы, реализованные с помощью пользовательского поставщика, объявляются явно, если владелец-элемент наследует непосредственно от класса Control. Например, следующий код объявляет одноранговый класс для класса Control, который реализует значение диапазона.

public class RangePeer1 : FrameworkElementAutomationPeer, IRangeValueProvider { }

Если владелец-элемент управления наследует конкретному типу элемента управления, например RangeBase, то одноранговый класс может наследовать от эквивалентного производного однорангового класса. В этом случае одноранговый класс будет наследовать от класса RangeBaseAutomationPeer, который предоставляет базовую реализацию интерфейса IRangeValueProvider. В следующем коде показано объявление такого однорангового класса.

public class RangePeer2 : RangeBaseAutomationPeer { }

Пример реализации см. в разделе Пример пользовательского элемента управления NumericUpDown с поддержкой тем и модели автоматизации пользовательского интерфейса.

Создание событий

Клиенты автоматизации можно подписать на события автоматизации. Настраиваемые элементы управления должны создавать отчет об изменениях, чтобы управлять состоянием посредством вызова метода RaiseAutomationEvent. Также, когда изменяется значение свойства, вызовите метод RaisePropertyChangedEvent. В следующем коде показано, как вернуть одноранговый объект из кода элемента управления и вызвать метод, чтобы создать событие. В качестве оптимизации, код определяет, имеется ли прослушиватель для этого типа событий. Создание события только при наличии прослушивателя позволяет избежать лишней нагрузки и способствует тому, что элемент управления остается в состоянии отклика.

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

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

См. также

Задачи

Пример пользовательского элемента управления NumericUpDown с поддержкой тем и модели автоматизации пользовательского интерфейса

Пример генератора тестовых сценариев

Основные понятия

Общие сведения о модели автоматизации пользовательского интерфейса

Реализация поставщика автоматизации пользовательского интерфейса на стороне сервера

Журнал изменений

Дата

Журнал

Причина

Июль 2008

Добавленный раздел.

Улучшение информации.