Автоматизация пользовательского интерфейса WPF - AutomationElement.FindFirst завершается ошибкой при большом количестве элементов - PullRequest
2 голосов
/ 09 июня 2010

У нас есть несколько автоматических тестов пользовательского интерфейса для нашего приложения WPF (.NET 4);эти тесты используют API пользовательского интерфейса API.

Мы вызываем AutomationElement.FindFirst , чтобы найти целевой элемент, а затем взаимодействовать с ним.

Пример(псевдокод):

var nameEquals = new PropertyCondition(AutomationElement.NameProperty, "OurAppWindow");
var appWindow = DesktopWindow.FindFirst(TreeScope.Children, nameEquals);
// this succeeds

var idEquals = new PropertyCondition(AutomationElement.AutomationIdProperty, "ControlId");
var someItem = appWindow.FindFirst(TreeScope.Descendants, idEquals);
// this suceeds sometimes, and fails sometimes!

Проблема заключается в том, что appWindow.FindFirst иногда завершается ошибкой и возвращает ноль, даже если элемент присутствует.Я написал вспомогательную функцию, которая обходит дерево автоматизации пользовательского интерфейса вручную и распечатывает его, и во всех случаях присутствует элемент с правильным идентификатором.

Похоже, это связано с тем, сколько других элементов такжеотображается в окне.Если других элементов нет, то это всегда успешно, но когда рядом с ним отображается много других сложных элементов пользовательского интерфейса, поиск не выполняется.

Похоже, что мы достигли какого-то внутреннего ограничения на количество элементов,Я не могу найти ни одного задокументированного предела элемента, упомянутого ни для одного из API автоматизации - есть ли способ обойти это?Я думаю, что мне, возможно, придется написать свою собственную реализацию FindFirst, которая сама обрабатывает дерево вручную ... Насколько я могу сказать, это должно работать, потому что моя утилита для работы с деревом-принтером делает именно это, и это нормально., но кажется, что это было бы ненужным и медленным: - (

Любая помощь будет принята с благодарностью

Ответы [ 3 ]

2 голосов
/ 29 сентября 2010

У меня была такая же проблема в одном из моих приложений, которые я автоматизировал.У меня был пользовательский элемент управления, который был на AdornerLayer, и я модифицировал дерево автоматизации пользовательского интерфейса, чтобы элемент AutomationElement Adorner отображался как дочерний элемент визуального интерфейса пользователя для элемента управления, который он украшал, вместо того, чтобы отображаться как дочерний элемент корня для приложения.

Когда я запускал UI Spy, в окне вывода я получал ряд ошибок, сообщающих о недопустимом родительском элементе при навигации по его дереву.Я исправил ошибку в своем коде, заключающуюся в том, что я являлся родителем элемента AutomationElement для элемента автоматизации Adorner.Как только я исправил ошибку, шпион UI больше не отображал ошибки в окне вывода, и я больше не получал сбои при вызовах метода FindFirst.

Если оригинальный постер все еще отслеживает этот вопрос, я хотел бы спросить: шпион UIесть какие-либо проблемы с навигацией по вашему Приложению?

2 голосов
/ 09 июня 2010

Выполнение обхода дерева вручную, вероятно, лучший способ обойти эту проблему.

И на самом деле вы, вероятно, обнаружите, что реализация FindFirst с использованием обхода дерева будет быстрее, чем при использовании FindFirst для элемента с большим числом дочерних элементов. Если вы посмотрите на код для AutomationElement.FindFirst в Reflector, вы увидите, что он работает, перетаскивая через границу автоматизации всех дочерних элементов, соответствующих условию, а затем возвращая первый из них. Напротив, подход TreeWalker будет пытаться переместить только одного первого ребенка через границу.

0 голосов
/ 06 января 2011

Я даже застрял с этой проблемой, но я только не видел свою ошибку.

var window = new System.Windows.Window();
window.Show();
window.Content = addControl;
GetWindow(window.Name);

Я создал окно на лету и добавил элемент управления в качестве содержимого окна. Моя ошибка здесь состояла в том, что я показал окно, а затем назначил Контент. Это даже не удается. После нескольких часов поиска я изменил свой код на это:

var window = new System.Windows.Window();
window.Content = addControl;
window.Show();
GetWindow(window.Name);

... и это работает.

Michael

...