Addressing Objects in WPF Applications

Applies to TestComplete 14.70, last modified on April 22, 2021

There are several ways to refer to objects in WPF applications. If you use Name Mapping in your test project, you can refer to the application objects using their names specified in Name Mapping. For objects not in Name Mapping, you can use the naming syntax that directly includes identification properties and values of these objects. This topics explains both approaches.

Note: The information in this topic applies only to GUI objects. To learn how to refer to non-GUI objects that are not displayed in the Object Browser, see Accessing Non-Visual Objects in .NET Applications.

About Object Names in the Object Browser

You can explore the object structure of the tested application in the Object Browser. Here is a sample view of the WPF application hierarchy displayed in the Object Browser:

A view of a WPF application in the object tree

Click the image to enlarge it.

Here, the Process("Orders") branch of the Sys object corresponds to your tested WPF application and the other objects correspond to the application’s windows, controls and objects.

To refer to an individual object in a tested WPF application, select the needed object in the Object Browser or Object Spy. These tools display the selected object’s name above the member list. From the right-click menu, you can copy this name to the clipboard and then insert it into your test.

Copying the object name from the Object Browser

Click the image to enlarge it.

You may notice that this name differs from what you see in the object tree on the left of the Object Browser. This is because the name displayed at the top of the panel uses object aliases, if they are defined, whereas the object tree uses the naming syntax that includes identification properties. The differences between the two object naming syntaxes are explained in the Addressing WPF Objects Using Name Mapping and Aliases and Addressing WPF Objects Without Name Mapping sections below.

You can also learn the object names in different syntaxes by looking at the following object properties:

  • MappedName - the object’s fully-qualified alias (including aliases of all parent objects). This name is used for the object by default in your tests. Note that if the selected object is not in Name Mapping, this property is empty.

  • Name - the object name that includes its identification properties. This is the same name you see in the Object Browser’s object tree. For an explanation of this syntax, see below.

  • FullName - the object’s fully-qualified name in the syntax that includes the identification properties. This name consists of the object’s Name property value and the names of all of its parent objects. See below.

Addressing WPF Objects Using Name Mapping and Aliases

By default, TestComplete uses the object names from Name Mapping (the object repository) to refer to objects in WPF applications under test. These names are called aliases. When you record a test, TestComplete automatically adds the recorded objects to Name Mapping and generates aliases for them.

You can see the available object aliases and add new aliases in the Name Mapping editor.

Sample Name Mapping for a WPF application

