设置场景
我有一个简单的 Microsoft WPF 应用程序,它由一个(数据驱动的)GroupBox 组成,其中包含一组猫和一组狗。猫组和狗组各包含两个组项目。当我运行应用程序时,一切都显示正常,我可以在屏幕上看到组及其内容。
运行应用程序会生成以下窗口:
但是,当我创建 UIAutomation 测试时,我找不到组项的任何 AutomationElements,只能找到组;只有 Cat 和 Dog 组可以使用 AutomationElement 路由访问,或者在 UISpy.exe 中看到,如下图所示:
单个猫和狗组项目的子组件不存在,我需要能够在我的测试代码中将它们作为 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);
}
}
以上当前输出:
名称:猫
child 数量:0
名称:狗
child 数量: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 绑定(bind)填充的。
那么如何使用 UIAutomation 获取内容?
非常感谢任何帮助!
最佳答案
这是一个众所周知的问题,其中TextBlock
数据模板内的 '在 Control
中不可见或Content
自动化树的 View 。这是WPF所做的优化。存在三种可能的解决方案。
一种是使用 .NET 4.5,我相信,它已更改,以便 TextBlock
现在将被包括在内。
另一个是确保您使用 Raw
看法。这在 UI Spy 中很容易(转到“ View ”>“原始 View ”),但在自动化测试中有点麻烦,因为您无法使用正常的 FindFirst
或FindAll
状况。您必须使用TreeWalker.RawViewWalker
手动检查自动化树。
最后,您可以对 TextBlock
进行子类化控制和覆盖 OnCreateAutomationPeer
返回自定义的方法 AutomationPeer
实现 IsControlElement
返回真。这在answer中概述了.
关于c# - Microsoft UIAutomation 无法检索 WPF GroupBox 中的子组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17596855/