{"record":{"id":"74f1d89e12f7fb58","repo":"unoplatform/uno","slug":"error-navigationviewitem-isselected-should-be-tru","errorCode":null,"errorMessage":"Error, NavigationViewItem.IsSelected should be true before raise SelectionChanged event","messagePattern":"Error, NavigationViewItem\\.IsSelected should be true before raise SelectionChanged event","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/SamplesApp/SamplesApp.Samples/Microsoft_UI_Xaml_Controls/NavigationViewTests/TopMode/NavigationViewTopNavOnlyPage.xaml.cs","lineNumber":157,"sourceCode":"\t\t}\n\n\t\tprivate void BackButtonVisibilityCheckbox_Checked(object sender, RoutedEventArgs e)\n\t\t{\n\t\t\tNavView.IsBackButtonVisible = NavigationViewBackButtonVisible.Visible;\n\t\t}\n\n\t\tprivate void BackButtonVisibilityCheckbox_Unchecked(object sender, RoutedEventArgs e)\n\t\t{\n\t\t\tNavView.IsBackButtonVisible = NavigationViewBackButtonVisible.Collapsed;\n\t\t}\n\n\t\tprivate void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs e)\n\t\t{\n\t\t\tvar container = (e.SelectedItemContainer as NavigationViewItem);\n\n\t\t\tif (container != null && !e.IsSettingsSelected && !container.IsSelected)\n\t\t\t{\n\t\t\t\tSelectionChangedResult.Text = \"Error, NavigationViewItem.IsSelected should be true before raise SelectionChanged event\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (e.SelectedItem is NavigationViewItem item)\n\t\t\t\t{\n\t\t\t\t\tSelectionChangedResult.Text = GetAndVerifyTheContainer(item.Content, container);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tSelectionChangedResult.Text = \"Null\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSelectionChangeRecommendedTransition.Text = RecommendedNavigationTransitionInfoToString(e.RecommendedNavigationTransitionInfo);\n\t\t}\n\n\t\tprivate void NavView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs e)\n\t\t{","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/unoplatform/uno/blob/04183404888ea21b4e5bfa3493e8d5f15e972c3a/src/SamplesApp/SamplesApp.Samples/Microsoft_UI_Xaml_Controls/NavigationViewTests/TopMode/NavigationViewTopNavOnlyPage.xaml.cs#L139-L175","documentation":"This is not a thrown exception but a contract-assertion message written by the NavigationView test/sample page. The NavigationView control guarantees (NavigationView.cs:2598-2600, Bug 17850504) that it selects the new item — setting NavigationViewItem.IsSelected = true via ChangeSelectStatusForItem (NavigationView.cs:3703) — BEFORE raising the SelectionChanged event (NavigationView.cs:2643). The handler at NavigationViewTopNavOnlyPage.xaml.cs:155 detects that this ordering was violated: it received a non-null SelectedItemContainer that is a NavigationViewItem, the Settings item was not the one selected, yet container.IsSelected was still false when the event fired.","triggerScenarios":"The message appears when NavigationView.SelectionChanged fires with e.SelectedItemContainer being a NavigationViewItem whose IsSelected is still false. This happens when the selected item's container was not realized at ChangeSelectStatusForItem time (NavigationView.cs:3697 returns null so the IsSelected setter at line 3703 is skipped) but WAS force-realized later for the event args (NavigationView.cs:2551, forceRealize:true) — i.e. a virtualization/realization race on the TopNav or overflow path, or an Uno Skia/WASM port gap where the container-lookup at selection time differs from native WinUI.","commonSituations":"Setting NavigationView.SelectedItem programmatically to an item whose container is not yet realized (e.g. right after adding MenuItems, or selecting an item in the overflow/TopNav area before layout); selecting items while the collection is being mutated; SelectionFollowsFocus or keyboard-nav paths that race with container realization; an Uno Platform regression in the NavigationView port (Skia/WASM targets) versus native WinUI; virtualization reclaiming the container between ChangeSelectStatusForItem and RaiseSelectionChangedEvent.","solutions":["Stop deriving selection state from NavigationViewItem.IsSelected inside the SelectionChanged handler — read e.SelectedItem, e.SelectedItemContainer, and e.IsSettingsSelected instead, which are the event-arg properties guaranteed correct at raise time.","If you must inspect the container's IsSelected, defer the read until after the event completes (DispatcherQueue.TryEnqueue) so any pending container realization / IsSelected propagation finishes.","Avoid setting SelectedItem to an item whose container is not yet realized: realize or scroll the container into view first (e.g. via ContainerContentChanging or waiting for Loaded) before assigning SelectedItem.","If reproducing only on Uno Skia/WASM and not on native WinUI, file a NavigationView framework bug — it is a violation of the documented event-ordering contract (Bug 17850504). The fix belongs in NavigationView.ChangeSelection: ensure ChangeSelectStatusForItem(nextItem, true) sets IsSelected even when the container must be force-realized for the event args."],"exampleFix":"// before\nprivate void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs e)\n{\n    var container = e.SelectedItemContainer as NavigationViewItem;\n    if (container != null && !e.IsSettingsSelected && !container.IsSelected)\n    {\n        Result.Text = \"Error, NavigationViewItem.IsSelected should be true...\";\n    }\n}\n\n// after\nprivate void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs e)\n{\n    var container = e.SelectedItemContainer as NavigationViewItem;\n    if (container == null)\n    {\n        Result.Text = \"Null\";\n        return;\n    }\n    // Use the event-arg properties that are guaranteed correct at raise time.\n    Result.Text = e.IsSettingsSelected ? \"Settings\" : container.Content?.ToString() ?? \"(empty)\";\n    if (!container.IsSelected)\n    {\n        // Framework contract (Bug 17850504) was violated — report as a framework bug,\n        // do not gate application logic on it.\n        System.Diagnostics.Debug.WriteLine(\"NavigationView: SelectionChanged raised before IsSelected set.\");\n    }\n}","handlingStrategy":"validation","validationCode":"private static bool IsSelectionChangedSafe(NavigationViewSelectionChangedEventArgs e)\n{\n    // The event-arg properties are always populated correctly at raise time.\n    // Do NOT trust container.IsSelected here.\n    return e.SelectedItemContainer is not null\n        && (e.IsSettingsSelected || e.SelectedItem is not null);\n}\n\nprivate void NavView_SelectionChanged(NavigationView s, NavigationViewSelectionChangedEventArgs e)\n{\n    if (!IsSelectionChangedSafe(e)) { Result.Text = \"Null\"; return; }\n    Result.Text = (e.SelectedItem as NavigationViewItem)?.Content?.ToString() ?? \"Settings\";\n}","typeGuard":"private static bool IsRealizedNavigationViewItem(object container)\n    => container is NavigationViewItem nvi && nvi.IsSelected;\n// Note: treat a false result as 'container not yet committed', NOT as 'not selected'.\n// Prefer e.SelectedItemContainer / e.SelectedItem over this guard.","tryCatchPattern":null,"preventionTips":["Never read NavigationViewItem.IsSelected inside SelectionChanged to drive app logic — it is set by the framework and may lag the event during container realization; use e.SelectedItem / e.SelectedItemContainer / e.IsSettingsSelected instead.","Before assigning NavigationView.SelectedItem programmatically, ensure the target container is realized (wait for Loaded or a ContainerContentChanging pass), especially for TopNav overflow items.","Do not mutate NavView.MenuItems (add/remove/clear) in the same synchronous block as a SelectedItem assignment — let layout realize containers first.","When porting or updating the NavigationView control itself, keep the ChangeSelectStatusForItem(nextItem, true) -> RaiseSelectionChangedEvent ordering intact (NavigationView.cs:2614 -> 2643) and verify the force-realize path sets IsSelected before raising.","If you depend on IsSelected, defer the check to DispatcherQueue.TryEnqueue so any pending IsSelected propagation completes."],"tags":["navigationview","winui","selection","event-ordering","isselected","uno-platform","virtualization"],"backgroundTag":null,"analyzedSha":"04183404888ea21b4e5bfa3493e8d5f15e972c3a","analyzedAt":"2026-08-13T21:08:11.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}