mcpField
M
maui-shell-navigation

maui-shell-navigation

github.com/davidortinau開発17968 回インストール19 週間前に更新
リポジトリ

maui-shell-navigation について

.NET MAUI Shell のナビゲーション設計を扱う技能です。ページのオンデマンド生成、クエリを使ったデータ受け渡し、非同期の遷移ガード、ルートや遷移で起きやすい問題を説明します。

主な機能

  1. 01ContentTemplate によるページのオンデマンド生成
  2. 02IQueryAttributable によるデータ受け渡し
  3. 03ShellNavigationQueryParameters による複雑なオブジェクトの受け渡し
  4. 04非同期チェックによる遷移の保留
  5. 05一意なルート登録と遷移の await

活用シーン

  1. 01Shell 起動時に生成されるページを減らす
  2. 02遷移先に識別子やオブジェクトを渡す
  3. 03未保存の変更がある場合に離脱前の確認を行う
  4. 04ルート不一致や遷移の競合を調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/davidortinau/maui-skills --skill maui-shell-navigation

インストール後、Claude Code で/maui-shell-navigationを入力して読み込まれたか確認します。

同梱ファイルreferences/shell-navigation-api.md

詳細

.NET MAUI Shell ナビゲーション

重要な決定事項

ContentTemplate — 常に使用する

ページを必要に応じて作成するため、常に DataTemplate とともに ContentTemplate を使用してください。 Content を直接使用すると、Shell の初期化中にすべてのページが作成され、起動時間が長くなります。


<ShellContent ContentTemplate="{DataTemplate views:HomePage}" />


<ShellContent>
    <views:HomePage />
</ShellContent>
データの受け渡し — QueryProperty より IQueryAttributable を優先する

IQueryAttributable を使うと、すべてのパラメーターを一度の呼び出しで取得でき、ViewModel でも使用できます。

public class AnimalDetailsViewModel : ObservableObject, IQueryAttributable
{
    public void ApplyQueryAttributes(IDictionary<string, object> query)
    {
        if (query.TryGetValue("id", out var id))
            AnimalId = id.ToString();
    }
}

複雑なオブジェクトには、シリアル化を避けるため ShellNavigationQueryParameters を使用してください。

var parameters = new ShellNavigationQueryParameters
{
    { "animal", selectedAnimal }
};
await Shell.Current.GoToAsync("animaldetails", parameters);
ナビゲーションの制御 — 非同期デファーラルパターン

非同期のチェック(例:「未保存の変更を保存しますか?」)には GetDeferral() を使用してください。

protected override async void OnNavigating(ShellNavigatingEventArgs args)
{
    base.OnNavigating(args);
    if (hasUnsavedChanges && args.Source == ShellNavigationSource.Pop)
    {
        var deferral = args.GetDeferral();
        bool discard = await ShowConfirmationDialog();
        if (!discard)
            args.Cancel();
        deferral.Complete();
    }
}

よくある落とし穴

  1. ルート名の重複 — Routing.RegisterRoute は、すでに登録済みのルート名、またはビジュアル階層のルートと一致するルート名に対して ArgumentException をスローします。 アプリ全体で、すべてのルート名を一意にする必要があります。

  2. 相対ルートには登録が必要 — somepage が Routing.RegisterRoute で登録されていない限り、GoToAsync("somepage") は呼び出せません。ビジュアル階層のページには、代わりに絶対 // ルートを使用します。

  3. ページは必要に応じて作成される — ContentTemplate を使用する場合、ページのコンストラクターが実行されるのは、初めてナビゲーションしたときだけです。起動時にページが存在すると思い込まないでください。

  4. Tab.Stack は読み取り専用 — ナビゲーションスタックを直接操作することはできません。ナビゲーションの変更にはすべて GoToAsync を使用してください。

  5. GoToAsync は非同期 — 必ず await する — ナビゲーションをファイア・アンド・フォーゲットで実行すると、競合状態が発生し、エラーが通知されずに失敗することがあります。

    // ❌ Fire-and-forget — race conditions
    Shell.Current.GoToAsync("details");
    
    // ✅ Always await
    await Shell.Current.GoToAsync("details");
    
  6. ルート階層が重要 — 絶対ルートは、ビジュアル階層を通る完全なパス(//FlyoutItem/Tab/ShellContent)と一致する必要があります。パスが間違っていると、例外ではなく何も起こらない状態になります。

コメント