Reputation: 574
I'm working with application window containing a lot of log messages. I need to filter them and retrieve those only that mathches some condition. My choice to traverse them all is TreeWalker
as filtering full bulk of messages after AutomationElement.GetAll()
is too expensive (there might be thousands of messages).
List<AutomationElement> messages = new List<AutomationElement>();
TreeWalker walker = new TreeWalker(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem));
AutomationElement row = walker.GetFirstChild(parentDatagrid);
while (row != null)
{
if (/*some condition*/)
messages.Add(row);
row = walker.GetNextSibling(row);
}
Here is the UISpy view of control hierarchy I'm testing.
Unexpectedly messages
length is larger that actual log messages count. I queried for extra automation elements is UISpy and found that this elements were retrieved from another window (they also matched the condition ControlTypeProperty = ControlType.DataItem
). Moreover, this window belonged even to another application. TreeWalker
finished its search in the scope of parentDatagrid
and continued to traverse all desktop hierarchy.
Of course, I hoped to get only child elements of datagrid. What could cause such strange TreeWalker
behaviour? Maybe, my code is wrong, but I wrote the same snipped multiple times, and it worked correctly.
Upvotes: 2
Views: 3126
Reputation: 2663
When you create a custom TreeWalker
, like you did, the behavior will be as you mentioned. It may be better you use a TreeWalker.ControlViewWalker
and then check each of the retrieved elements for your condition.
Upvotes: 0
Reputation: 1250
In fact I can't tell you why TreeWalker does that, because I never use TreeWalker for navigation. I just use it for looking up parents, childs, sibilings, etc..
What I can tell you is, that I have very good experience using the following:
List<AutomationElement> messages = new List<AutomationElement>();
AutomationElement parentDatagrid;//your AE
Condition yourCond = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem));
AutomationElementCollection aECollection;
aECollection= parentDatagrid.FindAll(TreeScope.Element | TreeScope.Descendants, yourCond);
foreach (AutomationElement element in aECollection)
{
//whatever you like
}
of course you have to be careful with TreeScope.Descendants, if performance is an issue. Then you should might consider TreeScope.Children instead, since Descendants looks at all subelements and Children just at the direct childs.
hope this helps!
Upvotes: 1