evilfish
evilfish

Reputation: 701

AutomationElement blocks when application show messagebox

I have an event in my WPF application that looks like this:

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");
    }
}

It is meant to block users from editing a cell in a datagrid in certain situations and show a messagebox when it happens.

Im currently building a UI test via System.Windows.Automation where in my code I currently have:

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));

This is one of many attempts to provoke the message box and try to click the button. The problem comes with the call parentCell.InsertValue("0"); This specific call, engages the edit event code above and showing the message box as expected. What it also does is block the testing code from progressing. If I click the button manually, it will release the parentCell.InsertValue("0");

During this block, I have tried in other threads to find this MessageBox, but with no success. No matter what I do, I cannot find the AutomationIdProperty of 2, which is the Ok button for the messagebox. I have verified this with Accessibility Insight for Windows.

enter image description here

My guess is the UI thread is blocking here, but I am not certain. Does anyone have a good approach on how to handle this situation?

Upvotes: 0

Views: 34

Answers (1)

evilfish
evilfish

Reputation: 701

TLDR

Putting message boxes in event is blocking the automation system. So I did this:

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");
    }));
}

And it fixes the issue.

Solution

It was actually worse than described. Trying out @Gerry's idea I found out that it was not even possible to contact the AutomationSystem at all. Any query to any AutomationElement was blocked after the insert value call.

I question this behavior a lot, as I have seem other post explaining that this is easy to get the information on a messagebox, so looked further. I noticed also that my Accessibility Insight for Windows also seem to be stuck when this message box happened, but ONLY when I was running the testcase it self. during manual control it worked fine. So for some reason, the automation system was a part of it.

So I tests the system on another case in my application that would spawn a message box. And that worked fine. This one was executed by a command and not an event. So I went to the event and but the Messagebox inside a task and asynchronously fired the MessageBox via the dispatcher. When I did that, the AutomationSystem no longer had a fit. The event call must have been blocking in a way I did not notice.

Upvotes: 0

Related Questions