しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

先日のデモアプリで戻り遷移時に OnNavigateTo メソッドが呼ばれない件

11/22 の最後のセッションで Windows Phone で戻り遷移をしても OnNavigateTo メソッドが呼ばれませんでした

これは NavigationService の単純な実装ミスでした;

    /// <summary>
    /// 戻る遷移
    /// </summary>
    public async Task GoBack()
    {
        await RootPage.PopAsync();

        var history = NavigationStack.Skip(1).FirstOrDefault();
        if (history != null)
        {
            PrepareNavigation(RootPage.CurrentPage, history.Parameter, NavigationMode.Poped);
        }
    }

NavigationService.GoBack() メソッドで戻る遷移の処理を記述していたのですが、戻るボタンで戻った場合ここを通らないので当然のように OnNavigateTo メソッドが呼ばれないという初歩的なミス・・・

修正は簡単で、

/// <summary>
/// 画面遷移サービス
/// </summary>
public class NavigationService : INavigationService
{
    ~ 中略 ~

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public NavigationService(IEventAggregator eventAggregator)
    {
        RootPage = new NavigationPage();
        RootPage.Popped += OnPoped;

        NavigationService.eventAggregator = eventAggregator;
        NavigationService.eventAggregator.GetEvent<AppStateChangedEvent>().Subscribe(this.OnAppStateChanged);
    }

    /// <summary>
    /// デフォルトの Page 生成メソッドを設定します
    /// </summary>
    /// <param name="factory">デフォルトの Page 生成メソッド</param>
    public static void SetPageFactiory(Func<Type, object> factory)
    {
        NavigationService.defaultPageFactory = factory;
    }

    /// <summary>
    /// 画面遷移用ルート画面を設定します
    /// </summary>
    /// <param name="rootPage">画面遷移用ルート画面</param>
    public static void SetRootPage(NavigationPage rootPage)
    {
        RootPage.Popped -= OnPoped;
        RootPage = rootPage;
        RootPage.Popped += OnPoped;

        if (rootPage.CurrentPage == null)
        {
            return;
        }

        PrepareNavigation(rootPage.CurrentPage, null, NavigationMode.Pushed);
    }

    ~ 中略 ~

    /// <summary>
    /// 戻る遷移
    /// </summary>
    public async Task GoBack()
    {
        await RootPage.PopAsync();
    }

    /// <summary>
    /// 戻る遷移時の処理
    /// </summary>
    /// <param name="sender">イベント発行者</param>
    /// <param name="e">イベント引数</param>
    private static void OnPoped(object sender, NavigationEventArgs e)
    {
        var history = NavigationStack.Skip(1).FirstOrDefault();
        if (history != null)
        {
            PrepareNavigation(RootPage.CurrentPage, history.Parameter, NavigationMode.Poped);
        }
    }
}

NavigationPage.Popped イベントを検知して画面遷移処理を仕掛けるだけです

f:id:matatabi_ux:20141124230449p:plain

戻る遷移の時も元の遷移パラメータが渡ってますね

というわけで GitHub のデモアプリコードの方も修正しておきました!

matatabi-ux/XamarinPrismNavigation · GitHub

アイテムが一度選択済みだとクリックしても反応しないというのは(今のところ)仕様です;

ビヘイビアを作れば解決しそうですが、それはまたの機会にしたいので