Microsoft UIAutomation无法检索WPF GroupBox中的子组件

时间:2013-07-11 15:00:10

标签: c# wpf microsoft-ui-automation

设置场景

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

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

Application Output

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

UISpy show no children for the groups

单个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 Binding填充的。

那么如何使用UIAutomation获取内容?

任何帮助都非常感谢!

3 个答案:

答案 0 :(得分:1)

尝试使用本机代码UI Automation API ,而不是使用.Net框架中的托管API 。此较新的API支持其他可访问性,Microsoft建议使用此API。 Here's some more information,请务必阅读原帖中的链接。

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

答案 1 :(得分:0)

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

然而,this question似乎相似,并且在那里给出的解决方案可以解决您的问题。

答案 2 :(得分:0)

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

一个是使用.NET 4.5,我相信这已经改变了,所以现在将包含TextBlock

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

最后,您可以继承TextBlock控件并覆盖OnCreateAutomationPeer方法,以返回自定义AutomationPeer实现,其中IsControlElement返回true。这在answer中列出。