Round-trip the legacy WPF SessionSettings shape - #3766
Merged
Conversation
The new Avalonia SessionSettings reads WindowBounds as Left/Top/Width/Height
attributes and reads ActiveTreeViewPath node values raw, but ILSpy 10.x wrote
WindowBounds as a CSV element body ("L,T,W,H", the Rect TypeConverter format)
and \xNNNN-hex-escaped every non-letter-or-digit char in each Node value (so
"TomsToolbox.Wpf" round-tripped through XML as "TomsToolbox\x002EWpf"). On
first launch against an existing ILSpy.xml that means the saved window
position resets to the default and the selected tree node never restores --
the escaped path can't match a live node's ToString().
Accept the CSV body when the WindowBounds element has no attributes, and
decode \xNNNN escapes in tree-view node values. Both fall back through the
existing ParseDouble defaults if a piece is missing, so a corrupted entry
won't crash startup.
Lock the shape in with tests against the actual section the WPF host emits,
plus a forward-compat pair confirming LoadFromXml ignores unknown children
(DockLayout, SelectedSearchMode, ActiveAutoLoadedAssembly) and SaveToXml
never echoes them back -- the AvalonDock schema doesn't translate to the
Avalonia Dock host and would otherwise persist forever as dead state.
Assisted-by: Claude:claude-opus-4-7[1m]:Claude Code
Three follow-ups so the WPF-era ILSpy.xml survives a load-save-load cycle through the Avalonia host without losing data the user expected to keep. Preserve unknown children verbatim. LoadFromXml only interprets a known set of element names (KnownChildren) and stashes everything else; SaveToXml re-emits the stash after the known section. The AvalonDock <DockLayout> blob the WPF host writes is incompatible with the Avalonia Dock host and we don't want to interpret it, but blank- ing it on save would discard a WPF user's saved layout the first time they launched the Avalonia build. The same stash future-proofs older builds against fields added in newer ones. Emit the legacy on-disk shape on save. WindowBounds is written as a CSV body "L,T,W,H" (the WPF Rect TypeConverter format) instead of Left/Top/Width/Height attributes, and ActiveTreeViewPath <Node> values are \xNNNN-hex-escaped on write. With both directions of the conversion in this file a file written by the Avalonia build is still readable by an older ILSpy 10.x install, and the diff against a pre-existing ILSpy.xml stays small during the transition. Wire SelectedSearchMode and ActiveAutoLoadedAssembly. The WPF host persisted both: the search-pane mode picker so the user's last choice survives restarts, and the file path of the auto-loaded (dependency) assembly the saved tree-path lands in so the restore can re-open it before walking. The Avalonia code read both into properties that nothing wrote to. Now SearchPaneModel restores SelectedSearchMode on construction and writes back on change via SettingsService, and AssemblyTreeModel walks the selection's ancestor chain to find the owning AssemblyTreeNode, stores its LoadedAssembly.FileName when IsAutoLoaded, and re-opens that file (when it still exists) before RestoreSelectedPathAsync. Assisted-by: Claude:claude-opus-4-7[1m]:Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Avalonia rewrite changed the on-disk shape of
<SessionSettings>inILSpy.xml. Users upgrading from ILSpy 10.x silently lose their saved window position, restored tree-view selection, search-mode pick, and auto-loaded dependency on first launch — the new code reads the new shape only, ignores the legacy CSV/escape encodings, and writes a fresh subset that drops anything it doesn't recognise (including the AvalonDock<DockLayout>blob).This branch makes the load+save cycle non-lossy against a real WPF-era
ILSpy.xml.WindowBoundsaccepts both the newLeft/Top/Width/Heightattribute form and the WPF<WindowBounds>L,T,W,H</WindowBounds>CSV body;<ActiveTreeViewPath><Node>values are\xNNNN-hex-decoded on read and re-encoded on write. With both directions in the file an older ILSpy 10.x install can still read what the Avalonia build writes, and the diff against a pre-existingILSpy.xmlstays small during the transition.LoadFromXmlstashes any child whose name isn't inKnownChildren(e.g. the AvalonDock<DockLayout>blob, a future field added in a newer build);SaveToXmlre-emits them verbatim after the known section. We don't try to interpret the WPF dock layout — but writing zeros over it would discard the user's saved layout the first time they launched the Avalonia build.SelectedSearchModeandActiveAutoLoadedAssembly. Both were read into properties that nothing in the Avalonia code wrote to. NowSearchPaneModelrestores the saved mode on construction and writes back on change viaSettingsService;AssemblyTreeModelwalks the selection's ancestor chain to find the owningAssemblyTreeNode, stores itsLoadedAssembly.FileNamewhenIsAutoLoaded, and re-opens that file (when it still exists) beforeRestoreSelectedPathAsyncso the saved tree path can resolve into the dependency.The
EnableSmoothScrollingattribute is intentionally not re-added — that feature was removed in the rewrite (per maintainer note) and now flows throughDisplaySettings' own attribute-passthrough so it doesn't crash the load.Test plan
ILSpy.Tests/SessionSettingsTests.cscover: legacy CSVWindowBoundsbody,\xNNNNNodeunescape, the full WPF-era section shape, unknown-children load (ignored, no throw), unknown-children save (re-emitted verbatim), legacy WPF encodings on save (CSV + escaped nodes), and round-trip ofSelectedSearchMode+ActiveAutoLoadedAssembly. Full ILSpy.Tests suite still green (817 passing, 3 skipped — same asmaster).ILSpy.xmlcontaining the WPF-era SessionSettings shape from a real 10.x user (with<WindowBounds>882.6666666666666,342,750,550</WindowBounds>,\x002E-escaped<Node>values,<SelectedSearchMode>TypeAndMember</SelectedSearchMode>, and the AvalonDock<DockLayout>blob); closed viaWM_CLOSEsoSettingsService.Saveran; verified the file came back with<WindowBounds>882,342,750,550</WindowBounds>(CSV body, no attributes),TomsToolbox\x002EWpfstill escaped,<SelectedSearchMode>retained, and<DockLayout>preserved verbatim.🤖 Generated with Claude Code