From 0abaa47de28d484840f8d3b20dc3efc63161e31a Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 23 Mar 2026 06:07:52 -0400 Subject: [PATCH] fix(ui): normalize TreeView expanded keys to strings for sessionStorage compatibility Keys from KeySelector (e.g. boxed int) were compared against string keys restored from sessionStorage, causing expansion state to be lost on navigation. All keys are now normalized to strings internally. --- .../Components/Shared/TreeView.razor | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/ScadaLink.CentralUI/Components/Shared/TreeView.razor b/src/ScadaLink.CentralUI/Components/Shared/TreeView.razor index b5ff6a1..0866097 100644 --- a/src/ScadaLink.CentralUI/Components/Shared/TreeView.razor +++ b/src/ScadaLink.CentralUI/Components/Shared/TreeView.razor @@ -32,7 +32,7 @@ else var key = KeySelector(item); var children = ChildrenSelector(item); var isBranch = HasChildrenSelector(item); - var isExpanded = _expandedKeys.Contains(key); + var isExpanded = _expandedKeys.Contains(KeyStr(key));
  • ? _items; - private HashSet _expandedKeys = new(); + private HashSet _expandedKeys = new(); + + /// Normalize any key object to a string for consistent comparison with sessionStorage. + private string KeyStr(object key) => key.ToString()!; private bool _initialExpansionApplied; private bool _storageLoaded; private TItem? _contextMenuItem; @@ -124,7 +127,7 @@ else var keys = System.Text.Json.JsonSerializer.Deserialize>(json); if (keys != null) { - _expandedKeys = new HashSet(keys); + _expandedKeys = new HashSet(keys); _initialExpansionApplied = true; } } @@ -159,7 +162,7 @@ else { if (InitiallyExpanded!(item)) { - _expandedKeys.Add(KeySelector(item)); + _expandedKeys.Add(KeyStr(KeySelector(item))); } var children = ChildrenSelector(item); @@ -172,9 +175,10 @@ else private void ToggleExpand(object key) { - if (!_expandedKeys.Remove(key)) + var k = KeyStr(key); + if (!_expandedKeys.Remove(k)) { - _expandedKeys.Add(key); + _expandedKeys.Add(k); } PersistExpandedState(); @@ -184,8 +188,7 @@ else { if (StorageKey != null) { - var keys = _expandedKeys.Select(k => k.ToString()!).ToList(); - var json = System.Text.Json.JsonSerializer.Serialize(keys); + var json = System.Text.Json.JsonSerializer.Serialize(_expandedKeys.ToList()); _ = JSRuntime.InvokeVoidAsync("treeviewStorage.save", StorageKey, json); } } @@ -232,7 +235,7 @@ else { if (HasChildrenSelector(item)) { - _expandedKeys.Add(KeySelector(item)); + _expandedKeys.Add(KeyStr(KeySelector(item))); } var children = ChildrenSelector(item); @@ -258,13 +261,14 @@ else public async Task RevealNode(object key, bool select = false) { var parentLookup = BuildParentLookup(); + var k = KeyStr(key); // If key is not in the tree at all, no-op - if (!parentLookup.ContainsKey(key)) + if (!parentLookup.ContainsKey(k)) return; // Walk up through ancestors - var current = key; + var current = k; while (parentLookup.TryGetValue(current, out var parentKey) && parentKey != null) { _expandedKeys.Add(parentKey); @@ -280,9 +284,9 @@ else StateHasChanged(); } - private Dictionary BuildParentLookup() + private Dictionary BuildParentLookup() { - var lookup = new Dictionary(); + var lookup = new Dictionary(); if (_items is { Count: > 0 }) { BuildParentLookupRecursive(_items, null, lookup); @@ -290,11 +294,11 @@ else return lookup; } - private void BuildParentLookupRecursive(IReadOnlyList items, object? parentKey, Dictionary lookup) + private void BuildParentLookupRecursive(IReadOnlyList items, string? parentKey, Dictionary lookup) { foreach (var item in items) { - var key = KeySelector(item); + var key = KeyStr(KeySelector(item)); lookup[key] = parentKey; var children = ChildrenSelector(item);