WPF/DevExpress context menu returns 0 descendants via UIAutomation after first dismiss — stale AutomationPeer cache?
13:16 19 Jun 2026

We are automating a WPF application built on DevExpress (FrameworkECM) using FlaUI 4.x (UIA3 / UIAutomation). The application contains a data grid. Right-clicking a grid row opens a context menu with AutomationId = "GridContextMenu" containing 17 items, all ControlType = Button.

On the first right-click, FindAllDescendants() returns all 17 items correctly.

On most subsequent right-clicks (after the first dismiss), FindAllDescendants() returns 0 elements — even though the menu is visually fully populated on screen. However, after sufficient time has passed — particularly after a long operation lasting 30–90 seconds — the menu occasionally repopulates correctly again without any explicit intervention. This non-deterministic self-healing is consistent with a GC cycle collecting stale peers in the background.

Reproduction Steps

// First right-click — works
RightClickGridRow(window, row);
var menu = window.FindFirstDescendant(cf => cf.ByAutomationId("GridContextMenu"));
var items = menu.FindAllDescendants(); // returns 17 Button elements ✓
// Dismiss by clicking elsewhere
ClickAway();
// Second right-click — usually broken
RightClickGridRow(window, row);
menu = window.FindFirstDescendant(cf => cf.ByAutomationId("GridContextMenu"));
items = menu.FindAllDescendants(); // returns 0 on most subsequent opens ✗
// menu.FindAllChildren() also returns 0
// menu.IsOffscreen == false (it IS on screen)
// menu.AutomationId, menu.Name still readable — only descendants are missing

The trigger is the first dismiss and I have used both escape key and clicking away to close the menu. No documents need to be opened or closed — simply opening the menu once and clicking away or sending escape is enough to cause subsequent opens to return 0 descendants.

Key Observations

Both FindAllDescendants() and FindAllChildren() return 0 on most opens after the first dismiss.

The menu is visually fully populated — IsOffscreen is false, own properties are readable.

The staleness self-heals non-deterministically. After long processing operations (30–90 seconds), the menu sometimes returns all descendants correctly again on the next right-click with no explicit action taken.

A fresh UIA3Automation instance created before the right-click does not help.

What We've Tried

Approach Result
Fresh UIA3Automation before right-click No Improvement
Keyboard fallback (DOWN×N + ENTER) Works — current workaround
InvokePattern / .Click() on items No Improvement
Polling FindAllDescendants in loop while open No joy
Fresh UIA3Automation created after right-click while menu is open No joy
GC.Collect() in the automating process Testing

Questions

  1. Why does WPF/DevExpress return stale peers after the first dismiss? Is there a known caching mechanism (AutomationPeer.PeerFromProvider, ItemsControlAutomationPeer item cache) that explains this, or is DevExpress layering its own cache on top?

  2. Is there a way to force WPF to rebuild the peer tree without waiting for GC — from the automating process, without modifying the target app?

  3. Would GC.Collect() in the automating process affect GC pressure inside the target WPF process, or does it need to run inside the target?

  4. Has anyone hit this with DevExpress BarManager / GridContextMenu specifically and found a solution beyond keyboard fallback?

Environment: FlaUI 4.x UIA3, DevExpress WPF (version unknown), .NET 8, Windows, SYSTEM context RDP loopback session.

wpf devexpress ui-automation flaui