Selector

Reading an Element

An element reaches a workflow through a callback, where CallIfFound hands over the elements the selector found and the ones that matched its filters. Each one answers the same questions whether it came from a page or from a window: Selected, Checked, Enabled, Displayed, Text, TagName, Location and Size.

An application element adds Name, what the control calls itself, which a page element has no equivalent of and reaches through GetAttribute instead. A page element carries more besides, because a page has more to say: Href and Src are the link and the source, Value and Placeholder are what is typed and what is suggested, and PageURL is the address the page was at when the element was read, which is what tells two elements from two pages apart in one grid.

Selected is true for a chosen row, tab, radio button or option. Checked is a checkbox's state and has three of them, so it is a nullable bool: true ticked, false clear, and null for the filled square a parent box shows when some of what is under it is on and some is not. Enabled and Displayed say whether the element can be used and whether it is on screen at all. Text is its content, TagName what kind of thing it is, and Location and Size where it is and how big.

Reading a property asks the element at the moment you ask, so a value read before a click and a value read after it are two different answers.

NOTE

The point of the list is that it is one list. A browser element and a window element are different objects underneath, a DOM node and a UIAutomation element, and neither of those exposes anything like the other. GPAL asks each in its own terms and answers in the same words, so a workflow that reads Selected off a table row reads Selected off a list view row, and code written against one can be read by someone who only knows the other. On a page Checked reads the input's indeterminate flag; on a window it reads the toggle state.

WARNING

Selected on an element that has no notion of selection is false, not an error, and the same goes for Checked on something that is not a checkbox, which answers null. So a property coming back empty means either that the answer is no or that the control does not publish one, and the two look alike. Where it matters, check the element is the one you meant rather than reading the property twice. A property also does not wait for anything: use WaitFor to settle the page or the window first, then read.

Examples

GPAL Fluent: High-level fluent C# API

//The handler is given two lists, everything the selector found and the subset that matched its filters, and matched is the one to read when the selector carries filters. Selected stays a plain bool because a row is either the chosen one or it is not; Checked is the nullable one because a box has a third state. Returning CallIfStatus.NotHandled reads the elements and leaves the unit of work to carry on as it would have. A page element also knows how it was found. Xpath and Css are the paths that located it, FullXPath is the absolute one from the root, and Xpaths is every path GPAL worked out for it, each with the number of elements it matches on that page. That count is the useful part: a path matching one element is a path worth keeping in a selector, and a path matching forty is a path that will find the wrong thing tomorrow. Reading them in a handler is how a workflow turns an element it found once into a selector it can rely on.

// the same handler shape, and the same property names, on either side

static CallIfStatus OnRowFound(IBrowser browser, List<IGPALElement> found, List<IGPALElement> matched, Selector selector, bool matchedAll)

{

foreach (IGPALElement element in matched)

if (true == element.Selected)

GPAL.PublishSimpleEvent(GPALEventType.NOTICE, $"[{element.Text}] is the selected one");


return CallIfStatus.NotHandled;

}


// a three state box: ticked, clear, or neither

static CallIfStatus OnBoxFound(IApplication application, List<IGPALAutomationElement> found, List<IGPALAutomationElement> matched, Selector selector, bool matchedAll)

{

foreach (IGPALAutomationElement element in matched)

GPAL.PublishSimpleEvent(GPALEventType.NOTICE, null == element.Checked

? $"[{element.Name}] is partly ticked"

: $"[{element.Name}] is [{element.Checked}]");


return CallIfStatus.NotHandled;

}


💬 Ask GPAL