Skip to content

Implement IExpandCollapseProvider on TreeViewItemAutomationPeer - #22565

Merged
MrJul merged 3 commits into
mainfrom
fix/treeviewitem-expandcollapse-peer
Oct 28, 2026
Merged

MrJul merged 3 commits into
mainfrom
fix/treeviewitem-expandcollapse-peer

Conversation

@grokys

@grokys grokys commented Oct 22, 2026

Copy link
Copy Markdown
Member

What does the pull request do?

Implements IExpandCollapseProvider on TreeViewItemAutomationPeer. A tree item can now report whether it's expanded, and can be expanded or collapsed through accessibility APIs.

What is the current behavior?

The peer implements only ISelectionItemProvider. A screen reader can't tell whether a node has hidden children. An automated test can only expand a node by clicking its toggle with synthesized input.

What is the updated/expected behavior with this PR?

  • Expand() and Collapse() set IsExpanded.
  • ExpandCollapseState is Expanded or Collapsed from IsExpanded, and LeafNode for an item with no children.
  • Expand() and Collapse() throw InvalidOperationException on a leaf item, as WPF does. They throw ElementNotEnabledException when the item is disabled.
  • A property-changed event is raised when the state changes. That covers changes to IsExpanded, and children being added or removed (e.g. LeafNode → Expanded).

How was the solution implemented (if it's not obvious)?

Expand() and Collapse() use SetCurrentValue rather than a plain setter. A common MVVM pattern binds IsExpanded from a style:

<Style Selector="TreeViewItem">
  <Setter Property="IsExpanded" Value="{Binding IsExpanded}" />
</Style>

A plain setter would set a local value. That would shadow the style binding for good, so the item would stop following its view model. TreeViewItem's own keyboard and pointer handling already uses SetCurrentValue for the same reason.

Checklist

Fixed issues

Fixes #22460

🤖 Generated with Claude Code

https://claude.ai/code/session_01GK2AhwrPmuRp98cikjR2Sk

A tree item couldn't report whether it was expanded, and couldn't be
expanded or collapsed through accessibility APIs.

Expand and Collapse set IsExpanded, and throw for an item with no
children, as WPF does. ExpandCollapseState is LeafNode when the item has
no children. A change to IsExpanded or to the item count raises a
property-changed event when the state changes.

Fixes #22460

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GK2AhwrPmuRp98cikjR2Sk

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Reentrant child updates can produce incorrect state notifications, and Linux accessibility mappings expose invalid expansion actions for leaf items.

2 open issues
What changed in this PR

Adds expand/collapse automation support to tree items, addressing #22460 so accessibility clients can query and change their expansion state.

Changes:

  • Implements expansion, collapse, and leaf-state reporting with disabled-item checks.
  • Preserves bindings through SetCurrentValue and emits state-change notifications.
  • Adds unit tests for states, operations, exceptions, and notifications.
File Description
tests/​Avalonia.Controls.UnitTests/​Automation/​TreeViewItemAutomationPeerTests.cs Tests expand/collapse behavior and automation notifications.
src/​Avalonia.Controls/​Automation/​Peers/​TreeViewItemAutomationPeer.cs Implements the expand/collapse provider and state-change reporting.

Review effort: Balanced

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

NuGet packages

The packages for this pull request have been published (workflow run):

@MrJul MrJul added area-accessibility backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch enhancement labels Oct 23, 2026
The Expanded/Collapsed routed events are raised before the peer's
PropertyChanged handler runs, so a handler that populates children
caused an ItemCount notification followed by a second, incorrect
Collapsed -> Expanded notification. Track the last reported state
and compare against it instead of the event's old/new values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ndcollapse-peer

# Conflicts:
#	tests/Avalonia.Controls.UnitTests/Automation/TreeViewItemAutomationPeerTests.cs
@MrJul
MrJul enabled auto-merge October 28, 2026 15:17
@MrJul
MrJul added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit c85e221 Oct 28, 2026
8 checks passed
@MrJul
MrJul deleted the fix/treeviewitem-expandcollapse-peer branch October 28, 2026 15:59
MrJul pushed a commit that referenced this pull request Nov 2, 2026
* Implement IExpandCollapseProvider on TreeViewItemAutomationPeer

A tree item couldn't report whether it was expanded, and couldn't be
expanded or collapsed through accessibility APIs.

Expand and Collapse set IsExpanded, and throw for an item with no
children, as WPF does. ExpandCollapseState is LeafNode when the item has
no children. A change to IsExpanded or to the item count raises a
property-changed event when the state changes.

Fixes #22460

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GK2AhwrPmuRp98cikjR2Sk

* Avoid duplicate expand/collapse notifications on reentrant changes

The Expanded/Collapsed routed events are raised before the peer's
PropertyChanged handler runs, so a handler that populates children
caused an ItemCount notification followed by a second, incorrect
Collapsed -> Expanded notification. Track the last reported state
and compare against it instead of the event's old/new values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@MrJul MrJul added backported-12.1.x and removed backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TreeViewItemAutomationPeer is missing IExpandCollapseProvider

3 participants