Frame内でPageを遷移させる(ナビゲーション)【C#/XAML】

アプリ内で画面を遷移させる方法としてアプリに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メソッドを実行
「<」「>」でそれぞれPageを「戻る」「進む」ことができます。

ページの状態を保持する

デフォルトではページを遷移するとその内容はすべて初期化されてしまいます。上記の方法で「戻る」「進む」を実装しても、ページの内容までは保持されません。ここでは、以下のように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の違いは以下のようになります。

  • Enabled:キャッシュサイズがリミット内であれば、Pageのインスタンスが保持される
  • Required:Pageのインスタンスが常に保持される

パラメーターを渡してナビゲーションする

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メソッドに渡されるNavigationEventArgsParameterプロパティがナビゲーションで指定したパラメーターになるので、それを受け取ってTextBlockに表示しています。

スポンサーリンク

コメントを残す

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

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)