[英]Windows 10 UWP, NavigationView Update Selected MenuItem on BackNavigation
I am writing an windows 10 UWP app and want to use the NavigationView in combination with the BackRequested
event handler to handle back navigation, however "GoBack" doesn't update the selected menu item, this means when I use the backbutton the selected menu item doesn't change. 我正在编写一个Windows 10 UWP应用程序,并希望将NavigationView与BackRequested
事件处理程序结合使用来处理后退导航,但是“GoBack”不会更新所选菜单项,这意味着当我使用后退BackRequested
时所选择的菜单项不会改变。 to fix this I have created an ugly foreach loop that selects the MenuItem
on back navigation using a tag. 为了解决这个问题,我创建了一个丑陋的foreach循环,使用标记在后面导航中选择MenuItem
。 This works but I was wondering if there is a more elegant way to do this, GoBack
doesn't fire the ItemInvoked
or SelectionChanged
event so I can't seem to be able to use those. 这有效,但我想知道是否有更优雅的方法来做到这一点, GoBack
不会触发ItemInvoked
或SelectionChanged
事件,所以我似乎无法使用它们。
MainPage.xaml MainPage.xaml中
<NavigationView x:Name="NavView"
CompactModeThresholdWidth="1920" ExpandedModeThresholdWidth="1920"
ItemInvoked="NavView_ItemInvoked"
SelectionChanged="NavView_SelectionChanged"
Loaded="NavView_Loaded"
Canvas.ZIndex="0">
<NavigationView.MenuItems>
<NavigationViewItem x:Uid="HomeNavItem" Content="Home" Tag="home">
<NavigationViewItem.Icon>
<FontIcon Glyph=""/>
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItemSeparator/>
</NavigationView.MenuItems>
<NavigationView.HeaderTemplate>
<DataTemplate>
<Grid Margin="24,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Style="{StaticResource TitleTextBlockStyle}"
FontSize="28"
VerticalAlignment="Center"
Text="Welcome"/>
</Grid>
</DataTemplate>
</NavigationView.HeaderTemplate>
<Frame x:Name="ContentFrame" Margin="24">
<Frame.ContentTransitions>
<TransitionCollection>
<NavigationThemeTransition/>
</TransitionCollection>
</Frame.ContentTransitions>
</Frame>
</NavigationView>
MainPage.xaml.cs snippet: MainPage.xaml.cs片段:
public MainPage()
{
this.InitializeComponent();
// initial page for ContentFrame
ContentFrame.Navigate(typeof(HomePage));
ContentFrame.Navigated += MainFrame_Navigated;
SystemNavigationManager.GetForCurrentView().BackRequested += MainPage_BackRequested;
}
private void MainPage_BackRequested(object sender, BackRequestedEventArgs e)
{
string tag = null;
if (!ContentFrame.CanGoBack) return;
e.Handled = true;
ContentFrame.GoBack();
if (ContentFrame.SourcePageType == typeof(HomePage))
{
tag = "home";
}
foreach (var navViewMenuItem in NavView.MenuItems)
{
if (navViewMenuItem is NavigationViewItem item)
{
if (item.Tag.Equals(tag)) item.IsSelected = true;
}
}
}
private void MainFrame_Navigated(object sender, NavigationEventArgs e)
{
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = ((Frame) sender).CanGoBack
? AppViewBackButtonVisibility.Visible
: AppViewBackButtonVisibility.Collapsed;
}
The NavigationView
menu items themselves could do other action than just navigation, hence the control has "no reason" to track the back navigation and update accordingly. NavigationView
菜单项本身可以执行除导航之外的其他操作,因此控件“没有理由”跟踪后退导航并相应地更新。 What you can do however to set the tag of your MenuItems
and use it for both ItemInvoked
navigation and for back navigation. 但是,您可以设置MenuItems
的标记,并将其用于ItemInvoked
导航和后退导航。
NavigationView
menu items XAML would include a Tag
that exactly matches the target page type name: NavigationView
菜单项XAML将包含与目标页面类型名称完全匹配的Tag
:
<NavigationView Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<NavigationView.MenuItems>
<NavigationViewItem Content="First" Tag="FirstPage">
<NavigationViewItem.Icon>
<FontIcon Glyph="1" FontFamily="Segoe UI"/>
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem Content="Second" Tag="SecondPage">
<NavigationViewItem.Icon>
<FontIcon Glyph="2" FontFamily="Segoe UI"/>
</NavigationViewItem.Icon>
</NavigationViewItem>
...
</NavigationView.MenuItems>
</NavigationView>
Now within the MainFrame_Navigated
method we can do the following: 现在,在MainFrame_Navigated
方法中,我们可以执行以下操作:
//get the Type of the currently displayed page
var pageName = AppFrame.Content.GetType().Name;
//find menu item that has the matching tag
var menuItem = AppNavigationView.MenuItems
.OfType<NavigationViewItem>()
.Where(item => item.Tag.ToString() == pageName)
.First();
//select
AppNavigationView.SelectedItem = menuItem;
You can also use similar approach for ItemInvoked
handler: 您还可以对ItemInvoked
处理程序使用类似的方法:
var invokedMenuItem = sender.MenuItems
.OfType<NavigationViewItem>()
.Where(item =>
item.Content.ToString() ==
args.InvokedItem.ToString())
.First();
var pageTypeName = invokedMenuItem.Tag.ToString();
var pageType = Assembly.GetExecutingAssembly().GetType($"{PageNamespace}.{pageTypeName}");
AppFrame.Navigate(pageType);
Where PageNamespace
is a string constant with the name of the namespace where your Pages
are stored. 其中PageNamespace
是一个字符串常量,其中包含存储Pages
的命名空间的名称。 You can use nameof
to keep it up to date safely, for example: 您可以使用nameof
安全地更新它,例如:
private const string PageNamespace = nameof(MyApp.Pages);
I have prepared a sample project that demonstrates these suggestions, you can check it out on my GitHub . 我准备了一个演示这些建议的示例项目,您可以在我的GitHub上查看。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.