UWP 2018 新版 NavigationView 嘗鮮

来源:https://www.cnblogs.com/hupo376787/archive/2018/08/10/9457066.html
-Advertisement-
Play Games

本文參考了官方文檔以及提供的示例代碼(官方代碼貌似有點誤導,所以寫了這一篇,並且文末有GayHub代碼地址) 官方文檔發佈於20180806,說明NavigationView剛發佈了沒幾天,還在開發中,所以裡面的介面啥的隨時會變! 隨時會變! 隨時會變! ,用在你的項目之前,請需要做好充足的心理準備 ...


本文參考了官方文檔以及提供的示例代碼(官方代碼貌似有點誤導,所以寫了這一篇,並且文末有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="&#xE10F;"/>
                    </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向下拉的時候,再導航欄下麵會有一個模糊的玻璃效果。

 

 

這個效果官方也做了說明,參考

Scroll content under top pane

不過我的程式中沒做上去,因為 ScrollViewer的  CanContentRenderOutsideBounds  這個屬性,再17134中並沒有,應該在 Insider 17723出現了。

詳見

Windows 10 SDK Preview Build 17723 available now! JULY 31, 2018 10:36 AM

 但是不曉得這個屬性,會不會照顧低版本系統呢。。。。。。又是一個坑!!!

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

 

 

參考官方文檔:

Windows UI Library (Preview version)

Navigation view (Preview version)

Windows 10 SDK Preview Build 17723 available now! JULY 31, 2018 10:36 AM


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • java中的多線程 Java是少數的幾種支持“多線程”的編程語言之一。大多數的編程語言只能順序運行多個單獨程式塊,無法同時運行不同的多個程式塊。java的“多線程”恰可以彌補這個缺憾,它可讓不同的程式塊併發執行,如此一來就可讓程式塊運行得更為流暢,同時也可達到多任務處理的目的。 先看一下單線程的情況 ...
  • 要瞭解Java垃圾收集機制,先理解JVM記憶體模式是非常重要的。今天我們將會瞭解JVM記憶體的各個部分、如何監控以及垃圾收集調優。 ...
  • sequence 序列 sequence(序列)是一組有順序的元素的集合 (嚴格的說,是對象的集合,但鑒於我們還沒有引入“對象”概念,暫時說元素)   序列可以包含一個或多個元素,也可以沒有任何元素。 我們之前所說的基本數據類型,都可以作為序列的元素。元素還可以是另一個序列,以及我們以後要 ...
  • 一、線程的狀態 線程一般具有五種狀態,即創建、就緒、運行、阻塞、終止。 它們之間的關係: 二、線程操作相關方法 1.設置和取得線程名稱。 如果不設置線程名稱,系統會自動分配線程名,一般格式為Thread-Xx 獲取當前線程用Thread.currentThread.getName(); 線程名稱的設 ...
  • 一, 時間模塊 1. 時間格式 時間戳格式 / float 數據類型 / 格林威治時間 (給機器看的) print(time.time()) 結構化時間 / 時間對象 (從給機器看轉換成給人看的過度) 能夠通過 . 屬性名來獲取對象中的值 print(time.strftime( ' %Y-%m-% ...
  • 1.導包其實就是在導包里的__init__文件以執行文件的sys.path為準(內部的導入是以頂級目錄作為開頭的,往後一層層找)1. 什麼是包 包就是一個包含有__init__.py文件的文件夾 包本質就是一種模塊,即包是用包導入使用的,包內部包含的文件也都是用來被導入使用 2 為何要用包 包是文件 ...
  • 這裡可以採用redirect以get形式向指定頁面發出get請求,指定頁面完成後會再次跳轉到redirect後邊指定的頁面 格式:需要請求的URL?redirect=請求URL完成後需要跳轉的地址 例如: response.sendRedirect("http://localhost:8080/te ...
  • 1 簡介 pipenv是requests作者的一個項目,整合了virtualenv、pip、pipfile, 用於更方便地為項目建立虛擬環境並管理虛擬環境中的第三方模塊。不需要再分別使用pip和virtualenv,直接使用pipenv即可。它使用Pipfile和Pipfile.lock 取代了re ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...