我有一个简单的Microsoft WPF应用程序,它包含一个(数据驱动的)GroupBox,其中包含一组Cats和一组Dogs。 Cat和Dog组都包含两个组项。当我运行应用程序时,一切正常,我可以在屏幕上看到组及其内容。
运行应用程序会生成以下窗口:
然而,当我创建UIAutomation测试时,我找不到任何针对组项的AutomationElements,只查找组;只有 Cat 和 Dog 组可以使用AutomationElement路由访问,或者在UISpy.exe中看到,如下图所示:
单个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获取内容?
任何帮助都非常感谢!
答案 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
在自动化树的Control
或Content
视图中不可见。这是WPF的优化。有三种可能的解决方案。
一个是使用.NET 4.5,我相信这已经改变了,所以现在将包含TextBlock
。
另一个是确保使用Raw
视图。这在UI Spy中很容易(转到View&gt; Raw View)但是在自动化测试中有些麻烦,因为您无法使用正常的FindFirst
或FindAll
条件。您必须使用TreeWalker.RawViewWalker
手动检查自动化树。
最后,您可以继承TextBlock
控件并覆盖OnCreateAutomationPeer
方法,以返回自定义AutomationPeer
实现,其中IsControlElement
返回true。这在answer中列出。