Skip to content

NavigationView: Moving selected item between groups leaves IsChildSelected=true on former ancestors #11927

Description

@YoungSx

Describe the bug

When using a hierarchical NavigationView, moving a currently selected item from one parent item/group to another leaves IsChildSelected set to true on its former ancestors.

As a result:

  • Collapsing an unrelated former parent moves the selection indicator to that group, even though SelectedItem still points to the original leaf in its new location.
  • Inserting a root item before the ancestor and selecting a top-level item can also leave the original parent marked as child-selected.

Why is this important?

In apps where items are dynamically categorized into hierarchical groups (e.g. grouping active/pending tasks, chat sessions, or folders), reparenting the currently selected item corrupts the ancestor selection visual states. When the user collapses the former group, it mistakenly claims the active selection indicator, misleading the user about which item is selected.

Steps to reproduce the bug

  1. Bind a left hierarchical NavigationView with two parent groups (e.g., Group A and Group B) containing child items in ObservableCollection.
  2. Expand both Group A and Group B.
  3. Select a child item under Group A (SelectedItem = child1). Notice Group A has IsChildSelected = true.
  4. Move child1 from Group A's child collection to Group B's child collection, and ensure SelectedItem is child1.
  5. Observe that Group A's container still has IsChildSelected = true.
  6. Collapse Group A.
  7. Observe that Group A's selection indicator becomes active, incorrectly displaying the selection indicator on Group A while SelectedItem remains child1 under Group B.

Actual behavior

Former ancestor containers retain IsChildSelected = true after the selected child item is reparented to another group. Collapsing the former parent displays a phantom selection indicator on that container.

Expected behavior

Former ancestors should have IsChildSelected cleared when their selected descendant is reparented or no longer under that ancestor. Only current active ancestors of SelectedItem should report IsChildSelected = true.

Screenshots

No response

NuGet package version

Microsoft.WindowsAppSDK 1.6+ (reproduced on Windows App SDK 2.4.0 / .NET 10 standalone native app)

Windows version

Windows 11 (24H2): Build 26100, Windows 11 (23H2): Build 22631

Additional context

In controls/dev/NavigationView/NavigationView.cpp#L2494-L2511 (OnSelectionModelSelectionChanged):
Ancestor unselection and cleanup resolves through the cached index path (m_lastSelectedItemIndexPath), which does not accurately track ancestor state changes when the item collection/hierarchy mutates or when items are moved between containers.

Cross-reference:

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions