From 53db111cd6e7a4b4791271ffe26a7cd09585d4ac Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 15 May 2026 17:38:50 +0200 Subject: [PATCH] =?UTF-8?q?Port=20#3705=20=E2=80=94=20async=20wait=20for?= =?UTF-8?q?=20load=20before=20refresh=20path-walk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-picked from master commits 4c8e606a6 + 4c347ef6b. Refresh (F5) on a selection inside a lazy-loaded resource tree (e.g. a .baml entry inside an embedded .resources file) was collapsing the selection back to the resources folder because FindNodeByPath ran before the assembly's metadata-file finished loading and the resource children hadn't materialised yet. Assisted-by: Claude:claude-opus-4-7:Claude Code --- ILSpy/AssemblyTree/AssemblyTreeModel.cs | 26 +++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.cs index 835759e83..d641d468e 100644 --- a/ILSpy/AssemblyTree/AssemblyTreeModel.cs +++ b/ILSpy/AssemblyTree/AssemblyTreeModel.cs @@ -728,14 +728,36 @@ namespace ILSpy.AssemblyTree } } - public void Refresh() => RefreshInternal(); + public void Refresh() => _ = RefreshInternalAsync(); - void RefreshInternal() + async Task RefreshInternalAsync() { if (AssemblyList == null || listManager == null) return; var path = GetPathForNode(SelectedItem); ShowAssemblyList(listManager.LoadList(AssemblyList.ListName)); + + // Ensure the assembly's children are realised before FindNodeByPath walks them. + // Lazy-loaded resource children (e.g. .baml entries inside an embedded + // .resources file) only materialise after the assembly's metadata-file is + // loaded; without this await the path-walk runs against an empty resource + // folder and the selection collapses to the resources folder itself (#3705 in + // the WPF tree). If the user navigated to a different node while we waited, + // honour that new selection rather than overwriting it with the pre-refresh path. + if (path is { Length: > 0 }) + { + var rootAssembly = AssemblyList.FindAssembly(path[0]); + if (rootAssembly != null) + { + var preAwaitSelection = SelectedItem; + try + { await rootAssembly.GetMetadataFileAsync().ConfigureAwait(true); } + catch { /* corrupt assembly — let FindNodeByPath best-match below */ } + if (!ReferenceEquals(SelectedItem, preAwaitSelection)) + return; + } + } + SelectNode(FindNodeByPath(path, returnBestMatch: true)); } }