Here, Mapped Objects and Aliases display the hierarchy of mapped objects and their aliases, respectively. The fully-qualified alias that can be used to refer to an object is displayed in the top right part of the Name Mapping editor (see the image above). It starts with Aliases and includes aliases of all of the object’s parent objects separated by dots (in VBScript, JScript, Python and DelphiScript projects) or square brackets (in C++Script and C#Script projects). For example, in the image above you can see that you can refer to the OrdersView object using the following name:

JavaScript, JScript

Aliases.Orders.HwndSource_MainForm.OrdersView

Python

Aliases.Orders.HwndSource_MainForm.OrdersView

VBScript

Aliases.Orders.HwndSource_MainForm.OrdersView

DelphiScript

Aliases.Orders.HwndSource_MainForm.OrdersView

C++Script, C#Script

Aliases["Orders"]["HwndSource_MainForm"]["OrdersView"]

You can copy object aliases from the Name Mapping editor to the clipboard and use them when manually adding test operations with the tested application’s objects.

The following example shows a sample item selection operation on the OrdersView control specified by an alias:

A keyword test operation over a WPF object addressed using its alias
Note: For simplicity, keyword tests do not display the Aliases identifier at the beginning of object aliases.

Also, keyword tests may not display intermediate objects in the application’s object hierarchy. To view the full name of an operation’s target object, double-click the operation or increase the Maximum depth option in Keyword Test Editor - Groups options.

JavaScript, JScript

Aliases.Orders.HwndSource_MainForm.OrdersView.ClickItem(5);

Python

Aliases.Orders.HwndSource_MainForm.OrdersView.ClickItem(5);

VBScript

Call Aliases.Orders.HwndSource_MainForm.OrdersView.ClickItem(5)

DelphiScript

Aliases.Orders.HwndSource_MainForm.OrdersView.ClickItem(5);

C++Script, C#Script

Aliases["Orders"]["HwndSource_MainForm"]["OrdersView"]["ClickItem"](5);

Note that the fully-qualified mapped name for this object is as follows:

JavaScript, JScript

NameMapping.Sys.Orders.HwndSource_MainForm.gridMain.OrdersView

Python

NameMapping.Sys.Orders.HwndSource_MainForm.gridMain.OrdersView

VBScript

NameMapping.Sys.Orders.HwndSource_MainForm.gridMain.OrdersView

DelphiScript

NameMapping.Sys.Orders.HwndSource_MainForm.gridMain.OrdersView

C++Script, C#Script

NameMapping["Sys"]["Orders"]["HwndSource_MainForm"]["gridMain"]["OrdersView"]

Since the MainForm and gridMain objects are of no interest for our test, we exclude them from the path to the OrdersView object in the Alias tree, so the object hierarchy becomes shorter. Using aliases lets you make your scripts shorter and more readable.

For more information about using Name Mapping and aliases, see Name Mapping and Access Objects by Aliases.

Addressing WPF Objects Without Name Mapping

Your tests can work not only with applications and objects added to Name Mapping, but also with any other running applications, their windows and controls. These objects can be addressed using syntax that directly includes identification property values:

A keyword test operation over a WPF object that is not in Name Mapping

JavaScript, JScript

Sys.Process("Orders").WPFObject("HwndSource: MainForm").WPFObject("MainForm").WPFObject("OrdersView").ClickItem(5);

Python

Sys.Process("Orders").WPFObject("HwndSource: MainForm").WPFObject("MainForm").WPFObject("OrdersView").ClickItem(5);

VBScript

Call Sys.Process("Orders").WPFObject("HwndSource: MainForm").WPFObject("MainForm").WPFObject("OrdersView").ClickItem(5)

DelphiScript

Sys.Process('Orders').WPFObject('HwndSource: MainForm').WPFObject('MainForm').WPFObject('OrdersView').ClickItem(5);

C++Script, C#Script

Sys["Process"]("Orders")["WPFObject"]("HwndSource: MainForm")["WPFObject"]("MainForm")["WPFObject"]("OrdersView")["ClickItem"](5);

To learn the exact syntax for referring to a particular object, use the Object Browser - the object tree and the FullName property of objects always use this naming syntax. See the About Object Names in the Object Browser section above.

Let’s have a closer look at this notation and its components.

  • The notation starts with Sys object that represents the operating system.

  • The next object, Process("Orders"), represents the .NET application with the file name Orders.exe.

  • WPFObject("HwndSource: MainForm") is the containing object that hosts WPF content in a window.

  • Further objects represent WPF content - windows and controls - in your WPF application.

    The default and most commonly used syntax for these objects is as follows:

    WPFObject(NativeName)

    Here, NativeName is the object name defined by the application developers; this name is specified by the object’s WPFControlName property.

    Another possible syntax for WPF objects is:

    WPFObject(NETClassName, Caption, [Index])

    Instead of the object’s native name, it uses its .NET class name (specified by the ClrClassName property value), text and (optionally) index among sibling objects with the same class and text. This syntax is and should be used in the following cases:

    • TestComplete cannot determine the object name that is specified in the application code.

    • There are several objects with the same name.

    For more information about WPF object addressing syntax and its parameters, see the description of the WPFObject notation.

For examples of this syntax applied to objects in your tested WPF application, examine your application in the Object Browser. You can also copy this syntax from the Object Browser and paste it to your test to avoid having to type it manually.

Remarks
  • The WPFObject notation is used for WPF GUI objects of any type - forms, buttons, combo boxes, grids and so on. The word Object here does not mean that TestComplete does not identify the object type. Just the opposite, TestComplete supports many different types of WPF GUI objects and provides high-level methods and properties for automating operations over them. See Support for WPF Applications' Controls for more information.

  • The object hierarchy of XAML Browser Applications (XBAP) includes the Browser and Page objects corresponding to the web browser and web page where the XBAP is hosted. For example:

    JavaScript, JScript

    Sys.Browser("iexplore").Page("http://server/orders/orders.xbap").WPFObject("RootBrowserWindow", "OrdersDemo - Untitled").WPFObject("AppPage").WPFObject("OrdersView");

    Python

    Sys.Browser("iexplore").Page("http://server/orders/orders.xbap").WPFObject("RootBrowserWindow", "OrdersDemo - Untitled").WPFObject("AppPage").WPFObject("OrdersView");

    VBScript

    Sys.Browser("iexplore").Page("http://server/orders/orders.xbap").WPFObject("RootBrowserWindow", "OrdersDemo - Untitled").WPFObject("AppPage").WPFObject("OrdersView")

    DelphiScript

    Sys.Browser('iexplore').Page('http://server/orders/orders.xbap').WPFObject('RootBrowserWindow', 'OrdersDemo - Untitled').WPFObject('AppPage').WPFObject('OrdersView);

    C++Script, C#Script

    Sys["Browser"]("iexplore")["Page"]("http://server/orders/orders.xbap")["WPFObject"]("RootBrowserWindow", "OrdersDemo - Untitled")["WPFObject"]("AppPage")["WPFObject"]("OrdersView");

  • If the Use native object names for TestComplete object names setting is disabled in your test project, TestComplete uses the WPFObject(NETClassName, Caption, [Index]) rather than WPFObject(NativeName) notation for WPF objects by default. For example, it uses this notation in the Object Browser and also during the test recording when Name Mapping is not used.

    Note, however, that this setting only affects the default object naming syntax used in TestComplete panels and dialogs. When creating tests manually, you can use both the WPFObject(NativeName) and WPFObject(NETClassName, Caption, [Index]) notations equally well, regardless of this setting.

About Containers in the WPF Object Hierarchy

Applications that include WPF applications often include container objects that are used to layout content, but do not affect the way the user interacts with the application. Examples of such containers used in WPF applications are the Panel and Border objects. The application object hierarchy represented in TestComplete (for example, the one displayed in the Object Browser) reflects the actual object hierarchy in the application and includes all the objects, including intermediate layout containers. However, if your tested WPF application has a complex user interface with many containers, its object hierarchy can be quite complex and deeply nested, which makes tests less readable.

To improve the readability of WPF application tests, TestComplete provides the Simplified WPF object tree project property. If this option is enabled, TestComplete omits the following layout container objects from the application object hierarchy available to your tests:

  • AdornerLevel
  • ContentPresenter
  • Decorator
  • FrameworkContentElement
  • GridViewRowPresenterBase
  • Panel
  • Descendant classes of the abovementioned base classes, except for Hyperlink

This reduces the number of nesting levels of tested objects corresponding to interactive controls in WPF applications, shortens the syntax used to address these objects in tests and thus improves the test readability.

The differences in the WPF object hierarchy provided by the Simplified WPF object tree option are illustrated in the following images.

WPF object hierarchy when 'Simplified WPF object tree' is disabled
WPF object hierarchy when 'Simplified WPF object tree' is disabled
WPF object hierarchy when 'Simplified WPF object tree' is enabled
WPF object hierarchy when 'Simplified WPF object tree' is enabled

For example, when the Simplified WPF object tree option is disabled, a fully-qualified name of a button object in a WPF application is as follows (layout containers are highlighted in blue):

Sys.Process("Orders").WPFObject("HwndSource: OrderForm").WPFObject("OrderForm").WPFObject("gridMain").WPFObject("gridButtons").WPFObject("ButtonOK")

With the Simplified WPF object tree option enabled, the object hierarchy is reduced and looks as follows:

Sys.Process("Orders").WPFObject("HwndSource: OrderForm").WPFObject("OrderForm").WPFObject("ButtonOK")

To view or modify the Simplified WPF object tree option, do the following:

  • Double-click your project in the Project Explorer.

  • In the project editor, switch to the Properties tabbed page.

  • In the tree on the left, select Open Applications | WPF.

  • Check or uncheck the Simplified WPF object tree option.

  • Select File | Save All from main menu to save the changed made.

Since the Simplified WPF object tree setting affects the object hierarchy of WPF applications, as it is available to the test engine, tests created with this setting enabled may not play back correctly when this setting is disabled, and vice versa.

Combining Mapped and Unmapped Object Names

You can combine aliases specified in Name Mapping and the WPFObject notation when referencing an object hierarchy in tests. For example, you can use aliases for parent objects and the WPFObject notation for child objects:

JavaScript, JScript

Aliases.Orders.HwndSource_OrderForm.WPFObject("OrderForm").WPFObject("ButtonOK").ClickButton();

Python

Aliases.Orders.HwndSource_OrderForm.WPFObject("OrderForm").WPFObject("ButtonOK").ClickButton();

VBScript

Aliases.Orders.HwndSource_OrderForm.WPFObject("OrderForm").WPFObject("ButtonOK").ClickButton

DelphiScript

Aliases.Orders.HwndSource_OrderForm.WPFObject('OrderForm').WPFObject('ButtonOK').ClickButton();

C++Script, C#Script

Aliases["Orders"]["HwndSource_OrderForm"]["WPFObject"]("OrderForm")["WPFObject"]("ButtonOK")["ClickButton"]();

However, keep in mind that aliases must always precede the WPFObject notation in the object hierarchy. Aliases cannot be used after the WPFObject notation within the same statement. That is, the following statement is invalid:

JavaScript, JScript

Sys.Process("Orders").WPFObject("HwndSource: OrderForm").OrderForm.ButtonOK.ClickButton();

Python

Sys.Process("Orders").WPFObject("HwndSource: OrderForm").OrderForm.ButtonOK.ClickButton();

VBScript

Sys.Process("Orders").WPFObject("HwndSource: OrderForm").OrderForm.ButtonOK.ClickButton

DelphiScript

Sys.Process('Orders').WPFObject('HwndSource: OrderForm').OrderForm.ButtonOK.ClickButton();

C++Script, C#Script

Sys["Process"]("Orders")["WPFObject"]("HwndSource: OrderForm")["OrderForm"]["ButtonOK"]["ClickButton"]();

See Also

Testing WPF Applications
Testing WPF Applications - Overview
Support for WPF Applications' Controls
Accessing Native Properties and Methods of .NET Objects
Accessing Non-Visual Objects in .NET Applications

Highlight search results