Grade
Grade

Reputation: 574

TreeWalker traverses controls from another window

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.

Screenshot from UISpy

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

Answers (2)

DoronG
DoronG

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

Haphil
Haphil

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

Related Questions