點擊左側導覽列即可切換不同頁面

上一堂課我們完成了左側邊欄的顯示,左側邊欄內有一個 Frame,開啟主視窗時,這個 Frame 預設載入一張空白頁。但目前點擊左側選單項目,還無法切換到其他頁面,本節課我們實作此功能:點擊左側不同選單,切換顯示對應頁面(Page)。

最終執行效果

修改主視窗的選單項目

編輯 MainWindow.xaml

    <NavigationView x:Name="NavView" PaneDisplayMode="Left" SelectionChanged="OnNavViewSelectionChanged">
        
        <NavigationView.MenuItems>
            <NavigationViewItem Content="Dashboard" Tag="DashboardPage" Icon="Home"/>
            <NavigationViewItem Content="Analytics" Tag="AnalyticsPage" Icon="Account"/>
            <NavigationViewItem Content="Play" Tag="PlayPage" Icon="Play"/>
        </NavigationView.MenuItems>

        <Frame x:Name="MainFrame"/>

    </NavigationView>Code language: HTML, XML (xml)

主要異動說明:

  1. 在 NavigationView 新增選單切換事件:SelectionChanged="OnNavViewSelectionChanged",切換選單項目時會觸發此事件
  2. 新增並調整數個選單項目 <NavigationViewItem Content="Play" Tag="PlayPage" Icon="Play"/>。注意:Content 是選單顯示文字,Tag 的字串對應頁面名稱,Icon 是 WinUI 內建圖示。

新增三個空白頁:DashboardPage、AnalyticsPage、PlayPage

每個頁面的 Grid 容器內加入 TextBlock,填入不同文字,方便區分各頁面。

  <Grid>
      <TextBlock Text="Dashboard Page" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24"/>
  </Grid>Code language: HTML, XML (xml)
    <Grid>
        <TextBlock Text="Analytics Page" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24"/>
    </Grid>Code language: HTML, XML (xml)
    <Grid>
        <TextBlock Text="Play Page" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24"/>
    </Grid>Code language: HTML, XML (xml)

實作頁面切換函式

將游標移到 XAML 裡的事件函式 OnNavViewSelectionChanged 上方,按下快捷鍵 F12,Visual Studio 會自動產生此事件函式:標頭檔 .h 會自動建立函式宣告(無實作內容),同時在 .cpp 產生實作區塊,游標會自動跳轉到 cpp,不用手動修改標頭檔。

下方為 MainWindow.xaml.cpp 的完整實作程式碼

void winrt::AppWinui::implementation::MainWindow::OnNavViewSelectionChanged(winrt::Microsoft::UI::Xaml::Controls::NavigationView const& sender, 
winrt::Microsoft::UI::Xaml::Controls::NavigationViewSelectionChangedEventArgs const& args)
{
    // 取得使用者點選的選單項目
    auto selectedItem = args.SelectedItem().as<NavigationViewItem>();
    if (!selectedItem) return;

    // 讀取 Tag 字串
    hstring tag = unbox_value<hstring>(selectedItem.Tag());
    winrt::Windows::UI::Xaml::Interop::TypeName targetPage;

    // 依據 Tag 對應目標頁面型別
    if (tag == L"DashboardPage")
    {
        targetPage = xaml_typename<AppWinui::DashboardPage>();
    }
    else if (tag == L"AnalyticsPage")
    {
        targetPage = xaml_typename<AppWinui::AnalyticsPage>();
    }
    else if (tag == L"PlayPage")
    {
        targetPage = xaml_typename<AppWinui::PlayPage>();
    }
    else
    {
        return;
    }

    // 透過 Frame 切換頁面
    MainFrame().Navigate(targetPage);
}Code language: C++ (cpp)

另外在檔案開頭需要引入對應命名空間與標頭

using namespace Microsoft::UI::Xaml;

#include "BlankPage.xaml.h"
#include "DashboardPage.xaml.h"
#include "AnalyticsPage.xaml.h"
#include "PlayPage.xaml.h"
#include <winrt/Windows.UI.Xaml.Interop.h>
using namespace winrt::Microsoft::UI::Xaml::Controls;Code language: C++ (cpp)

事件函式重點程式解說

auto selectedItem = args.SelectedItem().as<NavigationViewItem>(); — 取得使用者當下點擊的選單項目

hstring tag = unbox_value<hstring>(selectedItem.Tag()); — 取出選單項目的 Tag 屬性,也就是我們在 XAML 設定、對應頁面名稱的字串。

winrt::Windows::UI::Xaml::Interop::TypeName targetPage; — 宣告變數存放頁面型別,做為後續 MainFrame().Navigate(targetPage); 頁面跳轉的參數。

    if (tag == L"DashboardPage")
    {
        targetPage = xaml_typename<AppWinui::DashboardPage>();
    }Code language: C++ (cpp)

依據不同 Tag 名稱,指派對應頁面型別給 targetPage。

MainFrame().Navigate(targetPage); — 執行頁面跳轉。

完整主視窗程式碼

#include "pch.h"
#include "MainWindow.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif

using namespace winrt;
using namespace Microsoft::UI::Xaml;

#include "BlankPage.xaml.h"
#include "DashboardPage.xaml.h"
#include "AnalyticsPage.xaml.h"
#include "PlayPage.xaml.h"
#include <winrt/Windows.UI.Xaml.Interop.h>
using namespace winrt::Microsoft::UI::Xaml::Controls;


// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

namespace winrt::AppWinui::implementation
{

    MainWindow::MainWindow()
    {
        InitializeComponent();

        MainFrame().Navigate(xaml_typename<AppWinui::BlankPage>());
    }

    int32_t MainWindow::MyProperty()
    {
        throw hresult_not_implemented();
    }

    void MainWindow::MyProperty(int32_t /* value */)
    {
        throw hresult_not_implemented();
    }
}

void winrt::AppWinui::implementation::MainWindow::OnNavViewSelectionChanged(winrt::Microsoft::UI::Xaml::Controls::NavigationView const& sender,
 winrt::Microsoft::UI::Xaml::Controls::NavigationViewSelectionChangedEventArgs const& args)
{
    // 取得使用者點選的選單項目
    auto selectedItem = args.SelectedItem().as<NavigationViewItem>();
    if (!selectedItem) return;

    // 讀取 Tag 字串
    hstring tag = unbox_value<hstring>(selectedItem.Tag());
    winrt::Windows::UI::Xaml::Interop::TypeName targetPage;

    // 依據 Tag 對應目標頁面型別
    if (tag == L"DashboardPage")
    {
        targetPage = xaml_typename<AppWinui::DashboardPage>();
    }
    else if (tag == L"AnalyticsPage")
    {
        targetPage = xaml_typename<AppWinui::AnalyticsPage>();
    }
    else if (tag == L"PlayPage")
    {
        targetPage = xaml_typename<AppWinui::PlayPage>();
    }
    else
    {
        return;
    }

    // 透過 Frame 切換頁面
    MainFrame().Navigate(targetPage);
}
Code language: C++ (cpp)

完整專案原始碼下載

點擊左側導覽列即可切換不同頁面

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *