アプリ内で画面を遷移させる方法としてアプリにFrameを配置して、その中のPageを遷移させる方法が用意されています。ここではその方法を見ていきましょう。
開発環境
- .NET 6.0
 - WinUI 3.0 (Windows App SDK 1.0)
 

Frameを用いたPageのナビゲーション
アプリにおける画面遷移はFrameの中でPageを遷移させることが基本となります。Frameには画面遷移用のNavigateメソッドが用意されているのに加えて、画面遷移の履歴も保持するので、「戻る」「進む」の操作も可能になります。
また、PageのナビゲーションはNavigationViewなどの他のコントロールでも必要になるので、ぜひここで理解しておきましょう。
ナビゲーションの基本
FrameのNavigateメソッドに遷移させるPageを指定することでナビゲーションを実装することができます。例として、アプリ内のボタンからFrameに表示させるページをPage1 / Page2 / Page3に切り替えるアプリを作成してみましょう。

WinUI3アプリでデフォルトで生成されるMainWindowと、Frame内で遷移させるためのPage (Page1, Page2, Page3)を次のようにコーディングします。
MainWindow
MainWindow.xaml
<Window ...(省略)... >
    <StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Content="Page1" Click="Button_Click_1"/>
            <Button Content="Page2" Click="Button_Click_2"/>
            <Button Content="Page3" Click="Button_Click_3"/>
        </StackPanel>
        <Frame x:Name="contentFrame"/>
    </StackPanel>
</Window>
MainWindow.xaml.cs
public sealed partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
    }
    //Page1へナビゲーションする
    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        contentFrame.Navigate(typeof(Page1));
    }
    //Page2へナビゲーションする
    private void Button_Click_2(object sender, RoutedEventArgs e)
    {
        contentFrame.Navigate(typeof(Page2));
    }
    //Page3へナビゲーションする
    private void Button_Click_3(object sender, RoutedEventArgs e)
    {
        contentFrame.Navigate(typeof(Page3));
    }
}
MainWindowにButtonを3つ配置し、その下にFrameを配置します。Buttonをクリックしたときの動作として、FrameのNavigateメソッドでそれぞれPage1, Page2, Page3に遷移するように指定します。その際にNavigateの引数にはtypeof演算子でクラスの型を指定します。
さらにそれぞれのPageは以下のように定義しておきましょう。
Page1
Page1.xaml
<Page ...(略)...>
    <StackPanel Height="1000" HorizontalAlignment="Center">
        <TextBlock Text="Page 1" FontSize="40"/>
    </StackPanel>
</Page>
Page2
Page2.xaml
<Page ...(略)...>
    <StackPanel Height="1000" HorizontalAlignment="Center">
        <TextBlock Text="Page 2" FontSize="40"/>
    </StackPanel>
</Page>
Page3
Page3.xaml
<Page ...(略)...>
    <StackPanel Height="1000" HorizontalAlignment="Center">
        <TextBlock Text="Page 3" FontSize="40"/>
    </StackPanel>
</Page>
これでMainWindow内に配置したFrame内のPageのナビゲーションを行うことができました。
ページ遷移の「戻る」「進む」ボタンを実装する
Frameはナビゲーションの履歴をそれぞれBackStack / ForwardStackに保持しているので、「戻る」「進む」の機能を実装することができます。先ほどのサンプルアプリのMainWindowに以下の部分を追加してみましょう。
MainWindow
MainWindow.xaml
<Window ...(省略)... >
    <StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Content="<" Click="Button_Clike_Prev"/>
            <Button Content=">" Click="Button_Click_Next"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Content="Page1" Click="Button_Click_1"/>
            <Button Content="Page2" Click="Button_Click_2"/>
            <Button Content="Page3" Click="Button_Click_3"/>
        </StackPanel>
        <Frame x:Name="contentFrame"/>
    </StackPanel>
