UWP NavigationView:如何处理NavigationViewSelectionChangedEventArgs并修正选中指示器异常
This is a super common gotcha when adding conditional navigation logic to NavigationView—even if you block the page from switching, the control's selected state still updates, creating that confusing mismatch between what the UI shows and what's actually displayed. Here's how to fix it:
Solution 1: Revert SelectedItem in the SelectionChanged Event
The core idea is to track the previously selected item, and if your navigation block condition is met, manually set the SelectedItem back to the original value (while avoiding infinite event triggers):
private object _lastSelectedNavItem; private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) { // Initialize the tracked item on first load if (_lastSelectedNavItem == null) { _lastSelectedNavItem = sender.SelectedItem; return; } var targetItem = args.SelectedItem as NavigationViewItem; var currentItem = _lastSelectedNavItem as NavigationViewItem; // Your conditional check: block navigation from Page A to Page B if (currentItem?.Tag.ToString() == "PageA" && targetItem?.Tag.ToString() == "PageB") { // Skip your Frame.Navigate call here to block navigation // Revert the selected state to fix the visual mismatch sender.SelectedItem = _lastSelectedNavItem; return; } // Proceed with normal navigation if condition passes Frame.Navigate(Type.GetType(targetItem.Tag.ToString())); // Update the tracked selected item for future checks _lastSelectedNavItem = sender.SelectedItem; }
Solution 2: Handle It in MVVM (If You're Using That Pattern)
If you're working with a MVVM setup, handle the condition directly in your view model's SelectedNavItem property setter. This way, you never let the property (and thus the UI) update when navigation is blocked:
private object _selectedNavItem; public object SelectedNavItem { get => _selectedNavItem; set { var targetItem = value as NavigationViewItem; var currentItem = _selectedNavItem as NavigationViewItem; // Block navigation from Page A to Page B if (currentItem?.Tag.ToString() == "PageA" && targetItem?.Tag.ToString() == "PageB") { // Do not update the property or trigger navigation return; } // Update the property and notify the UI _selectedNavItem = value; OnPropertyChanged(nameof(SelectedNavItem)); // Execute your normal navigation logic NavigateToPage(targetItem.Tag.ToString()); } }
Why This Works
Both approaches make sure that when your navigation block condition triggers, the NavigationView's selected state stays tied to the actual displayed page. No more confusing users with a selected indicator that doesn't match the current page!
内容的提问来源于stack exchange,提问作者Jack

