WPF UI Automation - AutomationElement.FindFirst fails when there are lots of elements
We've got some automated UI tests for our WPF app (.NET 4); these test use the UI Automation API's.
We call AutomationElement.FindFirst to find a target element, and then interact with it.
Example (pseudocode):
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!
The problem is, the appWindow.FindFirst
will sometimes fail and return null, even when the element is present. I've written a helper function which walks the UI automation tree manually and prints it out, and the element with the correct ID is present in all cases.
It seems to be related to how many other items are also being displayed in the window. If there are no other items then it always succeeds, but when there are many other complex UI elements being displayed alongside it, then the find fails.
It appears as though we're hitting some kind of internal element limit. I can't find any documented开发者_开发技巧 element limit mentioned for any of the automation API's - is there some way around this? I'm thinking I might have to write my own implemententation of FindFirst
which does the tree walk manually itself... As far as I can tell this should work, because my tree-printer utility function does exactly that, and it's ok, but it seems like this would be unnecessary and slow :-(
Any help would be greatly appreciated
Doing the tree walk manually is probably the best way to work around this issue.
And in fact, you'll probably find that an implementation of FindFirst
using tree walking will be faster that using FindFirst
on an element with a large number of children. If you look at the code for AutomationElement.FindFirst
in Reflector, you'll see that it works by pulling accross the automation boundary all children matching the condition, then returning the first of them. By contrast, the TreeWalker approach will only attempt to pull the single first child accross the boundary.
I had the same problem in one of my Applications I was automating. I had a custom control that was on the AdornerLayer and I was modifying the UI Automation tree so the Adorner's AutomationElement appeared as a UI Visual child to the control it was decorating instead of appearing as a child of the root for the application.
When I ran UI Spy I would get a number of errors in the Output Window stating things about an invalid parent as I navigated through its tree. I resolved a bug in my code in how I was parenting the AutomationElement for the Adorner's AutomationElement. Once I fixed the bug, UI Spy no longer displayed errors in the Output Window and I was no longer getting failures from the FindFirst method calls.
If the original poster is still monitoring this question I would ask does UI Spy have any problems navigating through your Application?
I even stuck with this problem but i only have not seen my failure.
var window = new System.Windows.Window();
window.Show();
window.Content = addControl;
GetWindow(window.Name);
I create a window an the fly and added the control as the Content of the window. My failure here was, that i showed the window, and then assigned the Content. This even fails. After hours of searching i changed it my code to this:
var window = new System.Windows.Window();
window.Content = addControl;
window.Show();
GetWindow(window.Name);
... and it works.
Michael
精彩评论