Microsoft UIAutomation не может получить дочерние компоненты в WPF GroupBox

Настройка сцены

У меня есть простое приложение Microsoft WPF, которое состоит из (управляемого данными) GroupBox, содержащего группу кошек и группу собак. Обе группы Cat и Dog содержат по два групповых элемента каждая. Когда я запускаю приложение, все выглядит нормально, я вижу группы и их содержимое на экране.

Запуск приложения приводит к следующему окну:

Вывод приложения

Однако, когда я создаю тест UIAutomation, я не могу найти элементы автоматизации для элементов группы, только группы; только к группам Cat и Dog можно получить доступ либо с помощью маршрута AutomationElement, либо с помощью UISpy.exe, как показано на изображении ниже:

UISpy не показывать дочерние элементы для групп

Дочерние компоненты для отдельных элементов группы Cat и Dog отсутствуют, и мне нужно иметь возможность получить их как элементы автоматизации в моем тестовом коде:

    [TestMethod]
    public void MyTest()
    {
        Condition controlTypeCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Group);
        var foreGroundWindow = GetForegroundWindow();
        var collection = foreGroundWindow.FindAll(TreeScope.Descendants, controlTypeCondition);
        foreach (AutomationElement element in collection)
        {
            logger.Debug("Name: " + element.Current.Name);
            var children = element.FindAll(TreeScope.Children, Condition.TrueCondition);
            logger.Debug("Number of children: " + children.Count);
        }
    }

В настоящее время выводится:

Имя: Кот

Количество детей: 0

Имя: Собака

Количество детей: 0

Воспроизведение проблемы

Чтобы воспроизвести эту проблему, создайте новое приложение WPF в Visual Studio (с именем WpfApplication1) и замените содержимое MainWindow.xaml следующим:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
        </ResourceDictionary.MergedDictionaries>
        <XmlDataProvider x:Key="data">
            <x:XData>
                <Animals xmlns="">
                    <Animal name="Felix" Species="Cat" />
                    <Animal name="Garfield" Species="Cat" />
                    <Animal name="Rex" Species="Dog" />
                    <Animal name="Rover" Species="Dog" />
                </Animals>
            </x:XData>
       </XmlDataProvider>
        <CollectionViewSource x:Key="AnimalsBySpecies" Source="{Binding Source={StaticResource data}, XPath=Animals/Animal}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="@Species" />
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </ResourceDictionary>
</Window.Resources>

<ItemsControl ItemsSource="{Binding Source={StaticResource AnimalsBySpecies}}">
    <ItemsControl.GroupStyle>
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <GroupBox Header="{Binding Name}">
                                    <ItemsPresenter />
                                </GroupBox>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </ItemsControl.GroupStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding XPath=@name}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
</Window>

На самом деле мой код выглядит не совсем так, поскольку это приложение MVVM. Но для краткости я упростил это до одного файла XAML, который воспроизводит ту же проблему. Важно отметить, что содержимое группы заполняется из привязки XAML.

Итак, как я могу получить доступ к контенту с помощью UIAutomation?

Любая помощь очень ценится!


person Paul    schedule 11.07.2013    source источник


Ответы (3)


Попробуйте использовать API автоматизации пользовательского интерфейса с собственным кодом вместо управляемого API, который является частью платформы .Net. Этот новый API поддерживает дополнительные специальные возможности и рекомендуется Microsoft. Дополнительная информация, обязательно прочитайте ссылки в исходном сообщении.

Кроме того, UISpy устарел и больше не рекомендуется. Вместо этого используйте инструмент UIA Verify, который, помимо того, что он намного стабильнее и быстрее, чем UISpy, также работает с API автоматизации Windows, описанным выше, и, таким образом, может предоставить больше информации об интересующих вас элементах управления.

person Tal Bronfer    schedule 27.07.2013
comment
UIAVerify также не перечисляет дочерние элементы GroupBox. - person grzegorz_p; 10.11.2016

UISpy не является хорошим инструментом для проверки окон или элементов WPF. Я бы предложил использовать Snoop.

Однако этот вопрос кажется похожим, и приведенное там решение может решить вашу проблему.

person digitguy    schedule 12.07.2013
comment
Спасибо за предложение. Этот вопрос, на который вы ссылались, очень похож, но не решает проблему и не был принят автором. Что касается инструментов, причина, по которой я использую UISpy, заключается в том, что он ПРОСТО использует инфраструктуру UIAutomation для проверки визуальных эффектов, поэтому я в значительной степени знаю, что если я вижу элемент в UISpy, я знаю, что могу получить к нему доступ в своих тестах пользовательского интерфейса. - person Paul; 12.07.2013

Это хорошо известная проблема, когда элементы TextBlock внутри шаблонов данных не отображаются в представлениях Control или Content дерева автоматизации. Это оптимизация, сделанная WPF. Возможны три решения.

Одним из них является использование .NET 4.5, где, как я полагаю, это было изменено, так что теперь будут включены TextBlock.

Другой — убедиться, что вы используете представление Raw. Это легко сделать в UI Spy (перейдите в View > Raw View), однако это несколько громоздко в автоматических тестах, поскольку вы не можете использовать обычные условия FindFirst или FindAll. Вы должны использовать TreeWalker.RawViewWalker для ручной проверки дерева автоматизации.

Наконец, вы можете подклассировать элемент управления TextBlock и переопределить метод OnCreateAutomationPeer, чтобы вернуть пользовательскую реализацию AutomationPeer с IsControlElement, возвращающим true. Это описано в этом ответе.

person Mike Zboray    schedule 28.08.2013