1

设置场景

我有一个简单的 Microsoft WPF 应用程序,它由一个(数据驱动的)GroupBox 组成,其中包含一组猫和一组狗。Cat 和 Dog 组均包含两个组项。当我运行应用程序时一切正常,我可以在屏幕上看到组及其内容。

运行应用程序会产生以下窗口:

应用程序输出

但是,当我创建 UIAutomation 测试时,我找不到组项的任何 AutomationElements,只有组;只有CatDog组可以使用 AutomationElement 路由访问,或者在 UISpy.exe 中看到,如下图所示:

UISpy 不显示组的孩子

单个 Cat 和 Dog 组项目的子组件不存在,我需要能够在我的测试代码中将它们作为 AutomationElements 检索:

    [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

重现问题

要重现此问题,请在 Visual Studio 中创建一个新的 WPF 应用程序(称为 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 获取内容呢?

非常感谢任何帮助!

4

3 回答 3

1

尝试使用本机代码 UI 自动化 API,而不是作为 .Net 框架一部分的托管 API。这个较新的 API 支持额外的可访问性,并且是 Microsoft 推荐的。这里有更多信息,请务必阅读原帖中的链接。

此外,UISpy 已被弃用,不再推荐。相反,请使用 UIA 验证工具,该工具除了比 UISpy 更稳定和更快之外,还可以与上述 Windows 自动化 API 一起使用,因此可能会公开有关您感兴趣的控件的更多信息。

于 2013-07-27T12:35:10.593 回答
0

UISpy 不是检查 WPF 窗口或元素的好工具。我建议使用Snoop

但是,这个问题似乎很相似,那里给出的解决方案可能会解决您的问题。

于 2013-07-12T07:40:47.233 回答
0

这是一个众所周知的问题,其中TextBlock数据模板内部的 's在自动化树的Control或视图中不可见。Content这是 WPF 所做的优化。有三种可能的解决方案。

一种是使用 .NET 4.5,我相信这已被更改,因此TextBlock现在将包含 's 。

另一个是确保您使用Raw视图。这在 UI Spy 中很容易(转到 View > Raw View),但是在自动化测试中有点麻烦,因为您不能使用正常FindFirstFindAll条件。您必须使用TreeWalker.RawViewWalker手动检查自动化树。

最后,您可以对TextBlock控件进行子类化并覆盖该OnCreateAutomationPeer方法以返回自定义AutomationPeer实现并IsControlElement返回 true。此答案中概述了这一点。

于 2013-08-28T14:13:39.637 回答