本文参考了官方文档以及提供的示例代码(官方代码貌似有点误导,所以写了这一篇,并且文末有GayHub代码地址)
官方文档发布于20180806,说明NavigationView刚发布了没几天,还在开发中,所以里面的接口啥的随时会变! 随时会变! 随时会变! ,用在你的项目之前,请需要做好充足的心理准备。

不过他变任他变,效果还是非常诱人的。看一下效果图

2018 新版 NavigationView实现了汉堡菜单和顶部菜单的近乎完美结合,可以参考官方商店的设计风格,就是用的这个控件。
不过要用这个控件,也不是那么容易的,因为他需要Windows UI Library支持,而这个库不支持VS2015,必须是2017或者更高版本。详见 Getting started with the Windows UI Library
下面就说一下实现的完整步骤吧。
1.安装Microsoft.UI.Xaml
在NuGet中搜索Microsoft.UI.Xaml,需要勾选预发行版本。
然后需要将Microsoft.UI.Xaml添加到应用程序资源。
a. 如果你程序没有其他的程序资源,那么
- <Application>
- <Application.Resources>
- <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
- </Application.Resources>
- </Application>
b. 如果已存在其他的,那么只需要合并一下即可
- <Application>
- <Application.Resources>
- <ResourceDictionary>
- <ResourceDictionary.MergedDictionaries>
- <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
- </ResourceDictionary.MergedDictionaries>
- </ResourceDictionary>
- </Application.Resources>
- </Application>
2. 添加引用
在xaml文件中,添加
- xmlns:controls="using:Microsoft.UI.Xaml.Controls"
在.cs文件中添加
- using MUXC = Microsoft.UI.Xaml.Controls;
3. 编写Xaml界面
注意一下被注释掉的代码,你可以反注释一下,看看效果。
我这里主要是模仿一下商店的风格。
代码和官方的不大一样,主要是控件NavigationView,官方并没有在前面加上命名空间controls,我这里加上了。如果不加的话,编译器并不知道i用的是新版的控件。后台代码如果不加的话,会爆出N个错误。
详见我的Issue Developers and VS may get confused with namespace Microsoft.UI.Xaml.Controls and Windows.UI.Xaml.Controls
- <Grid>
- <VisualStateManager.VisualStateGroups>
- <VisualStateGroup>
- <VisualState>
- <VisualState.StateTriggers>
- <AdaptiveTrigger MinWindowWidth="{x:Bind NavView.CompactModeThresholdWidth}" />
- </VisualState.StateTriggers>
-
- <VisualState.Setters>
- <Setter Target="NavView.PaneDisplayMode" Value="Top"/>
- </VisualState.Setters>
- </VisualState>
- </VisualStateGroup>
- </VisualStateManager.VisualStateGroups>
-
- <controls:NavigationView x:Name="NavView"
- SelectionFollowsFocus="Enabled"
- ItemInvoked="NavView_ItemInvoked"
- IsSettingsVisible="True"
- Loaded="NavView_Loaded"
- BackRequested="NavView_BackRequested">
- <controls:NavigationView.MenuItems>
- <controls:NavigationViewItem Content="Home" x:Name="home" Tag="home">
- <controls:NavigationViewItem.Icon>
- <FontIcon Glyph=""/>
- </controls:NavigationViewItem.Icon>
- </controls:NavigationViewItem>
- <!--<controls:NavigationViewItemSeparator/>-->
- <!--<controls:NavigationViewItemHeader Content="Main pages"/>-->
- <controls:NavigationViewItem Icon="AllApps" Content="Apps" x:Name="apps" Tag="apps"/>
- <controls:NavigationViewItem Icon="People" Content="Games" x:Name="games" Tag="games"/>
- <controls:NavigationViewItem Icon="Video" Content="Movies and TVs" x:Name="moviestvs" Tag="moviestvs"/>
- <controls:NavigationViewItem Icon="Audio" Content="Music" x:Name="music" Tag="music"/>
- <controls:NavigationViewItem Icon="PhoneBook" Content="Books" x:Name="books" Tag="books"/>
- </controls:NavigationView.MenuItems>
-
- <!--<controls:NavigationView.AutoSuggestBox>
- <AutoSuggestBox x:Name="ASB" QueryIcon="Find"/>
- </controls:NavigationView.AutoSuggestBox>-->
-
- <!--<controls: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"/>
- <CommandBar Grid.Column="1"
- HorizontalAlignment="Right"
- VerticalAlignment="Top"
- DefaultLabelPosition="Right"
- Background="{ThemeResource SystemControlBackgroundAltHighBrush}">
- <AppBarButton Label="Refresh" Icon="Refresh"/>
- <AppBarButton Label="Import" Icon="Import"/>
- </CommandBar>
- </Grid>
- </DataTemplate>
- </controls:NavigationView.HeaderTemplate>-->
-
- <Frame x:Name="ContentFrame"/>
- </controls:NavigationView>
-
- <TextBlock Text="New Navigation View" FontSize="12" Margin="12,6,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
- </Grid>
4. 添加后台代码
首先添加一下必要的引用
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Windows.Foundation;
- using Windows.System;
- using Windows.UI.ViewManagement;
- using Windows.UI.Xaml;
- using Windows.UI.Xaml.Controls;
- using Windows.UI.Xaml.Input;
- using Windows.UI.Xaml.Navigation;
- using MUXC = Microsoft.UI.Xaml.Controls;
红色代码部分是我自己添加的,官方没有。
因为发现当初与设置界面的时候,拖动窗体改变大小,app会崩溃。目前已经提交官方pr,等待审核
- private Type currentPage;
- // List of ValueTuple holding the Navigation Tag and the relative Navigation Page
- private readonly IList<(string Tag, Type Page)> _pages = new List<(string Tag, Type Page)>
- {
- ("home", typeof(HomePage)),
- ("apps", typeof(AppsPage)),
- ("games", typeof(GamesPage)),
- ("moviestvs", typeof(MovieandTVPage)),
- ("music", typeof(MusicPage)),
- ("books", typeof(BooksPage)),
- };
- private void NavView_Loaded(object sender, RoutedEventArgs e)
- {
- // You can also add items in code behind
- //NavView.MenuItems.Add(new NavigationViewItemSeparator());
- //NavView.MenuItems.Add(new NavigationViewItem
- //{
- // Content = "Settings",
- // Icon = new SymbolIcon(Symbol.Folder),
- // Tag = "content"
- //});
- //_pages.Add(("content", typeof(SettingsPage)));
- ContentFrame.Navigated += On_Navigated;
- // NavView doesn't load any page by default: you need to specify it
- NavView_Navigate("home");
- // Add keyboard accelerators for backwards navigation
- var goBack = new KeyboardAccelerator { Key = VirtualKey.GoBack };
- goBack.Invoked += BackInvoked;
- this.KeyboardAccelerators.Add(goBack);
- // ALT routes here
- var altLeft = new KeyboardAccelerator
- {
- Key = VirtualKey.Left,
- Modifiers = VirtualKeyModifiers.Menu
- };
- altLeft.Invoked += BackInvoked;
- this.KeyboardAccelerators.Add(altLeft);
- }
- private void NavView_ItemInvoked(MUXC.NavigationView sender, MUXC.NavigationViewItemInvokedEventArgs args)
- {
- if (args.InvokedItem == null)
- return;
- if (args.IsSettingsInvoked)
- ContentFrame.Navigate(typeof(SettingsPage));
- else
- {
- // Getting the Tag from Content (args.InvokedItem is the content of NavigationViewItem)
- var navItemTag = NavView.MenuItems
- .OfType<MUXC.NavigationViewItem>()
- .First(i => args.InvokedItem.Equals(i.Content))
- .Tag.ToString();
- NavView_Navigate(navItemTag);
- }
- }
- private void NavView_Navigate(string navItemTag)
- {
- var item = _pages.First(p => p.Tag.Equals(navItemTag));
- if (currentPage == item.Page)
- return;
- ContentFrame.Navigate(item.Page);
- currentPage = item.Page;
- }
- private void NavView_BackRequested(MUXC.NavigationView sender, MUXC.NavigationViewBackRequestedEventArgs args)
- {
- On_BackRequested();
- }
- private void BackInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
- {
- On_BackRequested();
- args.Handled = true;
- }
- private bool On_BackRequested()
- {
- if (!ContentFrame.CanGoBack)
- return false;
- // Don't go back if the nav pane is overlayed
- if (NavView.IsPaneOpen &&
- (NavView.DisplayMode == MUXC.NavigationViewDisplayMode.Compact ||
- NavView.DisplayMode == MUXC.NavigationViewDisplayMode.Minimal))
- return false;
- ContentFrame.GoBack();
- return true;
- }
- private void On_Navigated(object sender, NavigationEventArgs e)
- {
- NavView.IsBackEnabled = ContentFrame.CanGoBack;
- if (ContentFrame.SourcePageType == typeof(SettingsPage))
- {
- // SettingsItem is not part of NavView.MenuItems, and doesn't have a Tag
- NavView.SelectedItem = (MUXC.NavigationViewItem)NavView.SettingsItem;
- }
- else
- {
- var item = _pages.First(p => p.Page == e.SourcePageType);
- NavView.SelectedItem = NavView.MenuItems
- .OfType<MUXC.NavigationViewItem>()
- .First(n => n.Tag.Equals(item.Tag));
- }
- }
如果你发现,代码中
- IList<(string Tag, Type Page)> _pages = new List<(string Tag, Type Page)>
报错,请在NuGet中安装 System.ValueTuple。
5. 延申扩展
商店还有一个效果,就是ScrollViewer向下拉的时候,再导航栏下面会有一个模糊的玻璃效果。

