From 1da17ba9c03f861a5ab36b51c122eb1dabbbdccf Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Apr 2026 19:05:41 +0200 Subject: [PATCH] Assembly list switching in toolbar - Hold AssemblyListManager on AssemblyTreeModel and mirror its AssemblyLists collection so the toolbar combo can bind to it. - New ActiveListName ([ObservableProperty]); OnActiveListNameChanged loads the named list via the manager and rebuilds Root. - The "seed initial assemblies if empty" fallback now only triggers for the (Default) list, so switching to an empty user list doesn't auto-populate it. - MainToolBar AssemblyListComboBox bound to AssemblyLists / ActiveListName (TwoWay). Assisted-by: Claude:claude-opus-4-7:Claude Code --- .../AssemblyTree/AssemblyTreeModelTests.cs | 14 ++++++++ ILSpy/AssemblyTree/AssemblyTreeModel.cs | 36 +++++++++++++++++-- ILSpy/Views/MainToolBar.axaml | 11 +++--- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/ILSpy.Tests/AssemblyTree/AssemblyTreeModelTests.cs b/ILSpy.Tests/AssemblyTree/AssemblyTreeModelTests.cs index eb8f20d20..0051a4bdd 100644 --- a/ILSpy.Tests/AssemblyTree/AssemblyTreeModelTests.cs +++ b/ILSpy.Tests/AssemblyTree/AssemblyTreeModelTests.cs @@ -20,6 +20,8 @@ using Avalonia.Headless.NUnit; using AwesomeAssertions; +using ICSharpCode.ILSpyX; + using ILSpy.AppEnv; using ILSpy.AssemblyTree; @@ -46,4 +48,16 @@ public class AssemblyTreeModelTests model.AssemblyList.Should().NotBeNull("Initialize loads or creates the default AssemblyList."); model.Root.Should().NotBeNull("Initialize wires Root to an AssemblyListTreeNode of the loaded list."); } + + [AvaloniaTest] + public void Initialize_populates_AssemblyLists_and_selects_the_default() + { + var model = AppComposition.Current.GetExport(); + model.Initialize(); + + model.AssemblyLists.Should().NotBeEmpty( + "Initialize mirrors AssemblyListManager.AssemblyLists into the toolbar combo's source."); + model.ActiveListName.Should().Be(AssemblyListManager.DefaultListName, + "Initialize selects the (Default) list so the tree has something to render at startup."); + } } diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.cs index 3ea4677a4..9d8226f0b 100644 --- a/ILSpy/AssemblyTree/AssemblyTreeModel.cs +++ b/ILSpy/AssemblyTree/AssemblyTreeModel.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.ObjectModel; using System.Composition; using System.Runtime.Serialization; @@ -37,6 +38,8 @@ namespace ILSpy.AssemblyTree { public const string PaneContentId = "AssemblyTree"; + AssemblyListManager? listManager; + [ObservableProperty] [property: IgnoreDataMember] private SharpTreeNode? root; @@ -45,9 +48,16 @@ namespace ILSpy.AssemblyTree [property: IgnoreDataMember] private SharpTreeNode? selectedItem; + [ObservableProperty] + [property: IgnoreDataMember] + private string? activeListName; + [IgnoreDataMember] public AssemblyList? AssemblyList { get; private set; } + [IgnoreDataMember] + public ObservableCollection AssemblyLists { get; } = []; + public AssemblyTreeModel() { Id = PaneContentId; @@ -58,12 +68,32 @@ namespace ILSpy.AssemblyTree public void Initialize() { var settings = ILSpySettings.Load(); - var listManager = new AssemblyListManager(settings); + listManager = new AssemblyListManager(settings); listManager.CreateDefaultAssemblyLists(); - AssemblyList = listManager.LoadList(AssemblyListManager.DefaultListName); + SyncListNames(); + listManager.AssemblyLists.CollectionChanged += (_, _) => SyncListNames(); + + ActiveListName = AssemblyListManager.DefaultListName; + } + + void SyncListNames() + { + if (listManager == null) + return; + AssemblyLists.Clear(); + foreach (var name in listManager.AssemblyLists) + AssemblyLists.Add(name); + } + + partial void OnActiveListNameChanged(string? value) + { + if (listManager == null || string.IsNullOrEmpty(value)) + return; + + AssemblyList = listManager.LoadList(value); - if (AssemblyList.GetAssemblies().Length == 0) + if (AssemblyList.GetAssemblies().Length == 0 && value == AssemblyListManager.DefaultListName) LoadInitialAssemblies(AssemblyList); var rootNode = new AssemblyListTreeNode(AssemblyList); diff --git a/ILSpy/Views/MainToolBar.axaml b/ILSpy/Views/MainToolBar.axaml index e851fa604..eee07e1b5 100644 --- a/ILSpy/Views/MainToolBar.axaml +++ b/ILSpy/Views/MainToolBar.axaml @@ -2,16 +2,19 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:vm="using:ILSpy.ViewModels" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="30" - x:Class="ILSpy.MainToolBar"> + x:Class="ILSpy.MainToolBar" + x:DataType="vm:MainWindowViewModel"> - - +