diff --git a/ILSpy.Tests/AssemblyList/FindTreeNodeReferenceTests.cs b/ILSpy.Tests/AssemblyList/FindTreeNodeReferenceTests.cs
new file mode 100644
index 000000000..06cc134c8
--- /dev/null
+++ b/ILSpy.Tests/AssemblyList/FindTreeNodeReferenceTests.cs
@@ -0,0 +1,70 @@
+// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System.Threading.Tasks;
+
+using Avalonia.Headless.NUnit;
+
+using AwesomeAssertions;
+
+using ILSpy.TreeNodes;
+
+using NUnit.Framework;
+
+namespace ICSharpCode.ILSpy.Tests;
+
+///
+/// AssemblyTreeModel.FindTreeNode must resolve non-entity references -- a whole assembly
+/// (LoadedAssembly / MetadataFile) and a namespace -- to their tree nodes, not just entities.
+/// (Regression: the Avalonia port only handled entity references, so Assembly/Namespace search
+/// results and resource/namespace links silently did nothing.)
+///
+[TestFixture]
+public class FindTreeNodeReferenceTests
+{
+ [AvaloniaTest]
+ public async Task FindTreeNode_Resolves_Assembly_And_Namespace_References()
+ {
+ var (_, vm) = await TestHarness.BootAsync(3);
+ var atm = vm.AssemblyTreeModel;
+
+ var asmNode = atm.FindNode("System.Linq");
+ Assert.That(asmNode, Is.Not.Null);
+ var loaded = asmNode!.LoadedAssembly;
+
+ // LoadedAssembly reference -> its assembly node. (Custom TreeNodeAssertions shadows
+ // .Should() on tree nodes, so use Assert.That here.)
+ Assert.That(atm.FindTreeNode(loaded), Is.SameAs(asmNode),
+ "a LoadedAssembly reference resolves to its assembly node");
+
+ // MetadataFile reference -> the same assembly node.
+ var metadataFile = loaded.GetMetadataFileOrNull();
+ Assert.That(metadataFile, Is.Not.Null);
+ Assert.That(atm.FindTreeNode(metadataFile), Is.SameAs(asmNode),
+ "a MetadataFile reference resolves to its assembly node");
+
+ // Namespace reference -> its namespace node.
+ var compilation = loaded.GetTypeSystemOrNull();
+ Assert.That(compilation, Is.Not.Null);
+ var ns = compilation!.MainModule.RootNamespace.GetChildNamespace("System")?.GetChildNamespace("Linq");
+ Assert.That(ns, Is.Not.Null);
+
+ Assert.That(atm.FindTreeNode(ns), Is.InstanceOf(),
+ "a namespace reference resolves to its namespace node");
+ }
+}
diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.cs
index 01c49974e..9bf5789de 100644
--- a/ILSpy/AssemblyTree/AssemblyTreeModel.cs
+++ b/ILSpy/AssemblyTree/AssemblyTreeModel.cs
@@ -620,11 +620,71 @@ namespace ILSpy.AssemblyTree
case IMember member:
return FindMemberNode(assemblyListTreeNode, member);
+ case LoadedAssembly lasm:
+ return FindAssemblyNode(lasm);
+
+ case MetadataFile metadataFile:
+ return assemblyListTreeNode.Children.OfType()
+ .FirstOrDefault(a => a.LoadedAssembly.GetMetadataFileOrNull() == metadataFile);
+
+ case Resource resource:
+ return FindResourceNode(assemblyListTreeNode, resource, null);
+
+ case ValueTuple resourceWithName:
+ return FindResourceNode(assemblyListTreeNode, resourceWithName.Item1, resourceWithName.Item2);
+
+ case INamespace ns:
+ return FindNamespaceNode(assemblyListTreeNode, ns);
+
default:
return null;
}
}
+ // Resolves a resource (optionally a named sub-entry) to its tree node. Mirrors the previous
+ // version's AssemblyListTreeNode.FindResourceNode so resource search results / links navigate.
+ static ILSpyTreeNode? FindResourceNode(AssemblyListTreeNode root, Resource resource, string? name)
+ {
+ if (resource == null)
+ return null;
+ ILSpyTreeNode? resourceNode = null;
+ foreach (var node in root.Children.OfType())
+ {
+ if (!node.LoadedAssembly.IsLoaded)
+ continue;
+ node.EnsureLazyChildren();
+ foreach (var list in node.Children.OfType())
+ {
+ resourceNode = list.Children.OfType().FirstOrDefault(x => x.Resource == resource)
+ ?? (ILSpyTreeNode?)list.Children.OfType().FirstOrDefault(x => resource.Name.Equals(x.Text));
+ if (resourceNode != null)
+ break;
+ }
+ if (resourceNode != null)
+ break;
+ }
+ if (resourceNode == null || name == null || name.Equals(resourceNode.Text))
+ return resourceNode;
+ resourceNode.EnsureLazyChildren();
+ return resourceNode.Children.OfType().FirstOrDefault(x => name.Equals(x.Text)) ?? resourceNode;
+ }
+
+ // Resolves a namespace to its tree node within its contributing assembly. Mirrors the previous
+ // version's AssemblyListTreeNode.FindNamespaceNode.
+ static NamespaceTreeNode? FindNamespaceNode(AssemblyListTreeNode root, INamespace ns)
+ {
+ var module = ns.ContributingModules.FirstOrDefault();
+ if (module?.MetadataFile == null)
+ return null;
+ var assembly = root.Children.OfType()
+ .FirstOrDefault(a => a.LoadedAssembly.GetMetadataFileOrNull() == module.MetadataFile);
+ if (assembly == null)
+ return null;
+ assembly.EnsureLazyChildren();
+ return assembly.Children.OfType()
+ .FirstOrDefault(n => ns.FullName.Length == 0 || ns.FullName.Equals(n.Text));
+ }
+
static TypeTreeNode? FindTypeNode(AssemblyListTreeNode root, ITypeDefinition type)
{
var module = type.ParentModule?.MetadataFile;