使用 Caliburn.Micro 实现 WPF UI 自动化?
我正在尝试为使用 Caliburn.Micro 和 白色。我正在使用 CM 的内置约定将我的控件绑定到视图模型的属性和方法。我还使用了Conductor 类,这样我就可以在单个屏幕上看到多个视图。这通常意味着屏幕上的多个控件最终可能具有相同的 x:Name
值。它只会绑定到不同的视图模型。我想要做什么的一个好主意可以在 HelloScreens 示例应用程序中看到与CM。
我遇到的问题是,我将拥有多个具有相同 x:Name
属性的 XAML 元素,以便 CM 可以为我处理所有绑定工作。不幸的是,这意味着多个 UIItem
对象将具有相同的 UI 自动化 ID。例如,我发现使用 x:Name="DisplayName"
获取不同 TextBlock
元素的唯一方法是进行如下调用:
SearchCriteria criteria = SearchCriteria.ByAutomationId("DisplayName").AndIndex(1);
WPFLabel label = myWindow.Get<WPFLabel>(criteria);
这意味着我的测试需要知道不同控件在屏幕上放置的确切顺序,这看起来很脆弱。只需添加另一个视图模型,我就可以看到我的测试全部中断。
- 除了使用
x:Name
属性之外,还有其他方法可以指定自动化 ID 吗? - 如果我直接使用 UI 自动化框架而不是使用 White 会更容易吗?
- 或者,我真的必须放弃 CM 基于约定的绑定并为每个唯一的
x:Name
值并手动绑定它们吗?
已更新
为了澄清我所说的同时显示多个视图的含义,这是我的总体布局。我有我的 ShellViewModel
,它是从 Conductor
派生的。然后我的视图有一个 ItemsControl
,它绑定到 shell 视图模型的 Items
属性。每个项目模板都显示一个按钮,用于将特定的 IScreen
加载到 shell 视图上的 ContentControl
中。因此,如果我尝试查找带有 x:Name="DisplayName"
的元素,我会在 shell 视图上找到标签,在 ItemsControl
中的按钮上找到标签以及 ContentControl
内的标签。
I am attempting to write some UI automation tests for a WPF application that is using Caliburn.Micro and White. I am using CM's builtin conventions to bind my controls to the view model's properties and methods. I am also using Conductor
classes so that I may have multiple views visible on a single screen. This generally means that multiple controls on a screen can end up having the same x:Name
value. It will just get bound to a different view model. A good idea of what I am trying to do can be seen in the HelloScreens sample application that comes with CM.
The problem that I am running in to is that I will have multiple XAML elements with the same x:Name
attribute so that CM can handle all of the binding work for me. This unfortunately means that multiple UIItem
objects will have the same UI Automation ID. The only way I have found to get, for instance, different TextBlock
elements with x:Name="DisplayName"
is to make a call such as the following:
SearchCriteria criteria = SearchCriteria.ByAutomationId("DisplayName").AndIndex(1);
WPFLabel label = myWindow.Get<WPFLabel>(criteria);
This means my tests need to know the exact order that different controls are placed on the screen, which seems very brittle. I can see my tests all breaking just by adding another view model.
- Is there a way to specify the Automation ID other than using the
x:Name
attribute? - Would this be easier if I used the UI Automation framework directly instead of using White?
- Or, do I really have to forego CM's convention based binding and give everyting unique
x:Name
values and bind them by hand?
UPDATED
To clarify what I mean by having multiple views visible at once, here is my general layout. I have my ShellViewModel
which I derive from Conductor<IScreen>.Collection.OneActive
. Then my view has an ItemsControl
that is bound to the shell view model's Items
property. Each item template shows a button that is meant to load that specific IScreen
into a ContentControl
that is on the shell's view. So, If I try to look for an element with x:Name="DisplayName"
, I have the label on the shell view, the label on the button in the ItemsControl
as well as a label inside of the ContentControl
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
虽然 AutomationId 默认情况下来自 x:Name 属性,但您可以通过设置 AutomationProperties.AutomationId。
Whilst the AutomationId by default comes from the x:Name attribute, you can override it by setting AutomationProperties.AutomationId.
一种选择可能是更改
ViewModelBinder
类型上的BindProperties
和BindActions
委托,以使用其名称根据视图而更改的控件名称。他们属于哪一个。例如,您可以选择将视图名称作为前缀添加到可能在其他视图中具有重复名称的每个控件。因此,
DisplayName
可能会变为ListViewDisplayName
和ContentViewDisplayName
。在继续处理控件之前,可以删除从控件名称到并包括单词“View”的任何文本,以形成干净的控件名称。
One option may be to alter the
BindProperties
andBindActions
delegates on theViewModelBinder
type to work with control names whose names are altered based on the view in which they belong.For example, you could optionally add the view name as a prefix to each control that is likely to have duplicate names in other views. So
DisplayName
could becomeListViewDisplayName
, andContentViewDisplayName
.Any text from the control name up to and including the word 'View' could be stripped to form the clean control name before continuing processing the control.