unoplatform/uno · error
Error, NavigationViewItem.IsSelected should be true before r
Error message
Error, NavigationViewItem.IsSelected should be true before raise SelectionChanged event
What it means
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.
Source
Thrown at src/SamplesApp/SamplesApp.Samples/Microsoft_UI_Xaml_Controls/NavigationViewTests/TopMode/NavigationViewTopNavOnlyPage.xaml.cs:157
}
private void BackButtonVisibilityCheckbox_Checked(object sender, RoutedEventArgs e)
{
NavView.IsBackButtonVisible = NavigationViewBackButtonVisible.Visible;
}
private void BackButtonVisibilityCheckbox_Unchecked(object sender, RoutedEventArgs e)
{
NavView.IsBackButtonVisible = NavigationViewBackButtonVisible.Collapsed;
}
private void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs e)
{
var container = (e.SelectedItemContainer as NavigationViewItem);
if (container != null && !e.IsSettingsSelected && !container.IsSelected)
{
SelectionChangedResult.Text = "Error, NavigationViewItem.IsSelected should be true before raise SelectionChanged event";
}
else
{
if (e.SelectedItem is NavigationViewItem item)
{
SelectionChangedResult.Text = GetAndVerifyTheContainer(item.Content, container);
}
else
{
SelectionChangedResult.Text = "Null";
}
}
SelectionChangeRecommendedTransition.Text = RecommendedNavigationTransitionInfoToString(e.RecommendedNavigationTransitionInfo);
}
private void NavView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs e)
{View on GitHub (pinned to 0418340488)
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.
Example fix
// before
private void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs e)
{
var container = e.SelectedItemContainer as NavigationViewItem;
if (container != null && !e.IsSettingsSelected && !container.IsSelected)
{
Result.Text = "Error, NavigationViewItem.IsSelected should be true...";
}
}
// after
private void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs e)
{
var container = e.SelectedItemContainer as NavigationViewItem;
if (container == null)
{
Result.Text = "Null";
return;
}
// Use the event-arg properties that are guaranteed correct at raise time.
Result.Text = e.IsSettingsSelected ? "Settings" : container.Content?.ToString() ?? "(empty)";
if (!container.IsSelected)
{
// Framework contract (Bug 17850504) was violated — report as a framework bug,
// do not gate application logic on it.
System.Diagnostics.Debug.WriteLine("NavigationView: SelectionChanged raised before IsSelected set.");
}
} Defensive patterns
Strategy: validation
Validate before calling
private static bool IsSelectionChangedSafe(NavigationViewSelectionChangedEventArgs e)
{
// The event-arg properties are always populated correctly at raise time.
// Do NOT trust container.IsSelected here.
return e.SelectedItemContainer is not null
&& (e.IsSettingsSelected || e.SelectedItem is not null);
}
private void NavView_SelectionChanged(NavigationView s, NavigationViewSelectionChangedEventArgs e)
{
if (!IsSelectionChangedSafe(e)) { Result.Text = "Null"; return; }
Result.Text = (e.SelectedItem as NavigationViewItem)?.Content?.ToString() ?? "Settings";
} Type guard
private static bool IsRealizedNavigationViewItem(object container)
=> container is NavigationViewItem nvi && nvi.IsSelected;
// Note: treat a false result as 'container not yet committed', NOT as 'not selected'.
// Prefer e.SelectedItemContainer / e.SelectedItem over this guard. Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to load animation.
- Failed load the animation
- Failed to load animation: {sourceUri}
- NotImplemented_GetFormattedString
- value
AI-assisted analysis of unoplatform/uno@0418340488 (2026-08-13).
Data as JSON: /api/errors/74f1d89e12f7fb58.
Report an issue: GitHub.