dotnet / dotnet/winforms

ControlAccessibleObject should bridge GetFocused() to UIA IRawElementProviderFragmentRoot.GetFocus()

Open
#14,412 5 comments 0 reactions 1 assignee Claimed by @LeafShi1 View on GitHub
tenet-accessibility untriaged
Dominant language
C#
Stars
4.9k
Forks
1.1k
Avg merge
20h 23m
Merged PRs (30d)
103

Description

## Summary

When building a custom WinForms control with child accessible objects (e.g. a grid where each cell is a `CellAccessibleObject : AccessibleObject`), overriding `GetFocused()` on a `ControlAccessibleObject` subclass correctly exposes the focused child to MSAA clients. However, UIA clients, including NVDA, never see it.

## Root cause

`IRawElementProviderFragmentRoot.GetFocus()` is implemented in `AccessibleObject` by calling an `internal virtual` method that returns `null` by default. `ControlAccessibleObject` does not override it, so UIA always reports the control itself as focused, regardless of what `GetFocused()` returns. `DataGridView` works correctly because it overrides `GetFocus()` from *inside* the WinForms assembly:

```csharp
internal override IRawElementProviderFragment.Interface? GetFocus() => GetFocused();
```

External code has no equivalent escape hatch. GetFocused() is public and functional, but the UIA path never reaches it. To repro:

1. Create a custom control with a ControlAccessibleObject subclass
2. Override GetFocused() to return a child AccessibleObject
3. Focus the control with NVDA running
4. Press NVDA+Tab to read the focused element

Actual result: NVDA reports the control, not the child cell.

Expected result: NVDA reports the focused child (the cell accessible object returned by GetFocused())

## Proposed fix

Either make GetFocus() protected virtual so external subclasses can override it, or have ControlAccessibleObject implement it as return GetFocused() as IRawElementProviderFragment.Interface; by default, matching what DataGridView already does internally.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.