Description
When a list page has rows whose primary command navigates to another page, drilling into a row and then navigating back (Backspace / Alt+Left / back button) resets the parent list's selection to the first item instead of restoring the row the user drilled in from. The previously highlighted row is lost on every back-navigation.
Steps to reproduce
- In a list page with several rows where a row's command opens a sub-page, arrow down to a row that isn't the first.
- Press Enter to navigate into that row's sub-page.
- Press Backspace (or Alt+Left / back button) to return.
- Selection is on the first row, not the row you came from.
Expected
Returning to a previously visited list page restores the selection (ideally scroll position too) to where it was when you navigated away.
Actual
Selection resets to index 0 every time.
Root cause (from main source)
This is currently by-design and already flagged as a TODO:
ShellPage.xaml.cs → GoBack() intentionally does not cache the VM being navigated away from. The comment there (~L500–502) reads:
// TODO: In the future we probably want a short cache (3-5?) of recent VMs in case the user re-navigates back to a recent page they visited ... so we don't have to reload it from scratch.
- On back-navigation,
ShellViewModel.LoadPageViewModelAsync re-initializes the page and CommandPalettePageViewModelFactory.TryCreatePageViewModel always constructs a new ListViewModel (no reuse path).
ListItemsView.OnViewModelChanged clears _stickySelectedItem when the VM swaps, and the fresh ListViewModel calls FetchItems(keepSelection: false), so selection falls back to the first item.
Because selection is matched by object reference (ProxyReferenceEqualityComparer) and the VM/sticky state is rebuilt from scratch, there is no extension-side workaround: IListItem exposes no stable id, IListPage exposes no initial-selection index, and RaiseItemsChanged(IncrementalRefresh) only affects the current VM, not the new one created on back-navigation.
Suggested fix
Implement the short recent-VM cache described in the existing TODO: cache recent PageViewModels keyed by IPage so back-navigation restores the existing ListViewModel (with its FilteredItems and _stickySelectedItem) instead of constructing a new one.
Environment
- Product: Command Palette (CmdPal)
- Microsoft.CmdPal.UI: 0.10.11181.0
- OS: Windows 11 24H2
Related
Description
When a list page has rows whose primary command navigates to another page, drilling into a row and then navigating back (Backspace / Alt+Left / back button) resets the parent list's selection to the first item instead of restoring the row the user drilled in from. The previously highlighted row is lost on every back-navigation.
Steps to reproduce
Expected
Returning to a previously visited list page restores the selection (ideally scroll position too) to where it was when you navigated away.
Actual
Selection resets to index 0 every time.
Root cause (from
mainsource)This is currently by-design and already flagged as a TODO:
ShellPage.xaml.cs→GoBack()intentionally does not cache the VM being navigated away from. The comment there (~L500–502) reads:ShellViewModel.LoadPageViewModelAsyncre-initializes the page andCommandPalettePageViewModelFactory.TryCreatePageViewModelalways constructs a newListViewModel(no reuse path).ListItemsView.OnViewModelChangedclears_stickySelectedItemwhen the VM swaps, and the freshListViewModelcallsFetchItems(keepSelection: false), so selection falls back to the first item.Because selection is matched by object reference (
ProxyReferenceEqualityComparer) and the VM/sticky state is rebuilt from scratch, there is no extension-side workaround:IListItemexposes no stable id,IListPageexposes no initial-selection index, andRaiseItemsChanged(IncrementalRefresh)only affects the current VM, not the new one created on back-navigation.Suggested fix
Implement the short recent-VM cache described in the existing TODO: cache recent
PageViewModels keyed byIPageso back-navigation restores the existingListViewModel(with itsFilteredItemsand_stickySelectedItem) instead of constructing a new one.Environment
Related