Peer navigation
After locating an automation peer, a UI Automation client can navigate the peer structure of an app by calling the peer object's GetChildren and GetParent methods. Navigation among UI elements within a control is supported by the peer's implementation of the GetChildrenCore method. The UI Automation system calls this method to build up a tree of subelements contained within a control; for example, list items in a list box. The default GetChildrenCore method in FrameworkElementAutomationPeer traverses the visual tree of elements to build the tree of automation peers. Custom controls can override this method to expose a different representation of child elements to automation clients, returning the automation peers of elements that convey information or allow user interaction.
Native automation support for text patterns
Some of the default UWP app automation peers provide control pattern support for the text pattern (PatternInterface.Text). But they provide this support through native methods, and the peers involved won't note the ITextProvider interface in the (managed) inheritance. Still, if a managed or non-managed UI Automation client queries the peer for patterns, it will report support for the text pattern, and provide behavior for parts of the pattern when client APIs are called.
If you intend to derive from one of the UWP app text controls and also create a custom peer that derives from one of the text-related peers, check the Remarks sections for the peer to learn more about any native-level support for patterns. You can access the native base behavior in your custom peer if you call the base implementation from your managed provider interface implementations, but it's difficult to modify what the base implementation does because the native interfaces on both the peer and its owner control aren't exposed. Generally you should either use the base implementations as-is (call base only) or completely replace the functionality with your own managed code and don't call the base implementation. The latter is an advanced scenario, you'll need good familiarity with the text services framework being used by your control in order to support the accessibility requirements when using that framework.
AutomationProperties.AccessibilityView
In addition to providing a custom peer, you can also adjust the tree view representation for any control instance, by setting AutomationProperties.AccessibilityView in XAML. This isn't implemented as part of a peer class, but we'll mention it here because it's germane to overall accessibility support either for custom controls or for templates you customize.
The main scenario for using AutomationProperties.AccessibilityView is to deliberately omit certain controls in a template from the UI Automation views, because they don't meaningfully contribute to the accessibility view of the entire control. To prevent this, set AutomationProperties.AccessibilityView to "Raw". For more info, see AutomationProperties.AccessibilityView.
Throwing exceptions from automation peers
The APIs that you are implementing for your automation peer support are permitted to throw exceptions. It's expected any UI Automation clients that are listening are robust enough to continue on after most exceptions are thrown. In all likelihood that listener is looking at an all-up automation tree that includes apps other than your own, and it's an unacceptable client design to bring down the entire client just because one area of the tree threw a peer-based exception when the client called its APIs.
For parameters that are passed in to your peer, it's acceptable to validate the input, and for example throw ArgumentNullException if it was passed null and that's not a valid value for your implementation. However, if there are subsequent operations performed by your peer, remember that the peer's interactions with the hosting control have something of an asynchronous character to them. Anything a peer does won't necessarily block the UI thread in the control (and it probably shouldn't). So you could have situations where an object was available or had certain properties when the peer was created or when an automation peer method was first called, but in the meantime the control state has changed. For these cases, there are two dedicated exceptions that a provider can throw:
Throw ElementNotAvailableException if you're unable to access either the peer's owner or a related peer element based on the original info your API was passed. For example, you might have a peer that's trying to run its methods but the owner has since been removed from the UI, such as a modal dialog that's been closed. For a non-.NET client, this maps to UIA_E_ELEMENTNOTAVAILABLE.
Throw ElementNotEnabledException if there still is an owner, but that owner is in a mode such as IsEnabled=false that's blocking some of the specific programmatic changes that your peer is trying to accomplish. For a non-.NET client, this map