ItemAutomationPeer doesn't properly update Children when the container is initially invisible
- Dominant language
- C#
- Stars
- 7.7k
- Forks
- 1.3k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 61
Description
### Description
For an `ItemsControl`, `ItemAutomationPeer` is supposed to help link the items' actual automation peers to the automation tree.
However, in certain situation, `ItemAutomationPeer` doesn't correctly update its `Children`, resulting in automation peers missing from the tree
### Reproduction Steps
Can be reproduced with the following XAML
```XML
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=CheckBox}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
Click Me
```
This is just a simplified example. In reality, we have many different types of data items, each with its own data template.
### Expected behavior
After checking the check box and the button becomes visible, a button automation peer should be available in the automation tree for UI automation tools e.g. Windows Narrator should be able to read the button out when focused on it
### Actual behavior
No button automation peers in the automation tree. Windows Narrator isn't able to discover the button
### Regression?
_No response_
### Known Workarounds
_No response_
### Impact
_No response_
### Configuration
_No response_
### Other information
The issue happens when the following conditions are met:
1. The item containers (`ContentPresenter`) are initially invisible, and later become visible
2. The data items are not `UIElement`
3. The data items' equality remains the same before and after the visibility is changed
The automation tree is updated after the layout update. When the visibility is changed, the automation tree is invalidated and the automation tree update goes from the top to the bottom. The problem is that `ItemAutomationPeer.Children` is null while `_ancestorsInvalid` is false and `_childrenValid` is true, which prevents it from updating its children when the automation tree is updated.
1. When an `ItemAutomationPeer` first attempts to update its children, [`GetWrapperPeer`](https://github.com/dotnet/wpf/blob/6e7df620b641b1ad71f95d6645e3d699c21b7e4c/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Automation/Peers/ItemAutomationPeer.cs#L201) creates a `FrameworkElementAutomationPeer` for the `ContentPresenter`. However, the wrapper peer won't be able to find any child because the `ContentPresenter` is invisible and doesn't have any visual child. `_ancestorsInvalid` is false and `_childrenValid` is set to true after the automation tree update.
2. When the `ContentPresenter` become visible, the automation peers call `InvalidateAncestorsRecursive` during the layout update, but `_ancestorsInvalid` remains false for the `ItemAutomationPeer` because no other automation peers can reach it through the ancestry link. Things will be different if the data item is an `UIElement`, in which case the `UIElement`'s automation peer will be [obtained as a wrapper peer and the ancestry link is established via `EventSource`](https://github.com/dotnet/wpf/blob/6e7df620b641b1ad71f95d6645e3d699c21b7e4c/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Automation/Peers/ItemsControlAutomationPeer.cs#L193-L196).
3. In the subsequent automation tree update, the same `ItemAutomationPeer` is [obtained from the cache](https://github.com/dotnet/wpf/blob/6e7df620b641b1ad71f95d6645e3d699c21b7e4c/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Automation/Peers/ItemsControlAutomationPeer.cs#L182), which won't be possible if the data item's equality has changed. Since `_ancestorsInvalid` is false and `_childrenValid` is still true for the `ItemAutomationPeer`, [no more children update will happen](https://github.com/dotnet/wpf/blob/6e7df620b641b1ad71f95d6645e3d699c21b7e4c/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Automation/Peers/AutomationPeer.cs#L1496). It remains having no children
Contributor guide
Assessment
This issue has not been assessed yet.