这个效果官方也做了说明,参考
不过我的程序中没做上去,因为 ScrollViewer的 CanContentRenderOutsideBounds 这个属性,再17134中并没有,应该在 Insider 17723出现了。
详见
但是不晓得这个属性,会不会照顾低版本系统呢。。。。。。又是一个坑!!!
我在HomePage里面注释了,预览版可以尝试一下。
- <ScrollViewer>
- <!--<ScrollViewer CanContentRenderOutsideBounds"True">-->
- <StackPanel>
- <TextBlock FontSize="30" TextWrapping="Wrap" Margin="0,100,0,0" IsColorFontEnabled="True" HorizontalAlignment="Center" VerticalAlignment="Center">
- <Run>For a seamless look+feel, if your app has pages that use a ScrollViewer and your navigation pane is top positioned, we recommend having the content scroll underneath the top nav pane.
- This can be achieved by setting the CanContentRenderOutsideBounds property on the relevant ScrollViewer to true.</Run>
- </TextBlock>
- <TextBlock Text="Home" FontSize="100" Margin="0,100,0,0" IsColorFontEnabled="True" HorizontalAlignment="Center" VerticalAlignment="Center"/>
- <TextBlock Text="Home" FontSize="100" Margin="0,100,0,0" IsColorFontEnabled="True" HorizontalAlignment="Center" VerticalAlignment="Center"/>
- <TextBlock Text="Home" FontSize="100" Margin="0,100,0,0" IsColorFontEnabled="True" HorizontalAlignment="Center" VerticalAlignment="Center"/>
- <TextBlock Text="Home" FontSize="100" Margin="0,100,0,0" IsColorFontEnabled="True" HorizontalAlignment="Center" VerticalAlignment="Center"/>
- <TextBlock Text="Home" FontSize="100" Margin="0,100,0,0" IsColorFontEnabled="True" HorizontalAlignment="Center" VerticalAlignment="Center"/>
- <TextBlock Text="Home" FontSize="100" Margin="0,100,0,0" IsColorFontEnabled="True" HorizontalAlignment="Center" VerticalAlignment="Center"/>
- </StackPanel>
- </ScrollViewer>
6. 再延申扩展一下
官方还说 Microsoft.UI.Xaml 支持更低的系统版本,最低支持到14393。但是在编译程序的时候,目标系统一定要是17134或者更高。
有低版本的系统,你可以在低版本上跑一下看看。反正半个月前是不能运行的,我测试过。
不过你的实际程序可能还有其他的官方库,那些有的可能最低是16299,所以14393也只是一个水中月而已。
7. GayHub项目地址
https://github.com/hupo376787/NewNavigationView
参考官方文档: