|
| 1 | +# Accessibility |
| 2 | + |
| 3 | +`TableView` exposes a complete UI Automation (UIA) tree so that screen readers, keyboard-only users, and accessibility testing tools can navigate and interact with the control. Custom `AutomationPeer` classes are registered for every interactive element: the table itself, rows, cells, column headers, and row headers. |
| 4 | + |
| 5 | +## When to use it |
| 6 | + |
| 7 | +You do not need to opt in. Accessibility support is always active. This page explains what is exposed, how to improve automation names for custom content, and what limitations apply. |
| 8 | + |
| 9 | +## Supported UIA patterns |
| 10 | + |
| 11 | +| Element | UIA patterns | |
| 12 | +|---|---| |
| 13 | +| [`TableView`](xref:WinUI.TableView.TableView) | `GridPattern`, `TablePattern`, `SelectionPattern` (inherited from `ListView`) | |
| 14 | +| [`TableViewRow`](xref:WinUI.TableView.TableViewRow) | `SelectionItemPattern` (inherited), `ExpandCollapsePattern` when `RowDetailsVisibilityMode` is `VisibleWhenExpanded` | |
| 15 | +| [`TableViewCell`](xref:WinUI.TableView.TableViewCell) | `GridItemPattern`, `TableItemPattern`, `SelectionItemPattern` | |
| 16 | +| [`TableViewColumnHeader`](xref:WinUI.TableView.TableViewColumnHeader) | `InvokePattern` when [`CanSort`](xref:WinUI.TableView.TableViewColumn.CanSort) is `true` | |
| 17 | +| `TableViewRowHeader` | Structural header element | |
| 18 | + |
| 19 | +### GridPattern / TablePattern (TableView) |
| 20 | + |
| 21 | +`TableView` implements `IGridProvider` and `ITableProvider`: |
| 22 | + |
| 23 | +- **`RowCount`** — number of data rows currently loaded |
| 24 | +- **`ColumnCount`** — number of visible columns |
| 25 | +- **`GetItem(row, column)`** — returns the automation element for the specified cell (only for realized, on-screen cells) |
| 26 | +- **`GetColumnHeaders()`** — returns automation elements for all visible column headers |
| 27 | +- **`RowOrColumnMajor`** — always `RowMajor` |
| 28 | + |
| 29 | +### GridItemPattern / TableItemPattern (cells) |
| 30 | + |
| 31 | +Each `TableViewCell` exposes `IGridItemProvider` and `ITableItemProvider`: |
| 32 | + |
| 33 | +- **`Row`** — zero-based row index |
| 34 | +- **`Column`** — zero-based column index |
| 35 | +- **`RowSpan` / `ColumnSpan`** — always 1 |
| 36 | +- **`ContainingGrid`** — the owning `TableView` |
| 37 | +- **`GetColumnHeaderItems()`** — the column header for this cell |
| 38 | + |
| 39 | +### SelectionItemPattern (cells and rows) |
| 40 | + |
| 41 | +- `IsSelected` reflects the current selection state |
| 42 | +- `Select()`, `AddToSelection()`, and `RemoveFromSelection()` manipulate the selection programmatically |
| 43 | +- `SelectionContainer` returns the owning `TableView` |
| 44 | +- Row `SelectionItemPattern` is provided automatically by the base `ListView` infrastructure |
| 45 | + |
| 46 | +### InvokePattern (column headers) |
| 47 | + |
| 48 | +When a column is sortable ([`CanSort`](xref:WinUI.TableView.TableViewColumn.CanSort) is `true`), its header exposes `IInvokeProvider`. Invoking the header cycles the sort direction: ascending → descending → unsorted. |
| 49 | + |
| 50 | +### ExpandCollapsePattern (row details) |
| 51 | + |
| 52 | +When [`RowDetailsVisibilityMode`](xref:WinUI.TableView.TableView.RowDetailsVisibilityMode) is `VisibleWhenExpanded`, each row exposes `IExpandCollapseProvider` so automation clients can expand or collapse the details pane programmatically. |
| 53 | + |
| 54 | +## Automation names |
| 55 | + |
| 56 | +### TableView |
| 57 | + |
| 58 | +Uses [`AutomationProperties.Name`](https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.automation.automationproperties.name) if set; otherwise inherits from the base `ListView` peer. |
| 59 | + |
| 60 | +```xml |
| 61 | +<tv:TableView AutomationProperties.Name="Products table" /> |
| 62 | +``` |
| 63 | + |
| 64 | +### Column headers |
| 65 | + |
| 66 | +Format: `"{headerText}"`, with an optional sort-state suffix and filter suffix when applicable. |
| 67 | + |
| 68 | +| State | Automation name example | |
| 69 | +|---|---| |
| 70 | +| Unsorted, unfiltered | `"Name"` | |
| 71 | +| Sorted ascending | `"Name, Sort Ascending"` | |
| 72 | +| Sorted descending | `"Name, Sort Descending"` | |
| 73 | +| Sorted and filtered | `"Name, Sort Descending, Filtered"` | |
| 74 | + |
| 75 | +### Rows |
| 76 | + |
| 77 | +Format: `"Row {N}"` (1-based index). The help text contains a summary of all cells in the row, for example `"Name: Waheed Ahmad, Age: 30, City: London"`. |
| 78 | + |
| 79 | +### Cells |
| 80 | + |
| 81 | +Format: `"{columnHeader}, Row {N}, {cellValue}"`. |
| 82 | + |
| 83 | +Examples: |
| 84 | + |
| 85 | +- `"Name, Row 3, Waheed Ahmad"` |
| 86 | +- `"Salary, Row 7, 95000"` |
| 87 | + |
| 88 | +Override the name for a specific column by setting `AutomationProperties.Name` through a `CellStyle`: |
| 89 | + |
| 90 | +```xml |
| 91 | +<tv:TableViewTextColumn Header="Status"> |
| 92 | + <tv:TableViewTextColumn.CellStyle> |
| 93 | + <Style TargetType="tv:TableViewCell"> |
| 94 | + <Setter Property="AutomationProperties.Name" |
| 95 | + Value="{Binding StatusDescription}" /> |
| 96 | + </Style> |
| 97 | + </tv:TableViewTextColumn.CellStyle> |
| 98 | +</tv:TableViewTextColumn> |
| 99 | +``` |
| 100 | + |
| 101 | +### Row headers |
| 102 | + |
| 103 | +Uses `AutomationProperties.Name` if set on the `TableViewRowHeader`, otherwise derives the name from the header's content, or falls back to `"Row {N}"`. |
| 104 | + |
| 105 | +## Keyboard navigation |
| 106 | + |
| 107 | +| Key | Action | |
| 108 | +|---|---| |
| 109 | +| Arrow keys | Move the current cell or row | |
| 110 | +| **Tab** / **Shift+Tab** | Move to the next / previous cell | |
| 111 | +| **Enter** | Move to the next row cell, or commit an edit | |
| 112 | +| **Space** | Select or deselect the current cell or row | |
| 113 | +| **F2** | Begin editing the current cell | |
| 114 | +| **Escape** | Cancel editing and return focus to the current cell | |
| 115 | +| **Home** / **End** | Move to the first / last column in the row | |
| 116 | +| **Ctrl+Home** / **Ctrl+End** | Move to the first / last row | |
| 117 | +| **Page Up** / **Page Down** | Move by one page | |
| 118 | +| **Ctrl+A** | Select all | |
| 119 | +| **Ctrl+Shift+A** | Deselect all | |
| 120 | +| **Ctrl+C** | Copy to clipboard | |
| 121 | + |
| 122 | +## Screen reader behavior |
| 123 | + |
| 124 | +When navigating with a screen reader such as Narrator: |
| 125 | + |
| 126 | +1. Moving to the **TableView** announces it as a table with its row and column count. |
| 127 | +2. Moving between **rows** announces the row number and a summary of its content. |
| 128 | +3. Moving between **cells** announces the column header, row number, and current value. |
| 129 | +4. **Column headers** announce their header text, current sort state, and filter state. |
| 130 | +5. **Editing**: pressing **F2** (or double-tapping) enters edit mode. Focus moves to the editing control (for example, a `TextBox`), which announces itself independently with its own value. Pressing **Escape** returns focus to the cell, keeping Narrator on the correct cell. |
| 131 | +6. **Selection changes** are announced through `SelectionItemPattern.IsSelected`. |
| 132 | + |
| 133 | +## Custom automation names for template columns |
| 134 | + |
| 135 | +`TableViewTemplateColumn` cells display developer-defined content. The cell automation name defaults to `"{columnHeader}, Row {N}"` unless overridden. Set `AutomationProperties.Name` directly on the root element of the template: |
| 136 | + |
| 137 | +```xml |
| 138 | +<tv:TableViewTemplateColumn Header="Actions"> |
| 139 | + <tv:TableViewTemplateColumn.CellTemplate> |
| 140 | + <DataTemplate> |
| 141 | + <Button Content="Edit" |
| 142 | + AutomationProperties.Name="Edit row" /> |
| 143 | + </DataTemplate> |
| 144 | + </tv:TableViewTemplateColumn.CellTemplate> |
| 145 | +</tv:TableViewTemplateColumn> |
| 146 | +``` |
| 147 | + |
| 148 | +## Custom column header names |
| 149 | + |
| 150 | +To override the automation name of a column header (for example, to provide a longer description for an abbreviated header): |
| 151 | + |
| 152 | +```xml |
| 153 | +<tv:TableViewTextColumn Header="DOB"> |
| 154 | + <tv:TableViewTextColumn.HeaderStyle> |
| 155 | + <Style TargetType="tv:TableViewColumnHeader"> |
| 156 | + <Setter Property="AutomationProperties.Name" |
| 157 | + Value="Date of Birth" /> |
| 158 | + </Style> |
| 159 | + </tv:TableViewTextColumn.HeaderStyle> |
| 160 | +</tv:TableViewTextColumn> |
| 161 | +``` |
| 162 | + |
| 163 | +## Notes and limitations |
| 164 | + |
| 165 | +- **Virtualized cells**: `IGridProvider.GetItem(row, column)` returns `null` for rows that are not currently in the visual tree. Scroll the target row into view before calling `GetItem`. |
| 166 | +- **IValueProvider on cells**: `IValueProvider` is not implemented on the cell peer. Instead, the editing element (for example, a `TextBox`) exposes `IValueProvider` while the cell is in edit mode. |
| 167 | +- **Custom column types**: cells in `TableViewTemplateColumn` show developer-defined content. Accessible names for those cells default to the column header and row index unless the template explicitly sets `AutomationProperties.Name`. |
| 168 | +- **Non-Windows platforms**: automation peers are compiled and run on all platforms (WinUI 3 and Uno Platform). However, not all Uno Platform targets expose a full UIA tree to assistive technologies. On WebAssembly (WASM), the platform relies on ARIA attributes managed by Uno. On Desktop Skia targets, accessibility support depends on the native platform's accessibility APIs. |
| 169 | + |
| 170 | +## Related articles |
| 171 | + |
| 172 | +- [Selection](selection.md) |
| 173 | +- [Editing](editing.md) |
| 174 | +- [Sorting](sorting.md) |
| 175 | +- [Filtering](filtering.md) |
| 176 | +- [Row details](row-details.md) |
| 177 | +- [Row headers](row-headers.md) |
| 178 | +- [Styling rows, cells, and headers](styling.md) |
| 179 | + |
0 commit comments