不一樣於Windows 8應用,Windows 10引入了「漢堡菜單」這一導航模式。說具體點,就拿官方的天氣應用來講,左上角三條橫槓的圖標外加一個SplitView控件組成的這一導航模式就叫「漢堡菜單」。git
本文討論的是如何實現官方的這同樣式(點擊後左側出現一個填充矩形),普通實現網上處處都是,有須要的朋友本身百度下吧。github
下面將介紹兩種不一樣的實現方法,第一種最簡單的方法是直接使用 Template 10 模板,第二種就是純手寫了。express
如有什麼不正確的地方望指正,你們共同討論。框架
1. Template 10 模板工具
使用 Template 10 模板能夠快速創建出應用的框架,簡單快捷。(幫助文檔 https://github.com/Windows-XAML/Template10/wiki )字體
要使用 Template 10 首先點擊 Visual Studio 「工具」菜單中的「擴展與更新」,搜索並安裝 Template 10(簡化搜索能夠直接輸入t10)this
安裝完成須要重啓,重啓後按下圖找到項目模板新建便可,使用很簡單,幫助文檔鏈接也在上方給出。spa
2. 手寫3d
先分析一下界面的構成,暫時不看標題欄,由一個設置了 Canvas.ZIndex 的 Button 和一個 SplitView 構成。SplitView.Pane 中又包含了兩個ListView(一級菜單和二級菜單)。ListView 裏的每一個 Item 又由 Rectangle,FontIcon,TextBlock 組成。見下圖雙向綁定
構成清晰以後實現的思路大概也就清晰了。下面給一個簡單的Demo,解決方案結構以下。(GitHub https://github.com/ZhangGaoxing/uwp-demo/tree/master/HamburgerDemo)
先建立一個NavMenuItem類
using System; using System.ComponentModel; using Windows.UI.Xaml; using Windows.UI.Xaml.Media; namespace HamburgerDemo { class NavMenuItem : INotifyPropertyChanged { // 記錄圖標字體 public FontFamily FontFamily { get; set; } // 圖標的C#轉義代碼 public string Icon { get; set; } // 標題 public string Label { get; set; } // 導航頁 public Type DestPage { get; set; } // 用於左側矩形的顯示 private Visibility selected = Visibility.Collapsed; public Visibility Selected { get { return selected; } set { selected = value; this.OnPropertyChanged("Selected"); } } // 雙向綁定,用於更新矩形是否顯示 public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
主頁面框架代碼
<Page x:Class="HamburgerDemo.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:HamburgerDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <!--菜單的數據模板--> <DataTemplate x:Key="DataTemplate"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="48" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Rectangle Fill="{ThemeResource SystemControlBackgroundAccentBrush}" Visibility="{Binding Selected, Mode=TwoWay}" HorizontalAlignment="Left" Width="5" Height="48" /> <FontIcon FontFamily="{Binding FontFamily}" Glyph="{Binding Icon}" Foreground="White" VerticalAlignment="Center" Margin="-2,0,0,0" Width="48" Height="48" /> <TextBlock Grid.Column="1" Text="{Binding Label}" Foreground="White" Margin="12,0,0,0" VerticalAlignment="Center" /> </Grid> </DataTemplate> <!--ListViewItem樣式定製--> <Style x:Key="NavMenuItemContainerStyle" TargetType="ListViewItem"> <Setter Property="MinWidth" Value="{StaticResource SplitViewCompactPaneThemeLength}"/> <Setter Property="Height" Value="48"/> <Setter Property="Padding" Value="0"/> <Setter Property="UseSystemFocusVisuals" Value="True" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListViewItem"> <ListViewItemPresenter ContentTransitions="{TemplateBinding ContentTransitions}" Control.IsTemplateFocusTarget="True" SelectionCheckMarkVisualEnabled="False" PointerOverBackground="{ThemeResource SystemControlHighlightListLowBrush}" PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}" SelectedBackground="Transparent" SelectedForeground="{ThemeResource SystemControlForegroundAccentBrush}" SelectedPointerOverBackground="{ThemeResource SystemControlHighlightListLowBrush}" PressedBackground="{ThemeResource SystemControlHighlightListMediumBrush}" SelectedPressedBackground="{ThemeResource SystemControlHighlightListMediumBrush}" DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" ContentMargin="{TemplateBinding Padding}"/> </ControlTemplate> </Setter.Value> </Setter> </Style> </Page.Resources> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <!--漢堡菜單開關--> <Button Name="PaneOpenButton" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Background="{Binding BackgroundColor}" Width="48" Height="48" VerticalAlignment="Top" Canvas.ZIndex="100" /> <SplitView Name="RootSplitView" DisplayMode="CompactOverlay" CompactPaneLength="48" OpenPaneLength="256" IsPaneOpen="True"> <SplitView.Pane> <Grid Background="#CC000000"> <Grid.RowDefinitions> <!--空出Button的高度--> <RowDefinition Height="48" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <!--一級菜單--> <ListView Name="NavMenuPrimaryListView" Grid.Row="1" VerticalAlignment="Top" SelectionMode="None" IsItemClickEnabled="True" ItemTemplate="{StaticResource DataTemplate}" ItemContainerStyle="{StaticResource NavMenuItemContainerStyle}"/> <!--二級菜單--> <ListView Name="NavMenuSecondaryListView" Grid.Row="2" VerticalAlignment="Bottom" SelectionMode="None" IsItemClickEnabled="True" ItemTemplate="{StaticResource DataTemplate}" ItemContainerStyle="{StaticResource NavMenuItemContainerStyle}" BorderBrush="{ThemeResource SystemControlBackgroundAccentBrush}" BorderThickness="0,1,0,0" /> </Grid> </SplitView.Pane> <SplitView.Content> <Frame Name="RootFrame" /> </SplitView.Content> </SplitView> </Grid> </Page>
主頁面的後臺代碼
using HamburgerDemo.Views; using System.Collections.Generic; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; namespace HamburgerDemo { public sealed partial class MainPage : Page { // 爲不一樣的菜單建立不一樣的List類型 private List<NavMenuItem> navMenuPrimaryItem = new List<NavMenuItem>( new[] { new NavMenuItem() { FontFamily = new FontFamily("Segoe MDL2 Assets"), Icon = "\xE10F", Label = "頁面1", Selected = Visibility.Visible, DestPage = typeof(Page1) }, new NavMenuItem() { FontFamily = new FontFamily("Segoe MDL2 Assets"), Icon = "\xE11A", Label = "頁面2", Selected = Visibility.Collapsed, DestPage = typeof(Page1) }, new NavMenuItem() { FontFamily = new FontFamily("Segoe MDL2 Assets"), Icon = "\xE121", Label = "頁面3", Selected = Visibility.Collapsed, DestPage = typeof(Page1) }, new NavMenuItem() { FontFamily = new FontFamily("Segoe MDL2 Assets"), Icon = "\xE122", Label = "頁面4", Selected = Visibility.Collapsed, DestPage = typeof(Page1) } }); private List<NavMenuItem> navMenuSecondaryItem = new List<NavMenuItem>( new[] { new NavMenuItem() { FontFamily = new FontFamily("Segoe MDL2 Assets"), Icon = "\xE713", Label = "設置", Selected = Visibility.Collapsed, DestPage = typeof(Page1) } }); public MainPage() { this.InitializeComponent(); // 綁定導航菜單 NavMenuPrimaryListView.ItemsSource = navMenuPrimaryItem; NavMenuSecondaryListView.ItemsSource = navMenuSecondaryItem; // SplitView 開關 PaneOpenButton.Click += (sender, args) => { RootSplitView.IsPaneOpen = !RootSplitView.IsPaneOpen; }; // 導航事件 NavMenuPrimaryListView.ItemClick += NavMenuListView_ItemClick; NavMenuSecondaryListView.ItemClick += NavMenuListView_ItemClick; // 默認頁 RootFrame.SourcePageType = typeof(Page1); } private void NavMenuListView_ItemClick(object sender, ItemClickEventArgs e) { // 遍歷,將選中Rectangle隱藏 foreach (var np in navMenuPrimaryItem) { np.Selected = Visibility.Collapsed; } foreach (var ns in navMenuSecondaryItem) { ns.Selected = Visibility.Collapsed; } NavMenuItem item = e.ClickedItem as NavMenuItem; // Rectangle顯示並導航 item.Selected = Visibility.Visible; if (item.DestPage != null) { RootFrame.Navigate(item.DestPage); } RootSplitView.IsPaneOpen = false; } } }
運行效果圖以下