Handling such applications may require a deeper understanding of the application and its components to dynamically traverse the object tree and find a required element by its properties. This article provides and demonstrates a set of utility functions that can be used to automate these applications.
Consider a sample application with a ListBox control as shown below:

Suppose we have Learned just a single item (listBoxItem4). And now our goal is to click any other items in the same list box.
First, let’s look at the locator part of the learned item:

It looks as shown below:
tabControl1/tabItem1/listBox1/listBoxItem4/listBoxItem4
This path matches the tree structure that we may see from the UI Automation Spy:

So if we need to click a specific item while having object pointing to listBoxItem4 then we need to do the following:
- Climb 2 levels up to the whole [List].
- Search through all the items matching specific text (i.e. listBoxItem5 or so).
Modern Method
function Test()
{
Global.DoLaunch("AUTWPF\\AUTWPF.exe", null, true, "AUTWPF");
SeS('listBoxItem4').DoClick();
SeS('listBoxItem4', { "location": "tabControl1/tabItem1/listBox1/listBoxItem2/listBoxItem2" }).DoClick();
var par = SeS('listBoxItem4').GetParent().GetParent();
var i5 = par.DoFindByText("listBoxItem5");
i5.DoClick();
}
See UIAObject.DoFindByText for more details.
Legacy Method
The attached Rapise sample contains a number of functions and a working sample demonstrating how it can be achieved.
In addition, here is the list of utility functions (you may find them in the attached sample):
function UIAInstance(obj)
{
var instance = obj;
try
{
if (obj && obj.instance)
{
instance = obj.instance;
}
} catch (e) { }
return instance;
}
function UIAParentObj(obj, lvl)
{
if (typeof (obj) == "string")
{
obj = SeS(obj);
}
lvl = lvl || 1;
var instance = UIAInstance(obj);
var par = SeSGetUIAutomationParent(instance);
if (lvl && lvl > 1)
{
return UIAParentObj(par, lvl - 1);
}
return SeSTryMatch(par, SeSUIAObjectRule);
}
function UIAGetChildCount(obj)
{
var instance = UIAInstance(obj);
return SeSGetUIAutomationChildrenCount(instance);
}
function UIAGetChildAt(obj, ind)
{
var instance = UIAInstance(obj);
var chld = SeSGetUIAutomationChildAt(instance, ind);
return SeSTryMatch(chld, SeSUIAObjectRule);
}
function UIAFindByText(obj, findTxt, findClsName)
{
var instance = UIAInstance(obj);
var txt = SeSGetUIAutomationText(instance);
var cls = SeSGetUIAutomationClass(instance);
var name = SeSGetUIAutomationName(instance);
if (SeSCheckString(findTxt, name) || SeSCheckString(findTxt, txt))
{
if (findClsName)
{
if (SeSCheckString(findClsName, cls))
{
return SeSTryMatch(instance, SeSUIAObjectRule);
}
} else
{
return SeSTryMatch(instance, SeSUIAObjectRule);
}
}
var cnt = UIAGetChildCount(instance);
for (var i = 0; i < cnt; i++)
{
var chld = SeSGetUIAutomationChildAt(instance, i);
var res = UIAFindByText(chld, findTxt, findClsName);
if (res) return res;
}
return null;
}
The test working with these functions is following:
function Test()
{
Global.DoLaunch("AUTWPF\\AUTWPF.exe", null, true, "AUTWPF");
SeS('listBoxItem4').DoClick();
SeS('listBoxItem4', { "location": "tabControl1/tabItem1/listBox1/listBoxItem2/listBoxItem2" }).DoClick();
var par = UIAParentObj('listBoxItem4', 2);
var i5 = UIAFindByText(par, "listBoxItem5");
i5.DoClick();
}