ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

c# – Windows 10 UWP,NavigationView在BackNavigation上更新选定的MenuItem

2019-06-22 11:52:08  阅读:416  来源: 互联网

标签:c xaml uwp navigationview


我正在编写一个Windows 10 UWP应用程序,并希望将NavigationView与BackRequested事件处理程序结合使用来处理后退导航,但是“GoBack”不会更新所选菜单项,这意味着当我使用后退按钮时所选择的菜单项不会改变.为了解决这个问题,我创建了一个丑陋的foreach循环,使用标记在后面导航中选择MenuItem.这有效,但我想知道是否有更优雅的方式来做到这一点,
GoBack不会触发ItemInvoked或SelectionChanged事件,所以我似乎无法使用它们.

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="&#xE10F;"/>
            </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片段:

        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;
    }

解决方法:

NavigationView菜单项本身可以执行除导航之外的其他操作,因此控件“没有理由”跟踪后退导航并相应地更新.但是,您可以设置MenuItems的标记,并将其用于ItemInvoked导航和后退导航.

NavigationView菜单项XAML将包含与目标页面类型名称完全匹配的标记:

<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>

现在,在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;

您还可以对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);

其中PageNamespace是一个字符串常量,其中包含存储页面的命名空间的名称.您可以使用nameof安全地更新它,例如:

private const string PageNamespace = nameof(MyApp.Pages);

我准备了一个演示这些建议的示例项目,你可以查看on my GitHub.

标签:c,xaml,uwp,navigationview
来源: https://codeday.me/bug/20190622/1263201.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有