Project archive
For better understanding of this article you should have advanced knowledge of WPF, especially in the part of custom control creating.
In this part we will closely examine such fundamentals of UI Automation as:
And in the end, we will try to implement a simple UI Automation support for custom control.
UI Automation control paterns provide a uniform approach to structure and express control's functionality. Microsoft identified the 18 control patterns, which represent everything that can be done with UI elements. For example, you can use Invoke control pattern for controls that can be invoked (such as buttons ) or Text pattern for edit controls and documents that expose textual information. There is no unique identification between patterns and controls, one pattern can belong to different controls as well as one control can support several pattrens. For example: ComboBox supports ExpandCollapse and Selection patterns. So combining these 18 control patterns, developers can represent the full range of functionality for any user of UI element.
Control Patterns and their Classes and Interfaces
Providers implement control pattern interfaces on UI elements. Control pattern interfaces are found in the System.Windows.Automation.Provider namespace and have names that include the suffix "Provider" (for example, IScrollProvider and IInvokeProvider ). Clients access methods and properties of control pattern classes and use them to access information about a UI element, or to manipulate the UI. These control patterns classes are found in the Systems.Windows.Automation namespace and have names that include the suffix "Pattern" (for example, InvokePattern and SelectionPattern ). Control patterns combine into one: structure, methods, properties and events supported by control. Control patterns relate to UI as interfaces relate to COM objects. In COM, you can query an object to ask what interfaces it supports, and then use those interfaces to access functionality. In UI Automation, clients can ask a control which patterns it supports and then interact with the control through the properties, methods, events, and structure of the supported control patterns. For example, providers implement IScrollProvider for a multi-line edit box. When a client detects that a UI element supports ScrollPattern, it can use the properties, methods, and events from that class to gather scroll-specific information or programmatically scroll its content to a new position. Here is a small part of code that shows how to use InvokePattern For example, we want to Invoke "Start" button. At first we need to find it and cast to AutomationElement, then to obtain its InvokePatterrn an call Invoke method:
UI Automation properties are a set of standard properties that expose information, such as Name, ControlType, Orientation, AccessKey, etc., that is important to assistive technologies. These properies give an opportunity for UI Automation Client application to discover information about different parts of UI. UI Automation properties are read-only. To set properties of a control, you have to use the methods of the appropriate control pattern. Also, as you may notice from the previous code: properties (property ID's) are used in constructing PropertyCondition objects used to find AutomationElement objects. In that way you can specify (by Name, by Type, by Process Id, etc.) what kind of UI element you want to find.
The following code example shows two ways of retrieving a property on an AutomationElement.
To improve performance, property values of controls and control patterns can be cached when AutomationElement objects are retrieved. In UI Automation, caching means that the data can then be accessed without further cross-process communication. So you can get Current or Cached equivalent of property value or control pattern. For the most part, caching - is an automated processs, but there are also special classes and methods that allow caching manipulations . The benefits of caching are most noticeable with WPF controls and custom controls that have server-side UI Automation providers. There is less benefit when accessing client-side providers such as the default providers for Win32 controls. For different UI Frameworks the same UI Automation property can expose different native framework properties. The following table shows how one standard UI Automation property maps to multiple property names in other UI frameworks.
By implementing UI Automation, providers should map unique UI framework properties to standard UI Automation properties.
UI Automation provides information to client applications through events. Unlike WinEvents, UI Automation events are not based on a broadcast mechanism. Clients register for specific event notifications and can request that specific UI Automation properties and control pattern information be passed into their event handler. Providers can improve performance by raising events selectively, depending on whether any clients are subscribed to those events, or not.
Here is an example on how to track Start button Invoke event:
This is a small tutorial about how to provide an UI Autoamtion support for custom WPF control. To demonstrate this, I have created two custom buttons (SimpleButton and SimpleButton2) with 3D effect click. This two controls are identional, but one of them supports UI Automation(SimpleButton) and another(SimpleButton2) does not. I've done it, to show that control with UI Automation support can be recognized by accesibility programs, and another one that does not provide UI Automation support can not.
Note: To feel all details of implementing UI Automation support, it is very important that control should be derived from low - hierarchy class (like Control or ContentControl) and would not have a standard WPF control inside its template. Because standard WPF controls support UI Automation by default.
Microsoft gives a special requirements (such as tree structure, properties, supported patterns, etc ) necessary for correct UI Automation implementation. You can find them here
Custom WPF controls provide UI Automatiom support through AutomationPeer class or derived from it. There are also nany specialized classes such as: ButtonAutomationPeer CheckBoxAutomationPeer, etc. But as our SimpleButton derives from ContentControl class our peer class will be derived from FrameworkElementAutomationPeer. The good rule is to name it SimpleButtonAutomationPeer (control name + "AutomationPeer"). Here is an implementation of SimpleButtonAutomationPeer:
In this class we overrode some basic property getters wich are responsible for correct control identification. As our control is a button we also should support InvokePattern and or TogglePattern (see requirements) To do this, IinvokeProvider interface must be implemented. If the control supports the Invoke control pattern, then InvokeEvent must be supported too. Therefore bofore raising Click RoutedEvent, we should raise UI Automation Invoke event(see code below).
And the last we should do is to override OnCreateAutomationPeer method in SimpleButton class, which returns SimpleButtonAutomationPeer object( see code below ).
To see the results of all this work I have created an application that contains several controls, among which there are standard WPF controls and two our custom buttons(one with UI Atomation support, and another one - without ) . I also added a simple UI Automation explorer that builds a tree and gives some information about controls with UI Automation support, which belong to its own application.
Don't forget! If you want to explore your own application user interfase, you must make all UI Automation calls from a separate thread.
As you can notice at the screenshot, MySimpleButton has an UI Automation support, therefore you can find it in the UI tree, and MySimpleButton2 (without UI Automation support) could not be detected by UI Automation system. You can also check it with UI Spy utulity.
It's a good idea to run UI Spy against your application to make sure everything is shown corectly. If an item appears incorrectly, you can manualy set the propety which provides a wrong information. You can do this in such way, for example HelpText property is incorect:
So, no matter how good your control is, if you want to make it accessible for people with special needs, you must support UI Automation. As it was shown at the latest surveys the nuber of such people increases, therefore supporting UI Automationwill will improve product quality and will be a good thing in attracting clients.