アイキャッチ画像

.Net MAUIの「AppShell.xaml」でヘッダーをカスタマイズする方法

.Net MAUIの「AppShell.xaml」を利用してヘッダーのカスタマイズ方法を紹介していきます。当記事では、個別にカスタマイズする方法・共有にカスタマイズする方法を紹介していきます。

紹介環境

当記事では、以下のの環境を利用しています。

  • Visual Studio 2022
  • .Net 8

はじめに

当記事で利用する「AppShell.xaml」は、以下のように「App.xaml.cs」で「MainPage」にAppShellクラスを指定する必要があります。指定されていない場合、当記事の内容が利用できないため気をつけてください。

// 名前空間はプロジェクトごとに変わります。
namespace SampleApp;

public partial class App : Application
{
    public App()
    {
        InitializeComponent();
        // ↓ ここでAppShellを指定します
        MainPage = new AppShell();
    }
}

「AppShell.xaml」の詳細を知りたい方は、Microsoftで紹介されていますのでご確認ください。「AppShell.xaml」は、「Shell」を継承したコントロールになります。

.Net MAUIのヘッダーについて

.Net MAUIのヘッダーは、以下のように「ContentPage」のTitleプロパティの内容が表示されます。※「ContentPage」のTitleプロパティが未指定の場合、「AppShell.xaml」で指定されたTitleプロパティが反映されます。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SampleApp.Pages.Sample1"
             Title="サンプル">
    <VerticalStackLayout>
        <Label
            Text="ようこそ.Net MAUIへ!!"
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>

見た目は以下のようになります。

タイトルを変更したandroidの見た目
スマートフォン(Android)の場合

ヘッダーをカスタマイズする方法について

ヘッダーをカスタマイズするには、以下のように「Shell.TitleView」を利用します。

<Shell.TitleView>
    <!-- ヘッダーの内容が入ります。 -->
</Shell.TitleView>

「Shell.TitleView」の利用する場所によってページ別か全ページか選択できます。

カスタマイズを個別にする場合

ヘッダーのカスタマイズを個別にする場合、以下のように「ContentPage」に対して「Shell.TitleView」を利用します。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SampleApp.Pages.Sample1">

    <!-- ヘッダーのカスタマイズ -->
    <!-- ここから -->
    <Shell.TitleView>
        <HorizontalStackLayout>
            <Label
                Text="サンプル"></Label>
            <Button Text="クリック"></Button>
        </HorizontalStackLayout>
    </Shell.TitleView>
    <!-- ここまで -->

    <VerticalStackLayout>
        <Label
            Text="ようこそ.Net MAUIへ!!"
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>

見た目は以下のようになります。

ヘッダーをカスタマイズしたandroidの見た目(ページ別)
スマートフォン(Android)の場合

カスタマイズを共有する場合

ヘッダーのカスタマイズを共有する場合、以下のように「AppShell.xaml(Shell)」に対して「Shell.TitleView」を利用します。

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="SampleApp.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:SampleApp"
    xmlns:pages="clr-namespace:SampleApp.Pages"
    Shell.FlyoutBehavior="Disabled">

    <!-- ヘッダーのカスタマイズ -->
    <!-- ここから -->
    <Shell.TitleView>
        <HorizontalStackLayout>
            <Label
                Text="サンプル"></Label>
            <Button Text="クリック"></Button>
        </HorizontalStackLayout>
    </Shell.TitleView>
    <!-- ここまで -->

    <ShellContent
        Title="Sample1"
        ContentTemplate="{DataTemplate pages:Sample1}"
        Route="Sample1" />
</Shell>

見た目は以下のようになります。

ヘッダーをカスタマイズしたandroidの見た目(全ページ)
スマートフォン(Android)の場合

優先順位について

ヘッダーのカスタマイズには、優先順位が存在します。最も優先されるのは、個別のカスタマイズになります。

実際に試した例は、次のようになります。

