我的 WPF 应用程序中有一个事件,如下所示:
private void ShiftsDataGrid_OnBeginningEdit(object? sender, DataGridBeginningEditEventArgs e)
{
if (e.Column == ShiftIdColumn && !e.Row.IsNewItem)
{
CancelColorPopup();
e.Cancel = true;
MessageBox.Show("Its not allowed to edit an existing id for shifts");
}
}
它的目的是在某些情况下阻止用户编辑数据网格中的单元格,并在发生这种情况时显示消息框。
我目前正在通过
System.Windows.Automation
构建 UI 测试,在我的代码中当前有:
var task = Task.Run(() =>
{
var cell = mainWindow.FindDescendantById("ShiftsDataGrid_Row0_Column0");
var parentCell = cell.GetParent();
parentCell.InsertValue("0");
});
WaitForCondition(() =>
{
AutomationElement.
var okButton = AutomationElement.RootElement.FindFirst(TreeScope.Children,
new PropertyCondition(AutomationElement.AutomationIdProperty, "2"));
if (okButton == null)
return false;
okButton.Click();
return true;
}, TimeSpan.FromSeconds(200));
这是激发消息框并尝试单击按钮的众多尝试之一。问题来自于调用
parentCell.InsertValue("0");
这个特定的调用,涉及上面的编辑事件代码并按预期显示消息框。它还会阻止测试代码继续进行。如果我手动点击按钮,它会释放parentCell.InsertValue("0");
在这段时间里,我尝试在其他线程中找到这个MessageBox,但没有成功。无论我做什么,我都找不到
2
的 AutomationIdProperty,即消息框的“确定”按钮。我已使用 Accessibility Insight for Windows 验证了这一点。
我的猜测是 UI 线程在这里阻塞,但我不确定。有没有人有一个好的方法来处理这种情况?
将消息框放入事件中会阻塞自动化系统。所以我这样做了:
if (e.Column == ShiftIdColumn && !e.Row.IsNewItem)
{
CancelColorPopup();
e.Cancel = true;
Task.Run(() => Dispatcher.InvokeAsync(() =>
{
MessageBox.Show("Its not allowed to edit an existing id for shifts");
}));
}
它解决了这个问题。
实际上比描述的更糟糕。尝试@Gerry 的想法后,我发现根本无法联系自动化系统。插入值调用后,对任何 AutomationElement 的任何查询都会被阻止。
我对这种行为提出了很多质疑,因为我似乎在其他帖子中解释过,这很容易在消息框中获取信息,因此请进一步查看。我还注意到,当这个消息框发生时,我的 Windows Accessibility Insight 似乎也被卡住了,但仅当我自己运行测试用例时。在手动控制期间,它工作得很好。因此,出于某种原因,自动化系统是其中的一部分。
因此,我在应用程序中的另一个案例上测试了系统,该案例会生成一个消息框。效果很好。这是由命令而不是事件执行的。因此,我去了该事件,但将 Messagebox 放在任务中,并通过调度程序异步触发 MessageBox。当我这样做时,自动化系统不再适应。事件调用一定是以我没有注意到的方式阻塞的。