by Vinicius de Melo Rocha

How to uniquely name your elements and automate tests for your desktop app

Photo by Ricardo Gomez Angel on Unsplash

Motivation

Writing automated tests for Desktop applications is not an easy task. Especially when it uses Windows Presentation Foundation (WPF). This allows so many possibilities of nested control and complex grids and menus.

Here at Clemex, we use a tool to automate desktop tests that rely on the WPF FrameworkElement.Name property to interact with the application. Because we need to create dynamic controls based on collection data, they can end up with the same name for multiple UI elements.

For example, the following code generates a menu based on a collection of panels.

Inspecting the element tree, we would see that we now have multiple elements with the same name: “MenuBtn”.

To avoid this situation and have unique names for each button, we came up with four different approaches.

  • Using the Code-Behind
  • Using data binding
  • Using attached properties
  • Using collection indexes

Using the Code-Behind

Assuming that we have access to some unique ID on the elements data context. The easiest approach is to use the Loaded event of FrameworkElement to set a unique name using the code-behind model.

Now, when we check the element tree, we will see that we have unique names for each button.

Using data binding

Using data binding makes our code much cleaner, as well as easier to read and understand. If we try a similar approach using data binding we might end up with source code like the following:

Unfortunately, if we try to build this code, we will get a compilation error with the message:

MarkupExtensions are not allowed for Uid or Name property values, so ‘{Binding Panel.PanelType, StringFormat=’MenuBtn{0}’}’ is not valid.

This restriction prevents us from binding directly to the Name property.

Using attached properties

To overcome the limitation of the previous attempt we can define a new property that would set the name for us. To add new properties to existing controls we can use Attached Properties.

The OnValueChanged event triggers every time the value of our property changes. When that happens, we get the new value and set it to be the FrameworkElement name. We are giving our attached property the name Name. It could be anything we want, like CustomName or TestName.

To use the new property, we need to add a namespace to the XAML and attach the property to our button.

Our code will now compile without any problems, and we will have unique names for each element.

Using collection indexes

In the previous example, we created unique names by appending the property Id. There are other scenarios where we don’t have an ID on the item to create a unique element name. For that, we can instead use the collection index.

Let’s try to bind our button collection to a list of strings.

To achieve that, we can use the same AttachedProperty with a converter. It will look for the index of the element inside the collection.

In the XAML, we will now use MultiBinding because we need both the element and the collection.

Looking at the element tree we can see that our buttons are named MenuBtn00, MenuBtn01 and so on.

Summary

Generating unique names for dynamically created WPF controls can be done in an elegant way by using Attached Properties and using the multi-binding with a custom converter.