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

  1. 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.
  2. 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.
  3. 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.
  4. 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

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


AI-assisted analysis of unoplatform/uno@0418340488 (2026-08-13). Data as JSON: /api/errors/74f1d89e12f7fb58. Report an issue: GitHub.