以下のように「ContentPage」と「AppShell.xaml(Shell)」を用意します。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SampleApp.Pages.Sample1">

    <!-- ヘッダーのカスタマイズ -->
    <!-- ここから -->
    <Shell.TitleView>
        <HorizontalStackLayout>
            <Label
                Text="サンプル(ContentPage)"></Label>
            <Button Text="クリック"></Button>
        </HorizontalStackLayout>
    </Shell.TitleView>
    <!-- ここまで -->

    <VerticalStackLayout>
        <Label
            Text="ようこそ.Net MAUIへ!!"
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="SampleApp.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:SampleApp"
    xmlns:pages="clr-namespace:SampleApp.Pages"
    Shell.FlyoutBehavior="Disabled">

    <!-- ヘッダーのカスタマイズ -->
    <!-- ここから -->
    <Shell.TitleView>
        <HorizontalStackLayout>
            <Label
                Text="サンプル(AppShell)"></Label>
            <Button Text="クリック"></Button>
        </HorizontalStackLayout>
    </Shell.TitleView>
    <!-- ここまで -->

    <ShellContent
        Title="Sample1"
        ContentTemplate="{DataTemplate pages:Sample1}"
        Route="Sample1" />
</Shell>

見た目は以下のようになります。「サンプル(ContentPage)」が表示されているため、個別が優先されています。

優先順位の実行例
スマートフォン(Android)の場合

Titleプロパティを反映する方法について

Titleプロパティが存在する要素(ContentPage・Shell)のTitleプロパティを「Label」に反映していきます。反映する方法は、2種類存在します。

Bindingを利用する場合

Bindingを利用する場合は、以下のように実装します。

Titleプロパティが存在する要素(ContentPage・Shell)のNameプロパティを指定します。

Bindingを利用するためにContentPage・ShellなどのNameプロパティを指定

次に「Label」のTextプロパティにBindingでTitleを指定します。

タイトルに「サンプル」を指定してBindingで利用

実装してみた例が以下のようになります。例では「ContentPage」を利用しています。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SampleApp.Pages.Sample1"
             x:Name="contentPage"
             Title="サンプル">

    <Shell.TitleView>
        <HorizontalStackLayout>
            <Label
                BindingContext="{x:Reference contentPage}"
                Text="{Binding Title}"></Label>
            <Button Text="クリック"></Button>
        </HorizontalStackLayout>
    </Shell.TitleView>

    <VerticalStackLayout>
        <Label
            Text="ようこそ.Net MAUIへ!!"
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>

この方法は共有でも利用できますが、「AppShell.xaml(Shell)」のTitleプロパティで利用すると全ページのタイトルが同じにになってしまいます。そのため、個別で利用する方が向いています。

「AppShell.xaml(Shell)」のイベントを利用する場合

「AppShell.xaml(Shell)」のイベントを利用する場合は、以下のように実装します。

Titleプロパティを反映したい要素のNameプロパティを指定します。以下の例では「Label」のNameプロパティを指定しています。

AppShellクラスに以下の内容を追加します。Titleプロパティの指定個所は複数あるため優先順位を決めています。この方法では「ContentPage > ShellContent > Shell」の順になっています。つまり、「ContentPage」が一番優先されます。

protected override void OnNavigated(ShellNavigatedEventArgs args)
{
    base.OnNavigated(args);

    /*
     * 以下の優先順位でタイトルが指定されます。
     * ContentPage > ShellContent > Shell
     */
    label_title.Text = CurrentPage.Title ?? Current.CurrentItem?.Title ?? Title;
}

実装してみた例が以下のようになります。

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="SampleApp.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:SampleApp"
    xmlns:pages="clr-namespace:SampleApp.Pages"
    Shell.FlyoutBehavior="Disabled">

    <Shell.TitleView>
        <HorizontalStackLayout>
            <Label x:Name="label_title"></Label>
            <Button Text="クリック"></Button>
        </HorizontalStackLayout>
    </Shell.TitleView>

    <ShellContent
        Title="Sample1"
        ContentTemplate="{DataTemplate pages:Sample1}"
        Route="Sample1" />
</Shell>
namespace SampleApp;

public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();
    }

    protected override void OnNavigated(ShellNavigatedEventArgs args)
    {
        base.OnNavigated(args);
        label_title.Text = CurrentPage.Title ?? Current.CurrentItem?.Title ?? Title;
    }
}

この方法では、「AppShell.xaml(Shell)」の画面遷移時イベントを利用します。そのため、共有で利用できる方法になっています。

終わりに

ヘッダーのカスタマイズに「Shell.TitleView」を利用してみました。「Shell.TitleView」を利用することで、様々なヘッダーを作成できますので利用してみてください。