</Window>
MainWindow.xaml.cs
public sealed partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
    }
    ...(略)...
    //「戻る」ボタンの処理
    private void Button_Clike_Prev(object sender, RoutedEventArgs e)
    {
        if (contentFrame.CanGoBack) contentFrame.GoBack();
    }
    //「進む」ボタンの処理
    private void Button_Click_Next(object sender, RoutedEventArgs e)
    {
        if (contentFrame.CanGoForward) contentFrame.GoForward();
    }
}
MainWindow.xamlでは「戻る」「進む」のボタンを追加しています。MainWindow.xaml.csで先ほど追加した2つのボタンの処理を次のように書いています。
- 「戻る」ボタン:CanGoBackで戻れることを確認して、GoBackメソッドを実行
 - 「進む」ボタン:CanGoForwardで進めることを確認して、GoForwardメソッドを実行
 

ページの状態を保持する
デフォルトではページを遷移するとその内容はすべて初期化されてしまいます。上記の方法で「戻る」「進む」を実装しても、ページの内容までは保持されません。ここでは、以下のようにTextBoxに入力した内容がページ遷移しても保持できるようにしてみましょう。

ページの状態を保持できるようにするためにはPageのNavigationCacheModeをEnabledかRequiredにします。
Page2
Page2.xaml
<Page ...(略)...
    NavigationCacheMode="Enabled">
    <StackPanel Height="1000" HorizontalAlignment="Center">
        <TextBlock Text="Page 2" FontSize="40"/>
    </StackPanel>
</Page>
EnabledとRequiredの違いは以下のようになります。
パラメーターを渡してナビゲーションする
Frameを用いてPageを遷移させる際に、Pageにパラメーターを渡すことも可能です。例えばPageにその親要素を渡せば、Pageからその親要素にアクセスすることも可能になります。その場合はNavigateメソッドの第2引数に渡したいパラメーターを指定しましょう。渡されたパラメーターはPageがロードされるときに呼び出されるOnNavigatedToメソッドで受け取ることができます。
ここでは例として、先ほどのアプリの一番上にTextBoxを追加して、Page1を呼び出すとそのTextBoxの文字列をPage1にも表示するようにしてみます。

まず、MainWindowを次のように修正して、TextBoxを追加します。この際、MainWindowに配置するTextBoxはPage1からアクセスできるようにアクセス修飾子をpublicに設定してあります(本来はデータ・バインディングを用いた方がよいと思いますが、ここでは簡単のためにこのようにしています)。
MainWindow
MainWindow.xaml
<Window ...(省略)... >
    <StackPanel>
        <TextBox x:Name="textBox" x:FieldModifier="public"/>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Content="<" Click="Button_Clike_Prev"/>
            <Button Content=">" Click="Button_Click_Next"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Content="Page1" Click="Button_Click_1"/>
            <Button Content="Page2" Click="Button_Click_2"/>
            <Button Content="Page3" Click="Button_Click_3"/>
        </StackPanel>
        <Frame x:Name="contentFrame"/>
    </StackPanel>
</Window>
MainWindow.xaml.cs
public sealed partial class MainWindow : Window
{
    ...(略)...
    //Page1へナビゲーションする
    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        contentFrame.Navigate(typeof(Page1), this);
    }
    ...(略)...
}
Navigateメソッドの第2引数にthisとして自分自身を渡すことで、親要素を渡してナビゲーションしています。
続いて、Page1を次のように修正します。
Page1
Page1.xaml
<Page ...(略)...>
    <StackPanel Height="1000" HorizontalAlignment="Center">
        <TextBlock Text="Page 1" FontSize="40"/>
        <TextBlock x:Name="page1_TextBlock" FontSize="30"/>
    </StackPanel>
</Page>
Page1.xaml.cs
public sealed partial class Page1 : Page
{
    public Page1()
    {
        this.InitializeComponent();
    }
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        var parent = (MainWindow)e.Parameter;
        page1_TextBlock.Text = parent.textBox.Text;
    }
}
Pageがロードされると呼び出されるOnNavigatedToメソッドに渡されるNavigationEventArgsのParameterプロパティがナビゲーションで指定したパラメーターになるので、それを受け取ってTextBlockに表示しています。
			
			
			
			
			
			
			
			
コメント