左側ナビゲーションバーの項目をクリックすると各ページが開きます

前回のレッスンで左サイドバーを表示する機能を実装しました。サイドバー内に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標準アイコンです。

空ページを3つ作成: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ファイルに実装用の雛形が作成されカーソルが移動します。利用者はヘッダーファイルを直接編集する必要はありません。

以下が 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()); XAMLで設定したTag属性の文字列(遷移先ページ名)を取得

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)

ソースコードダウンロードリンク

左側ナビゲーションバーの項目をクリックすると各ページが開きます

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です